commit 0e90ba6a1baabb43622b290c5171b1bbb3008fe9 Author: kamil Date: Tue Apr 7 17:22:17 2026 +0300 initial commit diff --git a/e-502_users_guide.pdf b/e-502_users_guide.pdf new file mode 100644 index 0000000..09d94a9 Binary files /dev/null and b/e-502_users_guide.pdf differ diff --git a/e502_guide_extracted.txt b/e502_guide_extracted.txt new file mode 100644 index 0000000..c279a86 Binary files /dev/null and b/e502_guide_extracted.txt differ diff --git a/e502api.h b/e502api.h new file mode 100644 index 0000000..040d4ba --- /dev/null +++ b/e502api.h @@ -0,0 +1,1106 @@ +#ifndef E502API_H +#define E502API_H + +#include "x502api.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + @addtogroup const_list + @{ + *****************************************************************************/ +/** @brief + + , , + E502_EthSvcBrowseGetEvent() */ +typedef enum { + E502_ETH_SVC_EVENT_NONE = 0, /**< */ + E502_ETH_SVC_EVENT_ADD = 1, /**< */ + E502_ETH_SVC_EVENT_REMOVE = 2, /**< + */ + E502_ETH_SVC_EVENT_CHANGED = 3 /**< + */ +} t_e502_eth_svc_event; + +/** @} */ + +/***************************************************************************//** + @addtogroup type_list + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + , + E-502. + , + . + E502_EthConfigCreate() + E502_EthConfigFree(). + , + E502_EthConfigRead(), + + E502_EthConfigWrite() + *****************************************************************************/ +typedef struct st_e502_eth_config_state* t_e502_eth_config_hnd; + +/**************************************************************************//** + @brief + + + . + E502_EthSvcBrowseStart() E502_EthSvcBrowseStop() + *****************************************************************************/ +typedef struct st_e502_eth_svc_browse_context *t_e502_eth_svc_browse_hnd; +/**************************************************************************//** + @brief + + , + E-502. + . E502_EthSvcBrowseGetEvent() + E502_EthSvcRecordFree() + *****************************************************************************/ +typedef struct st_e502_eth_svc_record *t_e502_eth_svc_record_hnd; + +/** @} */ + +/***************************************************************************//** + @addtogroup func_open + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief E-502, USB + + E-502, + , . + + #X502_GETDEVS_FLAGS_ONLY_NOT_OPENED. + + @param[in] serials size*#X502_SERIAL_SIZE , + . + NULL, size=0, devcnt!=NULL, , + . + @param[in] size , + serial. + size . + 0, serials=NULL + @param[in] flags #t_x502_getdevs_flags, + . + @param[out] devcnt devcnt!=NULL, + E502 + ( size). + @return <0 - , + serials ( <= size) +*******************************************************************************/ +X502_EXPORT(int32_t) E502_UsbGetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size, + uint32_t flags, uint32_t *devcnt); + +/***************************************************************************//** + @brief E502_UsbGetSerialList, E16 + ******************************************************************************/ +X502_EXPORT(int32_t) E16_UsbGetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size, + uint32_t flags, uint32_t *devcnt); + +/***************************************************************************//** + @brief E-502, USB, + + E-502, USB, + . + + , + . + X502_Close() + ( #X502_ERR_DEVICE_ACCESS_DENIED). + + NULL , + , + . + , + #X502_ERR_DEVICE_NOT_FOUND. E-502, + , + , + . + + + X502_Close(). + + @param[in] hnd . + @param[in] serial + NULL. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_OpenUsb(t_x502_hnd hnd, const char *serial); + +/***************************************************************************//** + @brief E502_OpenUsb, E16 + ******************************************************************************/ +X502_EXPORT(int32_t) E16_OpenUsb(t_x502_hnd hnd, const char *serial); + +/***************************************************************************//** + @brief E-502 IP- + + E-502, Ethernet, + IPv4. + + + X502_Close(). + + @param[in] hnd . + @param[in] ip_addr IPv4 32- . + "a.b.c.d" ip_addr = (a<<24)|(b<<16)|(c<<8)|d. + @param[in] flags , . , 0. + @param[in] tout . + , . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_OpenByIpAddr(t_x502_hnd hnd, uint32_t ip_addr, + uint32_t flags, uint32_t tout); + +/***************************************************************************//** + @brief E-16 IP- + + E-16, Ethernet, + IPv4. + + + X502_Close(). + + @param[in] hnd . + @param[in] ip_addr IPv4 32- . + "a.b.c.d" ip_addr = (a<<24)|(b<<16)|(c<<8)|d. + @param[in] flags , . , 0. + @param[in] tout . + , . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E16_OpenByIpAddr(t_x502_hnd hnd, uint32_t ip_addr, + uint32_t flags, uint32_t tout); + + +/** @} */ + +/***************************************************************************//** + @addtogroup func_devrec + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief , E502 + + USB E-502 + + ( ). + + X502_FreeDevRecordList() ( + E502_UsbGetDevRecordsList() , , + , ). + + @param[out] list . + size . + NULL, size=0, devcnt!=NULL, , + . + @param[in] size , + list. + size , . + @param[in] flags #t_x502_getdevs_flags, + . + @param[out] devcnt , + E-502, + USB ( size). + @return <0 --- , + ( <= size). + + X502_FreeDevRecordList() , + , . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_UsbGetDevRecordsList(t_x502_devrec* list, uint32_t size, + uint32_t flags, uint32_t* devcnt) ; + + +/***************************************************************************//** + @brief E502_UsbGetDevRecordsList, , E16 + ******************************************************************************/ +X502_EXPORT(int32_t) E16_UsbGetDevRecordsList(t_x502_devrec* list, uint32_t size, + uint32_t flags, uint32_t* devcnt) ; + +/***************************************************************************//** + @brief E502_UsbGetDevRecordsList, , E14-440 + ******************************************************************************/ +X502_EXPORT(int32_t) E440_UsbGetDevRecordsList(t_x502_devrec* list, uint32_t size, + uint32_t flags, uint32_t* devcnt) ; + + +/***************************************************************************//** + @brief , E502 + + E502_UsbGetDevRecordsList, + idVendor idProduct USB . + + @param[in] idVendor idVendor + @param[in] idProduct idProduct + @return <0 --- , + ( <= size). + + X502_FreeDevRecordList() , + , . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_UsbGetDevRecordsList2(t_x502_devrec *list, uint32_t size, + uint32_t flags, uint32_t *devcnt, uint16_t idVendor, uint16_t idProduct); + +/***************************************************************************//** + @brief IP- + + , + Ethernet, IPv4 . , + . + X502_OpenByDevRecord(). + + @param[out] devrec , + . + @param[in] ip_addr IPv4 32- ( + ip_addr E502_OpenByIpAddr()). + @param[in] flags . , 0. + @param[in] tout . + + X502_OpenByDevRecord(). + , + X502_OpenByDevRecord() . + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_MakeDevRecordByIpAddr(t_x502_devrec *devrec, uint32_t ip_addr, + uint32_t flags, uint32_t tout); + +/***************************************************************************//** + @brief IP- + + E502_MakeDevRecordByIpAddr. + E16 *devname. + + @param[out] devrec , + . + @param[in] ip_addr IPv4 32- ( + ip_addr E502_OpenByIpAddr()). + @param[in] flags . , 0. + @param[in] tout . + + X502_OpenByDevRecord(). + , + X502_OpenByDevRecord() . + @param[in] devname "E16" "E502". + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_MakeDevRecordByIpAddr2(t_x502_devrec *devrec, uint32_t ip_addr, + uint32_t flags, uint32_t tout, char const *devname); + + +/***************************************************************************//** + @brief TCP- + + TCP- + E-502. , E-502 , + , + E-502 . + E-502, . + , + TCP-, . + , + , E502_EthDevRecordSetDataPort(). + + , + E502_MakeDevRecordByIpAddr() + X502_OpenByDevRecord(). + + @param[in] devrec , + TCP-. + @param[in] cmd_port TCP- + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthDevRecordSetCmdPort(t_x502_devrec *devrec, uint16_t cmd_port); + +/***************************************************************************//** + @brief TCP- + + E502_EthDevRecordSetCmdPort(), TCP- + , -. + + @param[in] devrec , + TCP-. + @param[in] data_port TCP- + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthDevRecordSetDataPort(t_x502_devrec *devrec, uint16_t data_port); + + + +/***************************************************************************//** + @brief + + , + Ethernet, , + . + , E-502, . + , + . + X502_OpenByDevRecord(). + + , .. + E502_EthSvcRecordFree(). + + @param[out] devrec , + . + @param[in] svc , + E502_EthSvcBrowseGetEvent(). + @param[in] flags . , 0. + @param[in] tout . + + X502_OpenByDevRecord(). + , + X502_OpenByDevRecord() . + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_MakeDevRecordByEthSvc(t_x502_devrec *devrec, t_e502_eth_svc_record_hnd svc, + uint32_t flags, uint32_t tout); + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_eth_config E502 + @{ +*******************************************************************************/ + + + + +/***************************************************************************//** + @brief IP- + + IP- . + , + Ethernet. + @param[in] hnd + @param[out] ip_addr IPv4 32- ( + ip_addr E502_OpenByIpAddr()). + + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_GetIpAddr(t_x502_hnd hnd, uint32_t *ip_addr); + + + +/***************************************************************************//** + @brief + + . + + -. + @return NULL , - +*******************************************************************************/ +X502_EXPORT(t_e502_eth_config_hnd) E502_EthConfigCreate(void); + +/***************************************************************************//** + @brief . + + , + E502_EthConfigCreate(). + , + ! + @param[in] cfg + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigFree(t_e502_eth_config_hnd cfg); + + + +/***************************************************************************//** + @brief + + , + E502_EthConfigCreate() + . + + , + . + + @param[in] hnd + @param[in,out] cfg + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigRead(t_x502_hnd hnd, t_e502_eth_config_hnd cfg); + + +/***************************************************************************//** + @brief + + , + . + + Ethernet-, + , + , + --- + . + + + ( , ). USB + + ( , ). + + @param[in] hnd + @param[in] cfg + @param[in] passwd + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigWrite(t_x502_hnd hnd, t_e502_eth_config_hnd cfg, + const char *passwd); + + +/***************************************************************************//** + @brief + + + , . + + @param[in] src_cfg , + . + @param[out] dst_cfg , + + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigCopy(t_e502_eth_config_hnd src_cfg, + t_e502_eth_config_hnd dst_cfg); + +/***************************************************************************//** + @brief , Ethernet + + , Ethernet . + , Ethernet . + @param[in] cfg + @param[out] en , 1, + --- 0 + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetEnabled(t_e502_eth_config_hnd cfg, uint32_t *en); + +/***************************************************************************//** + @brief Ethernet + + , Ethernet. + , Ethernet . + @param[in] cfg + @param[in] en 0 Ethernet, 1 --- + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetEnabled(t_e502_eth_config_hnd cfg, uint32_t en); +/***************************************************************************//** + @brief , IP + + , IP + (IP-, , ) DHCP/linklocal + . + @param[in] cfg + @param[out] en , + 1, --- 0 + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetAutoIPEnabled(t_e502_eth_config_hnd cfg, uint32_t *en); +/***************************************************************************//** + @brief IP + + , IP + (IP-, , ) DHCP/linklocal + . + @param[in] cfg + @param[in] en , + 1, --- 0 + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetAutoIPEnabled(t_e502_eth_config_hnd cfg, uint32_t en); +/***************************************************************************//** + @brief IP + + , IP + (IP-, , ) DHCP/linklocal + @param[in] cfg + @param[out] state IP + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetAutoIPState(t_e502_eth_config_hnd cfg, uint32_t *state); + +/***************************************************************************//** + @brief , MAC- + + , MAC-, , + MAC-. + + @param[in] cfg . + @param[out] en MAC-, + 1, ( ) --- 0 + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetUserMACEnabled(t_e502_eth_config_hnd cfg, uint32_t *en); +/***************************************************************************//** + @brief , MAC- + + , MAC-, , + MAC-. + + @param[in] cfg . + @param[in] en MAC-, + 1, ( ) --- 0 + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetUserMACEnabled(t_e502_eth_config_hnd cfg, uint32_t en); + +/***************************************************************************//** + @brief IP- + + IP-, + , IP-. + + @param[in] cfg . + @param[out] ip_addr IP- 32- ( + ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetIPv4Addr(t_e502_eth_config_hnd cfg, uint32_t *ip_addr); +/***************************************************************************//** + @brief IP- + + IP-, + , IP-. + + @param[in] cfg . + @param[in] ip_addr IP- 32- ( + ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetIPv4Addr(t_e502_eth_config_hnd cfg, uint32_t ip_addr); + +/***************************************************************************//** + @brief + + , + , IP-. + + @param[in] cfg . + @param[out] mask 32- ( + ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetIPv4Mask(t_e502_eth_config_hnd cfg, uint32_t *mask); +/***************************************************************************//** + @brief + + , + , IP-. + + @param[in] cfg . + @param[in] mask 32- + ( ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetIPv4Mask(t_e502_eth_config_hnd cfg, uint32_t mask); + +/***************************************************************************//** + @brief + + , + , IP-. + + @param[in] cfg . + @param[out] gate 32- ( + ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetIPv4Gate(t_e502_eth_config_hnd cfg, uint32_t *gate); +/***************************************************************************//** + @brief + + , + , IP-. + + @param[in] cfg . + @param[in] gate 32- + ( ip_addr E502_OpenByIpAddr()). + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetIPv4Gate(t_e502_eth_config_hnd cfg, uint32_t gate); + +/***************************************************************************//** + @brief MAC- + + MAC-, + (. + E502_EthConfigSetUserMACEnabled()). + + @param[in] cfg . + @param[out] mac MAC- + #X502_MAC_ADDR_SIZE + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetUserMac(t_e502_eth_config_hnd cfg, uint8_t *mac); +/***************************************************************************//** + @brief MAC- + + MAC-, + (. + E502_EthConfigSetUserMACEnabled()). + + @param[in] cfg . + @param[in] mac MAC- + #X502_MAC_ADDR_SIZE + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetUserMac(t_e502_eth_config_hnd cfg, const uint8_t *mac); +/***************************************************************************//** + @brief MAC- + + MAC- , + . + MAC-, -, + ( " ") + . + MAC- , + MAC- E502_EthConfigGetUserMac() + E502_EthConfigSetUserMACEnabled(). + MAC-. + + + @param[in] cfg . + @param[out] mac MAC- + #X502_MAC_ADDR_SIZE + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetFactoryMac(t_e502_eth_config_hnd cfg, uint8_t *mac); + + +/***************************************************************************//** + @brief + + . + . , + , . + . + + @param[in] cfg . + @param[out] name + UTF-8. #X502_INSTANCE_NAME_SIZE + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetInstanceName(t_e502_eth_config_hnd cfg, char *name); +/***************************************************************************//** + @brief + + , + . + + @param[in] cfg . + @param[in] name + UTF-8. ( ) + #X502_INSTANCE_NAME_SIZE . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetInstanceName(t_e502_eth_config_hnd cfg, const char *name); + + +/***************************************************************************//** + @brief + + , + E502_EthConfigWrite(). + + + E502_EthConfigWrite() + , . + , E502_EthConfigWrite() + . + + @param[in] cfg . + @param[in] new_passwd , + . + ( ) + #X502_PASSWORD_SIZE . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetNewPassword(t_e502_eth_config_hnd cfg, const char *new_passwd); + + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_misc + @{ +*******************************************************************************/ + + +/***************************************************************************//** + @brief E-502 + + + Cortex-M4 E-502 lboot. + + , + USB ( + USB) TFTP ( Ethernet). + + , + .. X502_Close(). + + 30 , + . + + . + + + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_SwitchToBootloader(t_x502_hnd hnd); + +/***************************************************************************//** + @brief + + Cortex-M4 E-502 + Flash-. + + , + . + + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_ReloadFPGA(t_x502_hnd hnd); + + + +/***************************************************************************//** + @brief Cortex-M4. + + + Cortex-M4. + + + @param[in] hnd . + @param[in] cmd_code - , . + @param[in] par , ( + ). + @param[in] snd_data , . + , + snd_size = 0. + @param[in] snd_size , snd_data + @param[out] rcv_data , , + . + , + , rcv_size = 0. + @param[in] rcv_size , , + . + rcv_data + . + @param[in] tout , + . + , + . + @param[out] recvd_size , + , + + ( , + rcv_size). , + + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_CortexExecCmd(t_x502_hnd hnd, uint32_t cmd_code, uint32_t par, + const uint8_t* snd_data, uint32_t snd_size, + uint8_t* rcv_data, uint32_t rcv_size, + uint32_t tout, uint32_t* recvd_size); + + +/** @} */ + + + +/***************************************************************************//** + @addtogroup func_eth_svc_browse + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + , + E-502, . + E502_EthSvcBrowseGetEvent(). + E502_EthSvcBrowseStop(). + () --- + Bonjour Windows Avahi Linux. + @param[out] pcontext , + . + @param[in] flags (). 0. + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcBrowseStart(t_e502_eth_svc_browse_hnd *pcontext, + uint32_t flags); + +/***************************************************************************//** + @brief + + + ( ) , + . + + . + ( , , + ) , . + + E502_EthSvcBrowseStart() + . + E-502, + E502_EthSvcBrowseGetEvent() #E502_ETH_SVC_EVENT_ADD, + . + + , + #E502_ETH_SVC_EVENT_NONE. + + + . + + @param[in] context , + E502_EthSvcBrowseStart(). + @param[out] svc #E502_ETH_SVC_EVENT_NONE, + + , . + + E502_EthSvcRecordFree(). + @param[out] event ( + #t_e502_eth_svc_event). + , + #E502_ETH_SVC_EVENT_NONE. + @param[out] flags + (). , + . + @param[in] tout ( ) + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcBrowseGetEvent(t_e502_eth_svc_browse_hnd context, + t_e502_eth_svc_record_hnd *svc , + uint32_t *event, uint32_t *flags, + uint32_t tout); + +/***************************************************************************//** + @brief + + , + , . , + E502_EthSvcBrowseStart() . + . + E502_EthSvcBrowseStart() + E502_EthSvcBrowseStop() . + + @param[in] context , + E502_EthSvcBrowseStart(). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcBrowseStop(t_e502_eth_svc_browse_hnd context); + + + +/***************************************************************************//** + @brief + + , + E502_EthSvcBrowseGetEvent(). + + @param[in] svc + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordFree(t_e502_eth_svc_record_hnd svc); + +/***************************************************************************//** + @brief + + . , + , + , E502_EthConfigSetInstanceName(). + , , , + UTF-8, ASCII + . + . + + @param[in] svc + @param[out] name #X502_INSTANCE_NAME_SIZE , + + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordGetInstanceName(t_e502_eth_svc_record_hnd svc, char *name); + +/***************************************************************************//** + @brief + + E-502, + , . + . + + @param[in] svc + @param[out] serial #X502_SERIAL_SIZE , + + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordGetDevSerial(t_e502_eth_svc_record_hnd svc, char *serial); + +/***************************************************************************//** + @brief + + ("E502" "E16"), + , . + . + + @param[in] svc + @param[out] devname #X502_DEVNAME_SIZE , + + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordGetDevName(t_e502_eth_svc_record_hnd rec, char *devname); + + +/***************************************************************************//** + @brief IP + + IP- E-502, + , . + , + . + + @param[in] svc + @param[out] addr IP- 32- ( + ip_addr E502_OpenByIpAddr()) + @param[in] tout + . + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordResolveIPv4Addr(t_e502_eth_svc_record_hnd svc, + uint32_t *addr, uint32_t tout); + + +/***************************************************************************//** + @brief , + + , + . + , , , + #E502_ETH_SVC_EVENT_REMOVE #E502_ETH_SVC_EVENT_CHANGED, , + (.. + E502_EthSvcBrowseGetEvent() , + , #E502_ETH_SVC_EVENT_ADD) + + @param[in] svc1 + @param[in] svc2 + @return . #X502_ERR_OK, + . +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthSvcRecordIsSameInstance(t_e502_eth_svc_record_hnd svc1, + t_e502_eth_svc_record_hnd svc2); + + +/***************************************************************************//** + @brief , + + E502_EthSvcBrowse...() + Ethernet + + ( ). + + X502_FreeDevRecordList(). + + @param[out] list . + size . + NULL, size=0, devcnt!=NULL, , + . + @param[in] size , + list. + size , . + @param[in] flags #t_x502_getdevs_flags, + . + @param[out] devcnt , + , Ethernet ( size). + @param[in] event_tout E502_EthSvcBrowseGetEvent() + @param[in] tcp_tout E502_MakeDevRecordByEthSvc() + @return <0 --- , + ( <= size). + + X502_FreeDevRecordList() , + , . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_SearchEthForDevicesIPv4Addr(t_x502_devrec* rec_list, uint32_t flags, uint32_t size, + uint32_t *devcount, uint32_t event_tout, uint32_t tcp_tout); + +typedef int32_t (APIENTRY *t_x502_search_eth_cb)(t_e502_eth_svc_record_hnd svc_hnd, void* param); + + +/***************************************************************************//** + @brief , + + E502_EthSvcBrowse...() + Ethernet + cb t_x502_search_eth_cb + + @param[in] cb callback-, . + @param[in] param callback-. + @param[in] flags #t_x502_getdevs_flags, + . + @param[in] event_tout E502_EthSvcBrowseGetEvent() + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) E502_SvcBrowseForDevices(t_x502_search_eth_cb cb, void *param, uint32_t flags, uint32_t event_tout); + +/***************************************************************************//** + @brief tcp + + , + + @param[in] cfg + @param[in] port + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetTcpCmdPort(t_e502_eth_config_hnd cfg, uint16_t port); +/***************************************************************************//** + @brief tcp + + , + + @param[in] cfg + @param[in] port + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigSetTcpDataPort(t_e502_eth_config_hnd cfg, uint16_t port); +/***************************************************************************//** + @brief tcp + + @param[in] cfg + @param[out] port , + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetTcpCmdPort(t_e502_eth_config_hnd cfg, uint16_t *port); +/***************************************************************************//** + @brief tcp + + @param[in] cfg + @param[out] port , + @return +*******************************************************************************/ +X502_EXPORT(int32_t) E502_EthConfigGetTcpDataPort(t_e502_eth_config_hnd cfg, uint16_t *port); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif // E502API_H diff --git a/gate_capture.cpp b/gate_capture.cpp new file mode 100644 index 0000000..cc6cb42 --- /dev/null +++ b/gate_capture.cpp @@ -0,0 +1,1040 @@ +#ifdef _WIN32 + #ifndef NOMINMAX + #define NOMINMAX + #endif +#endif + +#include + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4995) +#endif +#include "x502api.h" +#include "e502api.h" +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +constexpr uint32_t kLogicalChannelCount = 2; +constexpr uint32_t kStartInMask = (static_cast(1U) << 15U); + +struct Config { + std::string serial; + + uint32_t mode = X502_LCH_MODE_DIFF; + uint32_t range = X502_ADC_RANGE_5; + uint32_t ch1 = 2; + uint32_t ch2 = 3; + + uint32_t clock_mode = X502_SYNC_DI_SYN1_RISE; + + double clock_hz = 2000000.0; + double gate_hz = 20000.0; + + uint32_t windows = 1000; + uint32_t plot_windows = 50; + + uint32_t recv_block_words = 8192; + uint32_t recv_timeout_ms = 50; + uint32_t clock_wait_ms = 5000; + uint32_t window_wait_ms = 5000; + uint32_t input_buffer_words = 262144; + uint32_t input_step_words = 8192; + + bool pullup_syn1 = false; + bool pulldown_start_in = false; + + std::string csv_path = "gate_capture.csv"; + std::string svg_path = "gate_capture.svg"; +}; + +struct Frame { + double ch1 = 0.0; + double ch2 = 0.0; +}; + +struct WindowData { + std::vector ch1; + std::vector ch2; +}; + +struct AverageTrace { + std::vector ch1; + std::vector ch2; + std::vector counts; +}; + +[[noreturn]] void fail(const std::string& message) { + throw std::runtime_error(message); +} + +std::string trim_copy(const std::string& text) { + const auto first = text.find_first_not_of(" \t\r\n"); + if (first == std::string::npos) { + return {}; + } + const auto last = text.find_last_not_of(" \t\r\n"); + return text.substr(first, last - first + 1); +} + +bool starts_with(const std::string& value, const std::string& prefix) { + return value.rfind(prefix, 0) == 0; +} + +uint32_t parse_u32(const std::string& text, const std::string& field_name) { + const std::string clean = trim_copy(text); + char* end = nullptr; + const auto value = std::strtoull(clean.c_str(), &end, 0); + if ((end == clean.c_str()) || (*end != '\0') || (value > std::numeric_limits::max())) { + fail("Invalid integer for " + field_name + ": " + text); + } + return static_cast(value); +} + +double parse_double(const std::string& text, const std::string& field_name) { + const std::string clean = trim_copy(text); + char* end = nullptr; + const double value = std::strtod(clean.c_str(), &end); + if ((end == clean.c_str()) || (*end != '\0') || !std::isfinite(value)) { + fail("Invalid floating point value for " + field_name + ": " + text); + } + return value; +} + +uint32_t parse_range(const std::string& text) { + const double value = parse_double(text, "range"); + if (std::fabs(value - 10.0) < 1e-9) { + return X502_ADC_RANGE_10; + } + if (std::fabs(value - 5.0) < 1e-9) { + return X502_ADC_RANGE_5; + } + if (std::fabs(value - 2.0) < 1e-9) { + return X502_ADC_RANGE_2; + } + if (std::fabs(value - 1.0) < 1e-9) { + return X502_ADC_RANGE_1; + } + if (std::fabs(value - 0.5) < 1e-9) { + return X502_ADC_RANGE_05; + } + if (std::fabs(value - 0.2) < 1e-9) { + return X502_ADC_RANGE_02; + } + fail("Unsupported E-502 range: " + text); +} + +double range_to_volts(uint32_t range) { + switch (range) { + case X502_ADC_RANGE_10: + return 10.0; + case X502_ADC_RANGE_5: + return 5.0; + case X502_ADC_RANGE_2: + return 2.0; + case X502_ADC_RANGE_1: + return 1.0; + case X502_ADC_RANGE_05: + return 0.5; + case X502_ADC_RANGE_02: + return 0.2; + default: + fail("Unknown ADC range enum"); + } +} + +uint32_t parse_mode(const std::string& text) { + const std::string value = trim_copy(text); + if ((value == "diff") || (value == "differential")) { + return X502_LCH_MODE_DIFF; + } + fail("gate_capture supports only mode:diff"); +} + +uint32_t parse_clock_mode(const std::string& text) { + const std::string value = trim_copy(text); + if (value == "di_syn1_rise") { + return X502_SYNC_DI_SYN1_RISE; + } + if (value == "di_syn1_fall") { + return X502_SYNC_DI_SYN1_FALL; + } + fail("Only clock:di_syn1_rise or clock:di_syn1_fall are supported"); +} + +std::string clock_mode_to_string(uint32_t mode) { + switch (mode) { + case X502_SYNC_DI_SYN1_RISE: + return "di_syn1_rise"; + case X502_SYNC_DI_SYN1_FALL: + return "di_syn1_fall"; + default: + return "unknown"; + } +} + +std::string phy_pair_name(uint32_t phy_ch) { + return "X" + std::to_string(phy_ch + 1) + "-Y" + std::to_string(phy_ch + 1); +} + +void print_help(const char* exe_name) { + std::cout + << "Usage:\n" + << " " << exe_name << " [serial:SN] [mode:diff] [ch1:2] [ch2:3] [range:5]\n" + << " [clock:di_syn1_rise] [clock_hz:2000000] [gate_hz:20000]\n" + << " [windows:1000] [plot_windows:50]\n" + << " [csv:gate_capture.csv] [svg:gate_capture.svg]\n" + << " [recv_block:8192] [recv_timeout_ms:50]\n" + << " [clock_wait_ms:5000] [window_wait_ms:5000]\n" + << " [buffer_words:262144] [step_words:8192]\n" + << " [pullup_syn1] [pulldown_start_in]\n" + << "\n" + << "Fixed sync scheme for this utility:\n" + << " DI_SYN1 -> external ADC clock\n" + << " START_IN -> gate input read from synchronous digital input (DI16 mirror)\n" + << " streams -> start immediately; windows are cut in software while START_IN is high\n" + << "\n" + << "Defaults for E-502:\n" + << " mode:diff -> differential measurement only\n" + << " ch1:2, ch2:3 -> X3-Y3 and X4-Y4\n" + << " range:5 -> +/-5 V range\n" + << " clock:di_syn1_rise\n" + << " clock_hz:2000000 -> nominal external clock frequency for timing/plots\n" + << " gate_hz:20000 -> nominal square gate frequency for reporting\n" + << " windows:1000 -> capture 1000 complete gate windows\n" + << " plot_windows:50 -> overlay first 50 windows in SVG\n" + << "\n" + << "Differential physical channel mapping:\n" + << " 0..15 -> X1-Y1 .. X16-Y16\n" + << "\n" + << "Important behavior:\n" + << " The program ignores a gate that is already high at startup and waits for the next\n" + << " clean low->high transition. This avoids saving a partial first window.\n" + << "\n" + << "Recommended example:\n" + << " " << exe_name + << " clock:di_syn1_rise clock_hz:2000000 gate_hz:20000 windows:1000" + << " csv:gate_capture.csv svg:gate_capture.svg\n"; +} + +Config parse_args(int argc, char** argv) { + Config cfg; + + for (int i = 1; i < argc; ++i) { + const std::string arg = argv[i]; + if ((arg == "help") || (arg == "--help") || (arg == "-h")) { + print_help(argv[0]); + std::exit(0); + } + if (arg == "pullup_syn1") { + cfg.pullup_syn1 = true; + continue; + } + if (arg == "pulldown_start_in") { + cfg.pulldown_start_in = true; + continue; + } + if (starts_with(arg, "serial:")) { + cfg.serial = arg.substr(7); + continue; + } + if (starts_with(arg, "mode:")) { + cfg.mode = parse_mode(arg.substr(5)); + continue; + } + if (starts_with(arg, "range:")) { + cfg.range = parse_range(arg.substr(6)); + continue; + } + if (starts_with(arg, "ch1:")) { + cfg.ch1 = parse_u32(arg.substr(4), "ch1"); + continue; + } + if (starts_with(arg, "ch2:")) { + cfg.ch2 = parse_u32(arg.substr(4), "ch2"); + continue; + } + if (starts_with(arg, "clock:")) { + cfg.clock_mode = parse_clock_mode(arg.substr(6)); + continue; + } + if (starts_with(arg, "clock_hz:")) { + cfg.clock_hz = parse_double(arg.substr(9), "clock_hz"); + continue; + } + if (starts_with(arg, "sample_clock_hz:")) { + cfg.clock_hz = parse_double(arg.substr(16), "sample_clock_hz"); + continue; + } + if (starts_with(arg, "gate_hz:")) { + cfg.gate_hz = parse_double(arg.substr(8), "gate_hz"); + continue; + } + if (starts_with(arg, "windows:")) { + cfg.windows = parse_u32(arg.substr(8), "windows"); + continue; + } + if (starts_with(arg, "plot_windows:")) { + cfg.plot_windows = parse_u32(arg.substr(13), "plot_windows"); + continue; + } + if (starts_with(arg, "recv_block:")) { + cfg.recv_block_words = parse_u32(arg.substr(11), "recv_block"); + continue; + } + if (starts_with(arg, "recv_timeout_ms:")) { + cfg.recv_timeout_ms = parse_u32(arg.substr(16), "recv_timeout_ms"); + continue; + } + if (starts_with(arg, "clock_wait_ms:")) { + cfg.clock_wait_ms = parse_u32(arg.substr(14), "clock_wait_ms"); + continue; + } + if (starts_with(arg, "window_wait_ms:")) { + cfg.window_wait_ms = parse_u32(arg.substr(15), "window_wait_ms"); + continue; + } + if (starts_with(arg, "buffer_words:")) { + cfg.input_buffer_words = parse_u32(arg.substr(13), "buffer_words"); + continue; + } + if (starts_with(arg, "step_words:")) { + cfg.input_step_words = parse_u32(arg.substr(11), "step_words"); + continue; + } + if (starts_with(arg, "csv:")) { + cfg.csv_path = arg.substr(4); + continue; + } + if (starts_with(arg, "svg:")) { + cfg.svg_path = arg.substr(4); + continue; + } + fail("Unknown argument: " + arg); + } + + if (cfg.mode != X502_LCH_MODE_DIFF) { + fail("gate_capture supports only differential inputs"); + } + if ((cfg.ch1 >= X502_ADC_DIFF_CH_CNT) || (cfg.ch2 >= X502_ADC_DIFF_CH_CNT)) { + fail("Differential E-502 channels must be in range 0..15"); + } + if (cfg.ch1 == cfg.ch2) { + fail("ch1 and ch2 must be different differential pairs"); + } + if (cfg.clock_hz <= 0.0) { + fail("clock_hz must be > 0"); + } + if (cfg.gate_hz <= 0.0) { + fail("gate_hz must be > 0"); + } + if (cfg.windows == 0) { + fail("windows must be > 0"); + } + if (cfg.plot_windows == 0) { + fail("plot_windows must be > 0"); + } + if (cfg.recv_block_words == 0) { + fail("recv_block must be > 0"); + } + if (cfg.input_step_words == 0) { + cfg.input_step_words = cfg.recv_block_words; + } + if (cfg.input_buffer_words < cfg.recv_block_words) { + cfg.input_buffer_words = cfg.recv_block_words; + } + + return cfg; +} + +template +Fn load_symbol(HMODULE module, const char* name) { + const auto addr = GetProcAddress(module, name); + if (addr == nullptr) { + fail(std::string("GetProcAddress failed for symbol: ") + name); + } + return reinterpret_cast(addr); +} + +struct Api { + HMODULE x502_module = nullptr; + HMODULE e502_module = nullptr; + + decltype(&X502_Create) Create = nullptr; + decltype(&X502_Free) Free = nullptr; + decltype(&X502_Close) Close = nullptr; + decltype(&X502_GetErrorString) GetErrorString = nullptr; + decltype(&X502_GetDevInfo2) GetDevInfo2 = nullptr; + decltype(&X502_SetMode) SetMode = nullptr; + decltype(&X502_StreamsStop) StreamsStop = nullptr; + decltype(&X502_StreamsDisable) StreamsDisable = nullptr; + decltype(&X502_SetSyncMode) SetSyncMode = nullptr; + decltype(&X502_SetSyncStartMode) SetSyncStartMode = nullptr; + decltype(&X502_SetLChannelCount) SetLChannelCount = nullptr; + decltype(&X502_SetLChannel) SetLChannel = nullptr; + decltype(&X502_SetAdcFreqDivider) SetAdcFreqDivider = nullptr; + decltype(&X502_SetAdcInterframeDelay) SetAdcInterframeDelay = nullptr; + decltype(&X502_SetDinFreqDivider) SetDinFreqDivider = nullptr; + decltype(&X502_SetStreamBufSize) SetStreamBufSize = nullptr; + decltype(&X502_SetStreamStep) SetStreamStep = nullptr; + decltype(&X502_SetDigInPullup) SetDigInPullup = nullptr; + decltype(&X502_SetExtRefFreqValue) SetExtRefFreqValue = nullptr; + decltype(&X502_Configure) Configure = nullptr; + decltype(&X502_StreamsEnable) StreamsEnable = nullptr; + decltype(&X502_StreamsStart) StreamsStart = nullptr; + decltype(&X502_Recv) Recv = nullptr; + decltype(&X502_ProcessData) ProcessData = nullptr; + + decltype(&E502_OpenUsb) OpenUsb = nullptr; + + Api() { + x502_module = LoadLibraryA("x502api.dll"); + if (x502_module == nullptr) { + fail("Cannot load x502api.dll"); + } + e502_module = LoadLibraryA("e502api.dll"); + if (e502_module == nullptr) { + fail("Cannot load e502api.dll"); + } + + Create = load_symbol(x502_module, "X502_Create"); + Free = load_symbol(x502_module, "X502_Free"); + Close = load_symbol(x502_module, "X502_Close"); + GetErrorString = load_symbol(x502_module, "X502_GetErrorString"); + GetDevInfo2 = load_symbol(x502_module, "X502_GetDevInfo2"); + SetMode = load_symbol(x502_module, "X502_SetMode"); + StreamsStop = load_symbol(x502_module, "X502_StreamsStop"); + StreamsDisable = load_symbol(x502_module, "X502_StreamsDisable"); + SetSyncMode = load_symbol(x502_module, "X502_SetSyncMode"); + SetSyncStartMode = load_symbol(x502_module, "X502_SetSyncStartMode"); + SetLChannelCount = load_symbol(x502_module, "X502_SetLChannelCount"); + SetLChannel = load_symbol(x502_module, "X502_SetLChannel"); + SetAdcFreqDivider = load_symbol(x502_module, "X502_SetAdcFreqDivider"); + SetAdcInterframeDelay = load_symbol(x502_module, "X502_SetAdcInterframeDelay"); + SetDinFreqDivider = load_symbol(x502_module, "X502_SetDinFreqDivider"); + SetStreamBufSize = load_symbol(x502_module, "X502_SetStreamBufSize"); + SetStreamStep = load_symbol(x502_module, "X502_SetStreamStep"); + SetDigInPullup = load_symbol(x502_module, "X502_SetDigInPullup"); + SetExtRefFreqValue = load_symbol(x502_module, "X502_SetExtRefFreqValue"); + Configure = load_symbol(x502_module, "X502_Configure"); + StreamsEnable = load_symbol(x502_module, "X502_StreamsEnable"); + StreamsStart = load_symbol(x502_module, "X502_StreamsStart"); + Recv = load_symbol(x502_module, "X502_Recv"); + ProcessData = load_symbol(x502_module, "X502_ProcessData"); + + OpenUsb = load_symbol(e502_module, "E502_OpenUsb"); + } + + ~Api() { + if (e502_module != nullptr) { + FreeLibrary(e502_module); + } + if (x502_module != nullptr) { + FreeLibrary(x502_module); + } + } +}; + +std::string x502_error(const Api& api, int32_t err) { + const char* text = api.GetErrorString ? api.GetErrorString(err) : nullptr; + std::ostringstream out; + out << "err=" << err; + if ((text != nullptr) && (*text != '\0')) { + out << " (" << text << ")"; + } + return out.str(); +} + +void expect_ok(const Api& api, int32_t err, const std::string& what) { + if (err != X502_ERR_OK) { + fail(what + ": " + x502_error(api, err)); + } +} + +struct DeviceHandle { + const Api& api; + t_x502_hnd hnd = nullptr; + bool opened = false; + bool streams_started = false; + + explicit DeviceHandle(const Api& api_ref) : api(api_ref), hnd(api.Create()) { + if (hnd == nullptr) { + fail("X502_Create failed"); + } + } + + ~DeviceHandle() { + if (hnd != nullptr) { + if (streams_started) { + api.StreamsStop(hnd); + } + if (opened) { + api.Close(hnd); + } + api.Free(hnd); + } + } +}; + +void print_device_info(const t_x502_info& info) { + std::cout << "Device: " << info.name << "\n" + << "Serial: " << info.serial << "\n" + << "FPGA version: " << static_cast(info.fpga_ver >> 8) << "." + << static_cast(info.fpga_ver & 0xFF) << "\n" + << "PLDA version: " << static_cast(info.plda_ver) << "\n" + << "Board revision: " << static_cast(info.board_rev) << "\n" + << "MCU firmware: " << info.mcu_firmware_ver << "\n"; +} + +AverageTrace build_average_trace(const std::vector& windows) { + AverageTrace result; + std::size_t max_len = 0; + for (const auto& window : windows) { + max_len = std::max(max_len, std::min(window.ch1.size(), window.ch2.size())); + } + + result.ch1.assign(max_len, 0.0); + result.ch2.assign(max_len, 0.0); + result.counts.assign(max_len, 0U); + + for (const auto& window : windows) { + const std::size_t len = std::min(window.ch1.size(), window.ch2.size()); + for (std::size_t i = 0; i < len; ++i) { + result.ch1[i] += window.ch1[i]; + result.ch2[i] += window.ch2[i]; + ++result.counts[i]; + } + } + + for (std::size_t i = 0; i < max_len; ++i) { + if (result.counts[i] != 0U) { + result.ch1[i] /= static_cast(result.counts[i]); + result.ch2[i] /= static_cast(result.counts[i]); + } + } + + return result; +} + +std::string build_polyline_points(const std::vector& data, + double frame_freq_hz, + std::size_t max_samples, + double y_min, + double y_max, + double left, + double top, + double width, + double height) { + std::ostringstream out; + out << std::fixed << std::setprecision(3); + + const std::size_t len = data.size(); + const double max_time_us = (max_samples > 1) + ? ((static_cast(max_samples - 1) * 1e6) / frame_freq_hz) + : 1.0; + const double y_span = std::max(1e-12, y_max - y_min); + + for (std::size_t i = 0; i < len; ++i) { + const double time_us = static_cast(i) * 1e6 / frame_freq_hz; + const double x = left + (time_us / max_time_us) * width; + const double y = top + height - ((data[i] - y_min) / y_span) * height; + out << x << "," << y << " "; + } + return out.str(); +} + +void write_csv(const std::string& path, + const std::vector& windows, + double frame_freq_hz) { + std::ofstream file(path, std::ios::binary); + if (!file) { + fail("Cannot open CSV for writing: " + path); + } + + file << "window_idx,sample_in_window,time_us,ch1_v,ch2_v\n"; + file << std::fixed << std::setprecision(9); + + for (std::size_t w = 0; w < windows.size(); ++w) { + const std::size_t len = std::min(windows[w].ch1.size(), windows[w].ch2.size()); + for (std::size_t i = 0; i < len; ++i) { + const double time_us = static_cast(i) * 1e6 / frame_freq_hz; + file << w << "," << i << "," << time_us << "," << windows[w].ch1[i] << "," << windows[w].ch2[i] + << "\n"; + } + } +} + +void write_svg(const std::string& path, + const std::vector& windows, + double frame_freq_hz, + double nominal_range_v, + uint32_t plot_windows, + const Config& cfg) { + std::ofstream file(path, std::ios::binary); + if (!file) { + fail("Cannot open SVG for writing: " + path); + } + + const AverageTrace avg = build_average_trace(windows); + + std::size_t max_samples = 0; + double min_y = std::numeric_limits::infinity(); + double max_y = -std::numeric_limits::infinity(); + + for (const auto& window : windows) { + const std::size_t len = std::min(window.ch1.size(), window.ch2.size()); + max_samples = std::max(max_samples, len); + for (std::size_t i = 0; i < len; ++i) { + min_y = std::min(min_y, std::min(window.ch1[i], window.ch2[i])); + max_y = std::max(max_y, std::max(window.ch1[i], window.ch2[i])); + } + } + + if (!std::isfinite(min_y) || !std::isfinite(max_y) || (min_y == max_y)) { + min_y = -nominal_range_v; + max_y = nominal_range_v; + } else { + const double pad = std::max(0.1, (max_y - min_y) * 0.10); + min_y -= pad; + max_y += pad; + } + + if (max_samples < 2) { + max_samples = 2; + } + + const std::size_t overlay_count = std::min(plot_windows, windows.size()); + const double max_time_us = (static_cast(max_samples - 1) * 1e6) / frame_freq_hz; + + const double width = 1500.0; + const double height = 980.0; + const double left = 95.0; + const double right = 40.0; + const double top = 55.0; + const double gap = 85.0; + const double bottom = 75.0; + const double plot_width = width - left - right; + const double panel_height = (height - top - bottom - gap) / 2.0; + const double overlay_top = top; + const double average_top = top + panel_height + gap; + + auto write_panel = [&](double panel_top, const std::string& title) { + file << " \n"; + for (int i = 0; i <= 10; ++i) { + const double x = left + (plot_width * i / 10.0); + const double y = panel_top + (panel_height * i / 10.0); + file << " \n"; + file << " \n"; + } + + if ((0.0 >= min_y) && (0.0 <= max_y)) { + const double zero_y = panel_top + panel_height + - ((0.0 - min_y) / std::max(1e-12, max_y - min_y)) * panel_height; + file << " \n"; + } + + file << " " + << title << "\n"; + + file << std::fixed << std::setprecision(3); + for (int i = 0; i <= 10; ++i) { + const double x = left + (plot_width * i / 10.0); + const double t = max_time_us * i / 10.0; + const double y = panel_top + panel_height - (panel_height * i / 10.0); + const double v = min_y + (max_y - min_y) * i / 10.0; + + file << " " << t << "\n"; + file << " " << v << "\n"; + } + }; + + file << "\n"; + file << " \n"; + file << " E-502 gate capture\n"; + file << " " + << phy_pair_name(cfg.ch1) << ", " << phy_pair_name(cfg.ch2) + << ", clock=" << cfg.clock_hz << " Hz, gate=" << cfg.gate_hz << " Hz, windows=" << windows.size() + << "\n"; + + write_panel(overlay_top, "Overlay of first windows"); + write_panel(average_top, "Average waveform"); + + for (std::size_t i = 0; i < overlay_count; ++i) { + const std::size_t len = std::min(windows[i].ch1.size(), windows[i].ch2.size()); + if (len < 2) { + continue; + } + + const std::vector ch1(windows[i].ch1.begin(), windows[i].ch1.begin() + static_cast(len)); + const std::vector ch2(windows[i].ch2.begin(), windows[i].ch2.begin() + static_cast(len)); + + file << " \n"; + file << " \n"; + } + + if (avg.ch1.size() >= 2U) { + file << " \n"; + file << " \n"; + } + + file << " CH1\n"; + file << " \n"; + file << " CH2\n"; + file << " \n"; + + file << " time within window, us\n"; + file << " V\n"; + file << " V\n"; + file << "\n"; +} + +int run(const Config& cfg) { + Api api; + DeviceHandle device(api); + + const int32_t open_err = api.OpenUsb(device.hnd, cfg.serial.empty() ? nullptr : cfg.serial.c_str()); + expect_ok(api, open_err, "Open device over USB"); + device.opened = true; + + t_x502_info info{}; + expect_ok(api, api.GetDevInfo2(device.hnd, &info, sizeof(info)), "Get device info"); + print_device_info(info); + + expect_ok(api, api.SetMode(device.hnd, X502_MODE_FPGA), "Set FPGA mode"); + api.StreamsStop(device.hnd); + api.StreamsDisable(device.hnd, X502_STREAM_ALL_IN | X502_STREAM_ALL_OUT); + + expect_ok(api, api.SetSyncMode(device.hnd, cfg.clock_mode), "Set external clock on DI_SYN1"); + expect_ok(api, api.SetSyncStartMode(device.hnd, X502_SYNC_INTERNAL), "Set immediate stream start"); + + const int32_t ext_ref_err = api.SetExtRefFreqValue(device.hnd, cfg.clock_hz); + if (ext_ref_err != X502_ERR_OK) { + if (cfg.clock_hz <= 1500000.0) { + expect_ok(api, ext_ref_err, "Set external reference frequency"); + } else { + std::cerr << "Warning: X502_SetExtRefFreqValue(" << cfg.clock_hz + << ") failed, continuing with nominal timing only: " + << x502_error(api, ext_ref_err) << "\n"; + } + } + + expect_ok(api, api.SetLChannelCount(device.hnd, kLogicalChannelCount), "Set logical channel count"); + expect_ok(api, api.SetLChannel(device.hnd, 0, cfg.ch1, cfg.mode, cfg.range, 1), "Set logical channel 0"); + expect_ok(api, api.SetLChannel(device.hnd, 1, cfg.ch2, cfg.mode, cfg.range, 1), "Set logical channel 1"); + expect_ok(api, api.SetAdcFreqDivider(device.hnd, 1), "Set ADC frequency divider"); + expect_ok(api, api.SetAdcInterframeDelay(device.hnd, 0), "Set ADC interframe delay"); + expect_ok(api, api.SetDinFreqDivider(device.hnd, kLogicalChannelCount), "Set DIN frequency divider"); + expect_ok(api, api.SetStreamBufSize(device.hnd, X502_STREAM_CH_IN, cfg.input_buffer_words), "Set input buffer size"); + expect_ok(api, api.SetStreamStep(device.hnd, X502_STREAM_CH_IN, cfg.input_step_words), "Set input stream step"); + + uint32_t pullups = 0; + if (cfg.pullup_syn1) { + pullups |= X502_PULLUPS_DI_SYN1; + } + if (cfg.pulldown_start_in) { + pullups |= X502_PULLDOWN_START_IN; + } + expect_ok(api, api.SetDigInPullup(device.hnd, pullups), "Set digital input pullups/pulldowns"); + + expect_ok(api, api.Configure(device.hnd, 0), "Configure device"); + expect_ok(api, api.StreamsEnable(device.hnd, X502_STREAM_ADC | X502_STREAM_DIN), "Enable ADC+DIN stream"); + + const double frame_freq_hz = cfg.clock_hz / static_cast(kLogicalChannelCount); + const double expected_window_us = 1e6 / (2.0 * cfg.gate_hz); + const double expected_frames_per_window = frame_freq_hz / (2.0 * cfg.gate_hz); + + std::cout << "Capture settings:\n" + << " clock source: " << clock_mode_to_string(cfg.clock_mode) << "\n" + << " gate source: start_in (read from synchronous DIN)\n" + << " sample clock: " << cfg.clock_hz << " Hz\n" + << " per-channel frame rate: " << frame_freq_hz << " Hz\n" + << " gate frequency: " << cfg.gate_hz << " Hz\n" + << " expected high window: " << expected_window_us << " us\n" + << " expected frames per window: " << expected_frames_per_window << "\n" + << " channel 1: " << phy_pair_name(cfg.ch1) << "\n" + << " channel 2: " << phy_pair_name(cfg.ch2) << "\n" + << " ADC range: +/-" << range_to_volts(cfg.range) << " V\n" + << " target windows: " << cfg.windows << "\n"; + + expect_ok(api, api.StreamsStart(device.hnd), "Start streams"); + device.streams_started = true; + + std::vector raw(cfg.recv_block_words); + std::vector adc_buffer(cfg.recv_block_words); + std::vector din_buffer(cfg.recv_block_words); + + std::vector windows; + windows.reserve(cfg.windows); + + std::deque pending_frames; + std::deque pending_gate; + + bool have_partial_ch1 = false; + double partial_ch1 = 0.0; + uint32_t next_lch = 0; + + bool gate_initialized = false; + bool last_gate = false; + bool saw_low_before_capture = false; + bool in_window = false; + + WindowData current_window; + + const ULONGLONG session_start = GetTickCount64(); + ULONGLONG last_stream_activity = session_start; + ULONGLONG last_window_complete = session_start; + ULONGLONG last_din_activity = session_start; + ULONGLONG last_gate_edge = session_start; + + uint64_t total_frames_seen = 0; + uint64_t total_din_words = 0; + uint64_t total_gate_edges = 0; + + auto finalize_window = [&]() { + const std::size_t len = std::min(current_window.ch1.size(), current_window.ch2.size()); + current_window.ch1.resize(len); + current_window.ch2.resize(len); + if (len != 0U) { + windows.push_back(std::move(current_window)); + current_window = WindowData{}; + last_window_complete = GetTickCount64(); + } else { + current_window = WindowData{}; + } + }; + + auto fail_waiting_for_gate = [&](ULONGLONG now) { + std::ostringstream message; + message << "ADC clock is present, but no complete START_IN windows were captured within " + << cfg.window_wait_ms << " ms. " + << "Processed frames=" << total_frames_seen + << ", DIN samples=" << total_din_words + << ", gate edges=" << total_gate_edges << ". "; + + if (total_din_words == 0) { + message << "No synchronous DIN words were decoded, so START_IN is not being sampled. "; + } else if (!gate_initialized) { + message << "DIN data is present, but START_IN state was not initialized yet. "; + } else if (total_gate_edges == 0) { + message << "START_IN appears stuck " << (last_gate ? "HIGH" : "LOW") << ". "; + } else if (in_window) { + message << "START_IN produced a rising edge, but no matching falling edge closed the window. "; + } else { + message << "START_IN toggled, but no complete low->high->low window was accepted. "; + } + + message << "Check START_IN wiring, common DGND with the generator, and signal level around 0/3.3 V. " + << "Gate progress: last DIN activity " + << (now - last_din_activity) + << " ms ago, last gate edge " + << (now - last_gate_edge) + << " ms ago."; + fail(message.str()); + }; + + while (windows.size() < cfg.windows) { + const int32_t recvd = api.Recv(device.hnd, raw.data(), cfg.recv_block_words, cfg.recv_timeout_ms); + if (recvd < 0) { + fail("X502_Recv failed: " + x502_error(api, recvd)); + } + + const ULONGLONG now = GetTickCount64(); + if (recvd == 0) { + if ((now - last_stream_activity) >= cfg.clock_wait_ms) { + if (windows.empty() && !gate_initialized) { + fail("Timeout waiting for external ADC clock on DI_SYN1. " + "Streams start immediately in this program, so a timeout here usually means " + "there is no valid clock on DI_SYN1."); + } + fail("External ADC clock stalled before capture completed."); + } + + if ((windows.size() < cfg.windows) && ((now - last_window_complete) >= cfg.window_wait_ms)) { + fail_waiting_for_gate(now); + } + continue; + } + + last_stream_activity = now; + + uint32_t adc_count = static_cast(adc_buffer.size()); + uint32_t din_count = static_cast(din_buffer.size()); + expect_ok(api, + api.ProcessData(device.hnd, + raw.data(), + static_cast(recvd), + X502_PROC_FLAGS_VOLT, + adc_buffer.data(), + &adc_count, + din_buffer.data(), + &din_count), + "Process ADC+DIN data"); + + for (uint32_t i = 0; i < adc_count; ++i) { + const double value = adc_buffer[i]; + if (next_lch == 0U) { + partial_ch1 = value; + have_partial_ch1 = true; + next_lch = 1U; + } else { + if (!have_partial_ch1) { + fail("Internal frame assembly error: missing channel 1 sample"); + } + pending_frames.push_back(Frame{partial_ch1, value}); + ++total_frames_seen; + have_partial_ch1 = false; + next_lch = 0U; + } + } + + for (uint32_t i = 0; i < din_count; ++i) { + pending_gate.push_back((din_buffer[i] & kStartInMask) != 0U); + } + if (din_count != 0U) { + total_din_words += din_count; + last_din_activity = now; + } + + if ((pending_frames.size() > 1000000U) || (pending_gate.size() > 1000000U)) { + fail("Internal backlog grew too large while waiting for gate windows. " + "ADC frames and DIN samples are not lining up as expected."); + } + + while (!pending_frames.empty() && !pending_gate.empty() && (windows.size() < cfg.windows)) { + const Frame frame = pending_frames.front(); + pending_frames.pop_front(); + + const bool gate = pending_gate.front(); + pending_gate.pop_front(); + + if (!gate_initialized) { + gate_initialized = true; + last_gate = gate; + saw_low_before_capture = !gate; + last_gate_edge = now; + } else if (!saw_low_before_capture && !gate) { + saw_low_before_capture = true; + } + + if (gate_initialized && (gate != last_gate)) { + ++total_gate_edges; + last_gate_edge = now; + } + + if (!in_window && saw_low_before_capture && gate_initialized && !last_gate && gate) { + in_window = true; + current_window = WindowData{}; + } + + if (in_window && !gate) { + finalize_window(); + in_window = false; + } + + if (in_window && gate) { + current_window.ch1.push_back(frame.ch1); + current_window.ch2.push_back(frame.ch2); + } + + last_gate = gate; + } + + if ((windows.size() < cfg.windows) && ((now - last_window_complete) >= cfg.window_wait_ms)) { + fail_waiting_for_gate(now); + } + } + + if (in_window) { + finalize_window(); + } + + expect_ok(api, api.StreamsStop(device.hnd), "Stop streams"); + device.streams_started = false; + + if (windows.size() > cfg.windows) { + windows.resize(cfg.windows); + } + if (windows.empty()) { + fail("No complete gate windows were captured"); + } + + write_csv(cfg.csv_path, windows, frame_freq_hz); + write_svg(cfg.svg_path, windows, frame_freq_hz, range_to_volts(cfg.range), cfg.plot_windows, cfg); + + std::size_t min_len = std::numeric_limits::max(); + std::size_t max_len = 0; + std::size_t total_len = 0; + for (const auto& window : windows) { + const std::size_t len = std::min(window.ch1.size(), window.ch2.size()); + min_len = std::min(min_len, len); + max_len = std::max(max_len, len); + total_len += len; + } + const double avg_len = static_cast(total_len) / static_cast(windows.size()); + + std::cout << "Captured windows: " << windows.size() << "\n" + << "Samples per window: min=" << min_len << ", avg=" << avg_len << ", max=" << max_len << "\n" + << "CSV: " << cfg.csv_path << "\n" + << "SVG: " << cfg.svg_path << "\n"; + + return 0; +} + +} // namespace + +int main(int argc, char** argv) { + try { + const Config cfg = parse_args(argc, argv); + return run(cfg); + } catch (const std::exception& ex) { + std::cerr << "Error: " << ex.what() << "\n"; + return 1; + } +} diff --git a/gate_capture.exe b/gate_capture.exe new file mode 100644 index 0000000..f12b8e3 Binary files /dev/null and b/gate_capture.exe differ diff --git a/gate_capture.obj b/gate_capture.obj new file mode 100644 index 0000000..437c0c0 Binary files /dev/null and b/gate_capture.obj differ diff --git a/gate_capture_test.exe b/gate_capture_test.exe new file mode 100644 index 0000000..d86f81a Binary files /dev/null and b/gate_capture_test.exe differ diff --git a/gate_capture_wiring.md b/gate_capture_wiring.md new file mode 100644 index 0000000..b2db1fd --- /dev/null +++ b/gate_capture_wiring.md @@ -0,0 +1,68 @@ +# E-502 Wiring For `gate_capture.exe` + +## Purpose + +This program captures two differential analog signals on `E-502` while: + +- `DI_SYN1` provides the external ADC clock +- `START_IN` provides the repeating gate +- data goes to the PC over the built-in `USB 2.0` + +The program does not use any digital output. + +## Analog Inputs + +- `Signal 1 +` -> `X3` +- `Signal 1 -` -> `Y3` +- `Signal 2 +` -> `X4` +- `Signal 2 -` -> `Y4` + +These pairs correspond to: + +- `ch1:2` -> `X3-Y3` +- `ch2:3` -> `X4-Y4` + +## Sync Inputs + +- `2 MHz clock` from generator -> `DI_SYN1` +- `20 kHz gate` from generator -> `START_IN` + +Behavior in software: + +- every clock edge on `DI_SYN1` advances ADC sampling +- rising edge of `START_IN` starts a capture window +- falling edge of `START_IN` closes the current window + +The stream itself starts immediately after `X502_StreamsStart()`. Windowing is done in software from the sampled state of `START_IN`. + +## Ground + +- generator common / reference ground -> `GND` of `E-502` + +Even with differential analog channels, the sync inputs still need a valid common reference with the generator. + +## USB + +- `E-502 USB 2.0` -> PC + +## ASCII Diagram + +```text +Signal source #1 (+) --------------------------> E-502 X3 +Signal source #1 (-) --------------------------> E-502 Y3 + +Signal source #2 (+) --------------------------> E-502 X4 +Signal source #2 (-) --------------------------> E-502 Y4 + +2 MHz generator output ------------------------> E-502 DI_SYN1 +20 kHz gate output ----------------------------> E-502 START_IN +Generator common / GND ------------------------> E-502 GND + +E-502 USB 2.0 ---------------------------------> PC +``` + +## Recommended Run Command + +```powershell +.\gate_capture.exe clock:di_syn1_rise clock_hz:2000000 gate_hz:20000 windows:1000 csv:gate_capture.csv svg:gate_capture.svg +``` diff --git a/l502api.h b/l502api.h new file mode 100644 index 0000000..40e262b --- /dev/null +++ b/l502api.h @@ -0,0 +1,162 @@ +/***************************************************************************//** + @file l502api.h + , + L-502 . + @date 11.03.2012 + @author Borisov Alexey + ******************************************************************************/ + +#ifndef L502_API_H +#define L502_API_H + +#include "l502api_compat.h" +#include "x502api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************//** + @addtogroup func_open + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief L-502 + + L-502, + , . + + , ( + , ), + #X502_GETDEVS_FLAGS_ONLY_NOT_OPENED. + + @param[in] serials size*#X502_SERIAL_SIZE , + . + NULL, size=0, devcnt!=NULL, , + . + @param[in] size , + serial. + size . + 0, serials=NULL + @param[in] flags #t_x502_getdevs_flags, + . + @param[out] devcnt devcnt!=NULL, + L502 + ( size). + @return <0 - , + serials ( <= size) +*******************************************************************************/ +X502_EXPORT(int32_t) L502_GetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size, + uint32_t flags, uint32_t *devcnt); + +/***************************************************************************//** + @brief L-502 + + L-502 . + , + . + X502_Close() + ( #X502_ERR_DEVICE_ACCESS_DENIED). + + NULL , + , + . + , + #X502_ERR_DEVICE_NOT_FOUND. L-502, + , + , + . + + + X502_Close(). + + @param[in] hnd . + @param[in] serial + NULL. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) L502_Open(t_x502_hnd hnd, const char *serial); + + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_devrec + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief , L502 + + L-502 + + ( ). + + X502_FreeDevRecordList() ( + L502_GetDevRecordsList() , , + , ). + + @param[in] list . + size . + NULL, size=0, devcnt!=NULL, , + . + @param[in] size , + list. + size , . + @param[in] flags #t_x502_getdevs_flags, + . + @param[out] devcnt , + L-502 ( size). + @return <0 --- , + ( <= size). + + X502_FreeDevRecordList() , + , . + ******************************************************************************/ +X502_EXPORT(int32_t) L502_GetDevRecordsList(t_x502_devrec *list, uint32_t size, + uint32_t flags, uint32_t *devcnt) ; +/** @} */ + + + + +/***************************************************************************//** + @addtogroup func_misc + @{ +*******************************************************************************/ + +/**************************************************************************//** + @brief L-502 + + , + . + 32- . + - , + , - . + + - , - , + - , - ( - 0). + + , Windows + modinfo Linux. + + PCI/PCI-Express (L502) + + @param[in] hnd . + @param[out] ver 32- , + @return . + *****************************************************************************/ +X502_EXPORT(int32_t) L502_GetDriverVersion(t_x502_hnd hnd, uint32_t* ver); + +/** @} */ + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/l502api_compat.h b/l502api_compat.h new file mode 100644 index 0000000..06da3b2 --- /dev/null +++ b/l502api_compat.h @@ -0,0 +1,1834 @@ +/***************************************************************************//** + @file l502api_compat.h + L502, + 1.0.x ( E502). + x502api.h, + X502_xxx x502api + + @note , L502_OpenByListItem, + LPCIE_GetDevInfoList LPCIE_FreeDevInfoList + @author Borisov Alexey + ******************************************************************************/ + +#ifndef L502API_COMPAT_H +#define L502API_COMPAT_H + + +#include "x502api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LPCIE_EXPORT(type) X502_EXPORT(type) + +/***************************************************************************//** + @addtogroup const_list . + @{ + *****************************************************************************/ + +/** */ +#define L502_LTABLE_MAX_CH_CNT 256 +/** */ +#define L502_ADC_RANGE_CNT 6 + +/** */ +#define L502_LCH_AVG_SIZE_MAX 128 +/** */ +#define L502_ADC_FREQ_DIV_MAX (1024*1024) +/** */ +#define L502_DIN_FREQ_DIV_MAX (1024*1024) + +/** */ +#define L502_ADC_INTERFRAME_DELAY_MAX (0x1FFFFF) + +/** BlackFin*/ +#define L502_BF_CMD_DEFAULT_TOUT 500 + +/** , */ +#define L502_ADC_SCALE_CODE_MAX 6000000 +/** , */ +#define L502_DAC_SCALE_CODE_MAX 30000 + +/** */ +#define L502_DEVNAME_SIZE 32 +/** */ +#define L502_SERIAL_SIZE 32 + +/** */ +#define L502_EXT_REF_FREQ_MAX 2000000 + + +/** Flash- */ +#define L502_FLASH_USER_SIZE 0x100000 + +/** BlackFin */ +#define L502_BF_REQ_TOUT 500 + + +/** */ +#define L502_DAC_RANGE 5. + +/** */ +#define L502_DAC_CH_CNT 2 + + +/** , , */ +#define L502_STREAM_IN_MSG_OVERFLOW 0x01010000 + + +/** */ +typedef enum { + /** */ + L502_ERR_OK = 0, + /** */ + L502_ERR_INVALID_HANDLE = -1, + /** */ + L502_ERR_MEMORY_ALLOC = -2, + /** */ + L502_ERR_ALREADY_OPENED = -3, + /** */ + L502_ERR_DEVICE_NOT_FOUND = -4, + /** ( - , + ) */ + L502_ERR_DEVICE_ACCESS_DENIED = -5, + /** */ + L502_ERR_DEVICE_OPEN = -6, + /** */ + L502_ERR_INVALID_POINTER = -7, + /** */ + L502_ERR_STREAM_IS_RUNNING = -8, + /** */ + L502_ERR_RECV = -9, + /** */ + L502_ERR_SEND = -10, + /** */ + L502_ERR_STREAM_OVERFLOW = -11, + /** */ + L502_ERR_UNSUP_STREAM_MSG = -12, + /** */ + L502_ERR_MUTEX_CREATE = -13, + /** */ + L502_ERR_MUTEX_INVALID_HANDLE = -14, + /** */ + L502_ERR_MUTEX_LOCK_TOUT = -15, + /** */ + L502_ERR_MUTEX_RELEASE = -16, + /** */ + L502_ERR_INSUFFICIENT_SYSTEM_RESOURCES= -17, + /** */ + L502_ERR_NOT_IMPLEMENTED = -18, + /** */ + L502_ERR_INSUFFICIENT_ARRAY_SIZE = -19, + /** FPGA */ + L502_ERR_FPGA_REG_READ = -20, + /** FPGA */ + L502_ERR_FPGA_REG_WRITE = -21, + /** */ + L502_ERR_STREAM_IS_NOT_RUNNING = -22, + /** */ + L502_ERR_INVALID_LTABLE_SIZE = -102, + /** */ + L502_ERR_INVALID_LCH_NUMBER = -103, + /** */ + L502_ERR_INVALID_LCH_RANGE = -104, + /** */ + L502_ERR_INVALID_LCH_MODE = -105, + /** */ + L502_ERR_INVALID_LCH_PHY_NUMBER = -106, + /** */ + L502_ERR_INVALID_LCH_AVG_SIZE = -107, + /** */ + L502_ERR_INVALID_ADC_FREQ_DIV = -108, + /** */ + L502_ERR_INVALID_DIN_FREQ_DIV = -108, + /** L502 */ + L502_ERR_INVALID_MODE = -109, + /** */ + L502_ERR_INVALID_DAC_CHANNEL = -110, + /** */ + L502_ERR_INVALID_REF_FREQ = -111, + /** */ + L502_ERR_INVALID_INTERFRAME_DELAY = -112, + /** */ + L502_ERR_INVALID_SYNC_MODE = -113, + /** DMA */ + L502_ERR_INVALID_DMA_CH = -114, + + /** */ + L502_ERR_REF_FREQ_NOT_LOCKED = -131, + /** */ + L502_ERR_IOCTL_FAILD = -132, + /** */ + L502_ERR_IOCTL_TIMEOUT = -133, + /** */ + L502_ERR_GET_INFO = -134, + /** */ + L502_ERR_DIG_IN_NOT_RDY = -135, + /** */ + L502_ERR_RECV_INSUFFICIENT_WORDS = -136, + /** , , */ + L502_ERR_DAC_NOT_PRESENT = -137, + /** */ + L502_ERR_PROC_INVALID_CH_NUM = -140, + /** */ + L502_ERR_PROC_INVALID_CH_RANGE = -141, + /** Flash- */ + L502_ERR_FLASH_INVALID_ADDR = -142, + /** Flash- */ + L502_ERR_FLASH_INVALID_SIZE = -143, + /** Flash- */ + L502_ERR_FLASH_WRITE_TOUT = -144, + /** Flash- */ + L502_ERR_FLASH_ERASE_TOUT = -145, + /** Flash- 4 */ + L502_ERR_FLASH_SECTOR_BOUNDARY = -146, + /** BlackFin */ + L502_ERR_LDR_FILE_OPEN = -180, + /** BlackFin */ + L502_ERR_LDR_FILE_READ = -181, + /** BlackFin */ + L502_ERR_LDR_FILE_FORMAT = -182, + /** LDR-, + BlackFin HDMA */ + L502_ERR_LDR_FILE_UNSUP_FEATURE = -183, + /** BlackFin */ + L502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR = -184, + /** / BlackFin */ + L502_ERR_BF_REQ_TIMEOUT = -185, + /** BlackFin */ + L502_ERR_BF_CMD_IN_PROGRESS = -186, + /** BlackFin */ + L502_ERR_BF_CMD_TIMEOUT = -187, + /** BlackFin */ + L502_ERR_BF_CMD_RETURN_INSUF_DATA = -188, + /** BlackFin */ + L502_ERR_BF_LOAD_RDY_TOUT = -189, + /** + */ + L502_ERR_BF_NOT_PRESENT = -190, + /** BlackFin HDMA */ + L502_ERR_BF_INVALID_ADDR = -191, + /** , BlackFin */ + L502_ERR_BF_INVALID_CMD_DATA_SIZE = -192 +} t_lpcie_errs; + +/** , */ +typedef enum { + /** , , + */ + L502_GETDEVS_FLAGS_ONLY_NOT_OPENED = X502_GETDEVS_FLAGS_ONLY_NOT_OPENED +} t_l502_getdevs_flags; + + + +/** @brief . + + . + Ȕ + L502_AsyncOutDig() L502_PrepareData() .*/ +typedef enum { + L502_DIGOUT_WORD_DIS_H = X502_DIGOUT_WORD_DIS_H, /**< ( ) + */ + L502_DIGOUT_WORD_DIS_L = X502_DIGOUT_WORD_DIS_L /**< + */ +} t_l502_digout_word_flags; + + +/** */ +typedef enum { + L502_REF_FREQ_2000KHZ = X502_REF_FREQ_2000KHZ, /**< 2 */ + L502_REF_FREQ_1500KHZ = X502_REF_FREQ_1500KHZ /**< 1.5 */ +} t_l502_ref_freq; + + +/** */ +typedef enum { + L502_ADC_RANGE_10 = X502_ADC_RANGE_10, /**< +/-10V */ + L502_ADC_RANGE_5 = X502_ADC_RANGE_5, /**< +/-5V */ + L502_ADC_RANGE_2 = X502_ADC_RANGE_2, /**< +/-2V */ + L502_ADC_RANGE_1 = X502_ADC_RANGE_1, /**< +/-1V */ + L502_ADC_RANGE_05 = X502_ADC_RANGE_05, /**< +/-0.5V */ + L502_ADC_RANGE_02 = X502_ADC_RANGE_02 /**< +/-0.2V */ +} t_l502_adc_range; + +/** */ +typedef enum { + L502_LCH_MODE_COMM = X502_LCH_MODE_COMM, /**< */ + L502_LCH_MODE_DIFF = X502_LCH_MODE_DIFF, /**< */ + L502_LCH_MODE_ZERO = X502_LCH_MODE_ZERO /**< */ +} t_l502_lch_mode; + +/** @brief . + + + - */ +typedef enum { + L502_SYNC_INTERNAL = 0, /**< */ + L502_SYNC_EXTERNAL_MASTER = 1, /**< */ + L502_SYNC_DI_SYN1_RISE = 2, /**< DI_SYN1 */ + L502_SYNC_DI_SYN2_RISE = 3, /**< DI_SYN2 */ + L502_SYNC_DI_SYN1_FALL = 6, /**< DI_SYN1 */ + L502_SYNC_DI_SYN2_FALL = 7 /**< DI_SYN2 */ +} t_l502_sync_mode; + +/** , */ +typedef enum { + /** , */ + L502_PROC_FLAGS_VOLT = X502_PROC_FLAGS_VOLT, + /** , + . + BlackFin + . */ + L502_PROC_FLAGS_DONT_CHECK_CH = X502_PROC_FLAGS_DONT_CHECK_CH +} t_l502_proc_flags; + + +/** */ +typedef enum { + L502_STREAM_ADC = X502_STREAM_ADC, /**< */ + L502_STREAM_DIN = X502_STREAM_DIN, /**< */ + L502_STREAM_DAC1 = X502_STREAM_DAC1, /**< */ + L502_STREAM_DAC2 = X502_STREAM_DAC2, /**< */ + L502_STREAM_DOUT = X502_STREAM_DOUT, /**< */ + /** , */ + L502_STREAM_ALL_IN = X502_STREAM_ALL_IN, + /** , */ + L502_STREAM_ALL_OUT = X502_STREAM_ALL_OUT +} t_l502_streams; + +/** , */ +typedef enum { + L502_STREAM_OUT_WORD_TYPE_DOUT = X502_STREAM_OUT_WORD_TYPE_DOUT, /**< */ + L502_STREAM_OUT_WORD_TYPE_DAC1 = X502_STREAM_OUT_WORD_TYPE_DAC1, /**< 1- */ + L502_STREAM_OUT_WORD_TYPE_DAC2 = X502_STREAM_OUT_WORD_TYPE_DAC2 /**< 2- */ +} t_l502_stream_out_wrd_type; + +/** L502 */ +typedef enum { + L502_MODE_FPGA = X502_MODE_FPGA, /**< + BlackFin */ + L502_MODE_DSP = X502_MODE_DSP, /**< + , + */ + L502_MODE_DEBUG = X502_MODE_DEBUG /**< */ +} t_l502_mode; + +/** @brief . + + L502_AsyncOutDac() */ +typedef enum { + L502_DAC_CH1 = X502_DAC_CH1, /**< */ + L502_DAC_CH2 = X502_DAC_CH2 /**< */ +} t_l502_dac_ch; + +/** @brief , . + + , L502_AsyncOutDac() + L502_PrepareData(), , + */ +typedef enum { + /** , + . , , + */ + L502_DAC_FLAGS_VOLT = X502_DAC_FLAGS_VOLT, + /** , + . */ + L502_DAC_FLAGS_CALIBR = X502_DAC_FLAGS_CALIBR +} t_l502_dacout_flags; + + +/** DMA */ +typedef enum { + L502_DMA_CH_IN = X502_STREAM_CH_IN, /**< DMA */ + L502_DMA_CH_OUT = X502_STREAM_CH_OUT /**< DMA */ +} t_l502_dma_ch; + + +/** @brief , + + , + */ +typedef enum { + L502_PULLUPS_DI_H = X502_PULLUPS_DI_H, /**< */ + L502_PULLUPS_DI_L = X502_PULLUPS_DI_L, /**< */ + L502_PULLUPS_DI_SYN1 = X502_PULLUPS_DI_SYN1, /**< SYN1 */ + L502_PULLUPS_DI_SYN2 = X502_PULLUPS_DI_SYN2 /**< SYN2 */ +} t_l502_pullups; + + +/** , */ +typedef enum { + /** */ + L502_DEVFLAGS_DAC_PRESENT = X502_DEVFLAGS_DAC_PRESENT, + /** */ + L502_DEVFLAGS_GAL_PRESENT = X502_DEVFLAGS_GAL_PRESENT, + /** BlackFin */ + L502_DEVFLAGS_BF_PRESENT = X502_DEVFLAGS_BF_PRESENT, + /** , Flash- */ + L502_DEVFLAGS_FLASH_DATA_VALID = X502_DEVFLAGS_FLASH_DATA_VALID, + /** , Flash- + */ + L502_DEVFLAGS_FLASH_ADC_CALIBR_VALID = X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID, + /** , Flash- + */ + L502_DEVFLAGS_FLASH_DAC_CALIBR_VALID = X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID +} t_l502_dev_flags; + + +/** @brief + + L502_OutCycleSetup() L502_OutCycleStop() */ +typedef enum { + /** , + . + ( 256 , + ), + */ + L502_OUT_CYCLE_FLAGS_FORCE = X502_OUT_CYCLE_FLAGS_FORCE +} t_l502_out_cycle_flags; + +/** @} */ + +/***************************************************************************//** + @addtogroup type_list . + @{ + *****************************************************************************/ + +/** @brief . + + , + . + , + . + . + L502_Create() + L502_Free(). */ +typedef t_x502_hnd t_l502_hnd; + + + +/** @brief + + , + . */ +typedef t_x502_serial_list t_l502_serial_list; + + +/** @brief . + + + . + (val-offs)*k, val - */ +typedef struct { + double offs; /**< */ + double k; /**< */ +} t_l502_cbr_coef; + + +/** @brief . + + , , + L502 */ +typedef struct { + /** */ + t_l502_cbr_coef adc[L502_ADC_RANGE_CNT]; + uint32_t res1[64]; /**< */ + /** */ + t_l502_cbr_coef dac[L502_DAC_CH_CNT]; + uint32_t res2[20]; /**< */ +} t_l502_cbr; + +/** @brief L502. + + , L502, + */ +typedef struct { + char name[L502_DEVNAME_SIZE]; /**< ("L502") */ + char serial[L502_SERIAL_SIZE]; /**< */ + uint32_t devflags; /**< #t_l502_dev_flags, + */ + uint16_t fpga_ver; /**< ( - , - ) */ + uint8_t plda_ver; /**< , */ + uint8_t board_rev; /**< */ + uint8_t res[120]; /**< */ + t_l502_cbr cbr; /**< ( Flash-) */ +} t_l502_info; + +/** @} */ + + +/** @addtogroup func_list . + @{ **/ + +/***************************************************************************//** + @addtogroup func_hnd . + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief . + + , L502. + + -. + @return NULL , - +*******************************************************************************/ +LPCIE_EXPORT(t_l502_hnd) L502_Create(void); + +/***************************************************************************//** + @brief . + + , L502_Create(). + , + ! + @param[in] hnd + @return +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_Free(t_l502_hnd hnd); +/** @} */ + + +/***************************************************************************//** + @addtogroup func_open . + @{ +*******************************************************************************/ + + +/***************************************************************************//** + @brief . + + L502, + ( ). + . + L502_Free(). + @param[in] hnd . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_Close(t_l502_hnd hnd); + + +/***************************************************************************//** + @brief . + + L502, . + @param[in] hnd . + @param[out] info ( #t_l502_info). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetDevInfo(t_l502_hnd hnd, t_l502_info* info); + + + +/** @} */ + +/***************************************************************************//** + @addtogroup func_config + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief . + + ( + L502_SetXXX) . + . + @param[in] hnd . + @param[in] flags ( - 0). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_Configure(t_l502_hnd hnd, uint32_t flags); + +/***************************************************************************//** + @brief . + + + . + @param[in] hnd . + @param[in] lch . + ( 0 #L502_LTABLE_MAX_CH_CNT-1) + @param[in] phy_ch , 0 + (0-15 , + 0-31 ) + @param[in] mode ( #t_l502_lch_mode) + @param[in] range ( #t_l502_adc_range) + @param[in] avg . + , + . + 1 ( ) + #L502_LCH_AVG_SIZE_MAX. + + , + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetLChannel(t_l502_hnd hnd, uint32_t lch, uint32_t phy_ch, + uint32_t mode, uint32_t range, uint32_t avg); + +/***************************************************************************//** + @brief . + + . + @param[in] hnd + @param[in] lch_cnt + ( 1 #L502_LTABLE_MAX_CH_CNT) + @return +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetLChannelCount(t_l502_hnd hnd, uint32_t lch_cnt); + + +/***************************************************************************//** + @brief . + + L502_SetLChannelCount() + . + @param[in] hnd + @param[out] lch_cnt + @return +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetLChannelCount(t_l502_hnd hnd, uint32_t* lch_cnt); + +/***************************************************************************//** + @brief . + + + ( , ) , + . + + L502_SetAdcFreq(), + . + + @param[in] hnd . + @param[in] adc_freq_div ( 1 #L502_ADC_FREQ_DIV_MAX). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetAdcFreqDivider(t_l502_hnd hnd, uint32_t adc_freq_div); + +/***************************************************************************//** + @brief . + + , + , + + , . + + L502_SetAdcFreq(), + + ( ). + + @param[in] hnd . + @param[in] delay ( 0 + #L502_ADC_INTERFRAME_DELAY_MAX) + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetAdcInterframeDelay(t_l502_hnd hnd, uint32_t delay); + +/***************************************************************************//** + @brief . + + + , + . + + L502_SetDinFreq(), + + . + + @param[in] hnd . + @param[in] din_freq_div ( 1 #L502_DIN_FREQ_DIV_MAX). + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDinFreqDivider(t_l502_hnd hnd, uint32_t din_freq_div); + + +/***************************************************************************//** + @brief . + + , + f_acq. + , . + + , + ( ) + . + f_frame ( + ). + f_frame , + . + + , + L502_SetRefFreq(), + . + + , + , + L502_SetLChannelCount(). + + + , + , L502_SetRefFreq(). + + + @param[in] hnd . + @param[in,out] f_acq + . + . + @param[in,out] f_frame + ( ) + . + . + , + ( ). + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetAdcFreq(t_l502_hnd hnd, double *f_acq, double *f_frame); + + + + + + +/***************************************************************************//** + @brief . + + , + . + , . + + , + L502_SetRefFreq(), + . + + + , + , L502_SetRefFreq(). + + @param[in] hnd . + @param[in,out] f_din + . + . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDinFreq(t_l502_hnd hnd, double *f_din); + + +/***************************************************************************//** + @brief + + + ( ) , + L502_SetAdcFreq() + L502_SetAdcFreqDivider()/L502_SetAdcInterframeDelay(). + + @param[in] hnd . + @param[out] f_acq NULL, + . + @param[out] f_frame NULL, + . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetAdcFreq(t_l502_hnd hnd, double *f_acq, double *f_frame); + + + +/***************************************************************************//** + @brief . + + , + / + . + + : + 2 1.5 (2 -), + #t_l502_ref_freq. + + , + + L502_SetAdcFreq()/L502_SetDinFreq() + - DMA , + . + + @param[in] hnd . + @param[in] freq #t_l502_ref_freq, + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetRefFreq(t_l502_hnd hnd, uint32_t freq); + +/***************************************************************************//** + @brief . + + - + . + + #L502_SYNC_INTERNAL + , L502_SetRefFreq(). + L502_StreamsStart() + , L502_SetSyncStartMode(), + L502_StreamsStop(). + + + . + + @param[in] hnd . + @param[in] sync_mode #t_l502_sync_mode, + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetSyncMode(t_l502_hnd hnd, uint32_t sync_mode); + +/***************************************************************************//** + @brief . + + / . + + L502_SetSyncMode() + #L502_SYNC_INTERNAL, + , + + (.. + ). + + , + (. #t_l502_sync_mode). + #L502_SYNC_INTERNAL + L502_StreamsStart(), - + L502_StreamsStart() . + .. , + L502_StreamsStart(). + + @param[in] hnd . + @param[in] sync_start_mode #t_l502_sync_mode, + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetSyncStartMode(t_l502_hnd hnd, uint32_t sync_start_mode); + + +/***************************************************************************//** + @brief . + + , + BlackFin. + . + L502_BfLoadFirmware() + . + + , + , + , + (, JTAG ). + + @param[in] hnd . + @param[in] mode #t_l502_mode. + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetMode(t_l502_hnd hnd, uint32_t mode); +/***************************************************************************//** + @brief . + + . + @param[in] hnd . + @param[out] mode + ( #t_l502_mode). + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetMode(t_l502_hnd hnd, uint32_t* mode); +/***************************************************************************//** + @brief . + + . + , + Flash- + . + + (val+offs)*k, val - + . + + , + . + , Flash- + . + + @param[in] hnd . + @param[in] range ( #t_l502_adc_range). + @param[in] k . + @param[in] offs . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetAdcCoef(t_l502_hnd hnd, uint32_t range, double k, double offs); + +/***************************************************************************//** + @brief . + + + . , + Flash- , , + L502_SetAdcCoef() . + + @param[in] hnd . + @param[in] range ( #t_l502_adc_range). + @param[in] k + . + @param[in] offs . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetAdcCoef(t_l502_hnd hnd, uint32_t range, double* k, double* offs); + + + +/***************************************************************************//** + @brief . + + , + l502api + , #L502_DAC_FLAGS_CALIBR. + + + (val+offs)*k, val - ( ). + + , + Flash- . + + + . Flash-, .. + + Flash-. + + @param[in] hnd . + @param[in] ch ( #t_l502_dac_ch). + @param[in] k . + @param[in] offs . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDacCoef(t_l502_hnd hnd, uint32_t ch, double k, double offs); + + +/***************************************************************************//** + @brief . + + . + , + Flash- , , + L502_SetDacCoef() . + + @param[in] hnd . + @param[in] ch ( #t_l502_dac_ch). + @param[in] k + . + @param[in] offs . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetDacCoef(t_l502_hnd hnd, uint32_t ch, double* k, double* offs); + + + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_async - + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief . + + . + , , + ( ). + + , + , + . + + @param[in] hnd . + @param[in] ch ( #t_l502_dac_ch). + @param[in] data ( ) + @param[in] flags #t_l502_dacout_flags. + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_AsyncOutDac(t_l502_hnd hnd, uint32_t ch, double data, uint32_t flags); + +/***************************************************************************//** + @brief . + + . + L502_PrepareData() - 16 + , - ( + ). + + , + , . + + , , + , , + , + . + + @param[in] hnd . + @param[in] val - , - + #t_l502_digout_word_flags. + @param[in] msk - + ( + val). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_AsyncOutDig(t_l502_hnd hnd, uint32_t val, uint32_t msk); + + +/***************************************************************************//** + @brief . + + . + ( + #L502_STREAM_DIN). + + L502 , + / + L502_StreamsStart(), + + . + + @param[in] hnd . + @param[out] din + . + 18 , 14 - . + + , , + ! + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_AsyncInDig(t_l502_hnd hnd, uint32_t* din); + + + + + + + + + +/***************************************************************************//** + @brief . + + + . + L502_SetAdcFreq(). + . , + L502_AsyncGetAdcFrame() + . + + , + L502_ProcessAdcData(), , + L502_ProcessAdcData(). + + + . + + , + , + . + + @param[in] hnd . + @param[in] flags t_l502_proc_flags + @param[in] tout + @param[out] data , + . , + double , + + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_AsyncGetAdcFrame(t_l502_hnd hnd, uint32_t flags, + uint32_t tout, double* data); + +/** @} */ + + + + +/***************************************************************************//** + @addtogroup func_streams - + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief /. + + / + . + L502_Configure(), . + L502_StreamsStart(). + + + , + , + (. @ref sect_sync_mode_buf) + @param[in] hnd . + @param[in] streams #t_l502_streams, , + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_StreamsEnable(t_l502_hnd hnd, uint32_t streams); +/****************************************************************************//** + @brief /. + + . + . + , L502_StreamsEnable(). + @param[in] hnd . + @param[in] streams #t_l502_streams, , + . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_StreamsDisable(t_l502_hnd hnd, uint32_t streams); + +/***************************************************************************//** + @brief /. + + . + . , + , + + . + + DMA , + , + DMA , + , L502_PreloadStart() ( + ). + + @param[in] hnd . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_StreamsStart(t_l502_hnd hnd); + +/***************************************************************************//** + @brief /. + + / . + ( + ) + . + @param[in] hnd . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_StreamsStop(t_l502_hnd hnd); + + +/***************************************************************************//** + @brief , /. + + L502_StreamsStart() + - BlackFin. + , + #L502_ERR_STREAM_IS_NOT_RUNNING, , + + @param[in] hnd . + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_IsRunning(t_l502_hnd hnd); + +/***************************************************************************//** + @brief . + + , DMA + . , + , ( + ) ( , ). + L502_ProcessData(). + + , , + + . + , . + + + L502_GetRecvReadyCount(). + + L502_Recv() + L502_StreamsStart(). + + @param[in] hnd . + @param[out] buf , . + @param[in] size (32- ). + @param[in] tout . + @return < 0 - . + >= 0 - . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_Recv(t_l502_hnd hnd, uint32_t* buf, uint32_t size, uint32_t tout); + + +/***************************************************************************//** + @brief . + + , + DMA . + , , + ( , 1 2). + L502_PrepareData(). + + , + . + + L502_GetSendReadyCount(). + + , + . + + + L502_PreloadStart(). + + @param[in] hnd . + @param[in] buf , + @param[in] size (32- ). + @param[in] tout ( ) . + @return < 0 - . + >= 0 - . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_Send(t_l502_hnd hnd, const uint32_t* buf, uint32_t size, uint32_t tout); + + + +/***************************************************************************//** + @brief . + + , L502_Recv(). + + , ( #L502_PROC_FLAGS_VOLT). + + , + ( + - ). + + , + L502_ProcessData(), + . + + @param[in] hnd . + @param[in] src , L502_Recv(). + @param[out] dest , + . + @param[in,out] size - src, - + + dest + @param[in] flags #t_l502_proc_flags + @return . + ****************************************************************************/ +LPCIE_EXPORT(int32_t) L502_ProcessAdcData(t_l502_hnd hnd, const uint32_t* src, double *dest, + uint32_t *size, uint32_t flags); + + +/***************************************************************************//** + @brief . + + , L502_Recv(). + , + - , double, + . + + . + , + . + , + #L502_ADC_SCALE_CODE_MAX + . + + , , + (, ). + @param[in] hnd . + @param[in] src , L502_Recv(). + @param[in] size (32- ) src. + @param[in] flags #t_l502_proc_flags, + . + "". + @param[out] adc_data , , + . + NULL, + ( adc_data_size NULL, + 0). + @param[in,out] adc_data_size + adc_data. + adc_data_size, adc_data + adc_data_size . + + + . + NULL, adc_data = NULL + @param[out] din_data , + . 18 + , 14 - . + NULL, + . + @param[in,out] din_data_size adc_data_size + din_data , + + . NULL, + din_data = NULL. + @return . + ****************************************************************************/ +LPCIE_EXPORT(int32_t) L502_ProcessData(t_l502_hnd hnd, const uint32_t* src, uint32_t size, + uint32_t flags, double *adc_data, uint32_t *adc_data_size, + uint32_t *din_data, uint32_t *din_data_size); + +/***************************************************************************//** + @brief . + + L502_ProcessData(), + . + , , + . + usr_data + ( ). + , + BlackFin. + @param[in] hnd . + @param[in] src , + L502_Recv(). + @param[in] size (32- ) src. + @param[in] flags #t_l502_proc_flags. + @param[out] adc_data , + (. L502_ProcessData()). + @param[in,out] adc_data_size . L502_ProcessData() + @param[out] din_data , + . . L502_ProcessData(). + @param[in,out] din_data_size . L502_ProcessData(). + @param[out] usr_data , + . + @param[in,out] usr_data_size usr_data + + . + NULL usr_data = NULL. + @return . + ****************************************************************************/ +LPCIE_EXPORT(int32_t) L502_ProcessDataWithUserExt(t_l502_hnd hnd, const uint32_t* src, uint32_t size, + uint32_t flags, double *adc_data, + uint32_t *adc_data_size, uint32_t *din_data, + uint32_t *din_data_size, + uint32_t *usr_data, uint32_t *usr_data_size); + + + +/***************************************************************************//** + @brief . + + - , + . + , . + + , . + + n*size , n - + ( 1 3). + + 32- , 16- + , - + #t_l502_digout_word_flags, + ( ) . + + , , + , + . + , + #L502_DAC_SCALE_CODE_MAX , +5V. + + @param[in] hnd . + @param[in] dac1 + NULL, . + @param[in] dac2 + NULL, . + @param[in] digout + NULL, . + @param[in] size . + @param[in] flags , , + #t_l502_dacout_flags. + @param[out] out_buf , + . + n*size (n - + ) + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_PrepareData(t_l502_hnd hnd, const double* dac1, const double* dac2, + const uint32_t* digout, uint32_t size, int32_t flags, + uint32_t* out_buf); + +/***************************************************************************//** + @brief . + + , + + L502_Recv(). + L502_Recv() , , + L502_Recv() ( + ). + @param[in] hnd . + @param[out] rdy_cnt . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetRecvReadyCount(t_l502_hnd hnd, uint32_t *rdy_cnt); + + +/***************************************************************************//** + @brief . + + , + . + L502_Send() + . + @param[in] hnd . + @param[out] rdy_cnt + . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetSendReadyCount(t_l502_hnd hnd, uint32_t *rdy_cnt); + + +/***************************************************************************//** + @brief + . + + , + L502_ProcessData()/ + L502_ProcessAdcData() , . + + , , + . + + . + L502_ProcessData() , + , , + L502_ProcessData(). + + , 7 , L502_ProcessData() + 7 , + L502_GetNextExpectedLchNum() 0 ( + ). + L502_ProcessData() 7*n + 5 , + 5 ( + 0,1,2,3,4 ). + + @param[in] hnd . + @param[out] lch ( ). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_GetNextExpectedLchNum(t_l502_hnd hnd, uint32_t *lch); + + +/***************************************************************************//** + @brief + + + . + , + L502_StreamsStart(). + + DMA . + + L502_Send(). + + @param[in] hnd . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_PreloadStart(t_l502_hnd hnd); + + + +/***************************************************************************//** + @brief + + + . + L502_Send(). + + ( + ) - .. + L502_OutCycleSetup(). + . + + @param[in] hnd . + @param[in] size + . + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_OutCycleLoadStart(t_l502_hnd hnd, uint32_t size); + +/***************************************************************************//** + @brief + + . + - ( L502_StreamsStart()), + , + -. + + , + , + #L502_OUT_CYCLE_FLAGS_FORCE. + + L502_OutCycleLoadStart() + ! + + @param[in] hnd . + @param[in] flags #t_l502_out_cycle_flags. + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_OutCycleSetup(t_l502_hnd hnd, uint32_t flags); + + +/***************************************************************************//** + @brief + + + L502_OutCycleSetup(). + ( + , ), + . + + L502_StreamsStop() ( + L502_StreamsDisable()) + . + + @param[in] hnd . + @param[in] flags #t_l502_out_cycle_flags. + @return . + ***************************************************************************/ +LPCIE_EXPORT(int32_t) L502_OutCycleStop(t_l502_hnd hnd, uint32_t flags); + + + + + +/***************************************************************************//** + @brief . + + , + . + , - + - + + @param[in] hnd . + @param[in] dma_ch , + ( #t_l502_dma_ch). + @param[in] size 32- + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDmaBufSize(t_l502_hnd hnd, uint32_t dma_ch, uint32_t size); + +/***************************************************************************//** + @brief DMA. + + + . + DMA + , + . + , + . + + @param[in] hnd . + @param[in] dma_ch , + ( #t_l502_dma_ch). + @param[in] step 32- + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDmaIrqStep(t_l502_hnd hnd, uint32_t dma_ch, uint32_t step); + +/** @} */ + + + + +/***************************************************************************//** + @addtogroup func_dsp + @{ +*******************************************************************************/ +/***************************************************************************//** + @brief BlackFin. + + + , + ( ). + LDR. + @param[in] hnd . + @param[in] filename . + @return . + *****************************************************************************/ +LPCIE_EXPORT(int32_t) L502_BfLoadFirmware(t_l502_hnd hnd, const char* filename); + + + +/***************************************************************************//** + @brief , BlackFIn. + + BlackFin + . , + BlackFin . + ( , + ..) . + DSP. + + + ( ) + JTAG-. + + @param[in] hnd . + @param[out] version , + BlackFin + . + @return . + *****************************************************************************/ +LPCIE_EXPORT(int32_t) L502_BfCheckFirmwareIsLoaded(t_l502_hnd hnd, uint32_t *version); + +/***************************************************************************//** + @brief . + + . + , (L1), SDRAM. + BlackFin . + + , + . + + @param[in] hnd . + @param[in] addr , + . + @param[out] regs , + . + @param[in] size 32- . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_BfMemRead(t_l502_hnd hnd, uint32_t addr, uint32_t* regs, + uint32_t size); + +/***************************************************************************//** + @brief . + + BlackFin. + 8 32- (32 ). + (L1), SDRAM. + BlackFin . + + , + . + + @note , .. , + . + + @param[in] hnd . + @param[in] addr , + . + @param[out] regs . + @param[in] size 32- + ( 8). + @return . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_BfMemWrite(t_l502_hnd hnd, uint32_t addr, + const uint32_t* regs, uint32_t size); + + +/***************************************************************************//** + @brief . + + + , BlackFin. + + + , + . + . + + , l502api + , . + L502_BF_CMD_CODE_USER (0x8000). + + @param[in] hnd . + @param[in] cmd_code - , . + @param[in] par , ( + ). + @param[in] snd_data , . + , + snd_size = 0. + @param[in] snd_size 32- , snd_data + @param[out] rcv_data , , + . + , + , rcv_size = 0. + @param[in] rcv_size 32- , , + . + rcv_data + . + @param[in] tout , + . + , + . + @param[out] recvd_size , + 32- , + + ( , + rcv_size). + @return . + , + . +*******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_BfExecCmd(t_l502_hnd hnd, uint16_t cmd_code, uint32_t par, + const uint32_t* snd_data, uint32_t snd_size, + uint32_t* rcv_data, uint32_t rcv_size, uint32_t tout, uint32_t* recvd_size); +/** @} */ + + + +/***************************************************************************//** + @addtogroup func_flash Flash- + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief Flash-. + + Flash- , + . - + . + @param[in] hnd . + @param[in] addr . + @param[out] data , + ( size ). + @param[in] size . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_FlashRead(t_l502_hnd hnd, uint32_t addr, uint8_t* data, + uint32_t size); +/***************************************************************************//** + @brief Flash- . + + Flash- . + L502_FlashErase() + L502_FlashWriteEnable(), + Flash-. + #L502_FLASH_USER_SIZE + Flash-. + @param[in] hnd . + @param[in] addr . + @param[in] data c ( + size ). + @param[in] size . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_FlashWrite(t_l502_hnd hnd, uint32_t addr, + const uint8_t* data, uint32_t size); +/***************************************************************************//** + @brief Flash-. + + Flash- ( + 0xFF). 4096 ! + + L502_FlashWriteEnable(). + @param[in] hnd . + @param[in] addr ( 4K). + @param[in] size ( 4K). + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_FlashErase(t_l502_hnd hnd, uint32_t addr, uint32_t size); +/***************************************************************************//** + @brief Flash-. + + Flash- ( + #L502_FLASH_USER_SIZE ). , + L502_FlashErase() L502_FlashWrite() + . + L502_FlashWriteDisable(). + @param[in] hnd . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_FlashWriteEnable(t_l502_hnd hnd); +/***************************************************************************//** + @brief Flash-. + + Flash- + ( #L502_FLASH_USER_SIZE ). , + + L502_FlashErase() L502_FlashWrite(), + . + @param[in] hnd . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_FlashWriteDisable(t_l502_hnd hnd); + +/** @} */ + +/***************************************************************************//** + @addtogroup func_misc . + @{ +*******************************************************************************/ +/**************************************************************************//** + @brief . + + l502api.dll. + 32- . + - , + , - . + + - , - , + - , - ( - 0) + + @return 32- , + *****************************************************************************/ +LPCIE_EXPORT(uint32_t) L502_GetDllVersion(void); + + + +/***************************************************************************//** + @brief . + + , . + ( + ). + + @note , Windows + Windows CP1251, Linux + UTF-8. + @param[in] err , . + @return , + ******************************************************************************/ +LPCIE_EXPORT(const char*) L502_GetErrorString(int32_t err); + + +/***************************************************************************//** + @brief . + + , /, + . + + . + + / + . + + @param[in] hnd . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_LedBlink(t_l502_hnd hnd); + +/***************************************************************************//** + @brief . + + + . + , , SYN1 + SYN2. , + . + . + + @param[in] hnd . + @param[in] pullups ( #t_l502_pullups), , + . + @return . + ******************************************************************************/ +LPCIE_EXPORT(int32_t) L502_SetDigInPullup(t_l502_hnd hnd, uint32_t pullups); + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/lcard_pstdint.h b/lcard_pstdint.h new file mode 100644 index 0000000..c82f7e4 --- /dev/null +++ b/lcard_pstdint.h @@ -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 +#include + +/* + * 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 +#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 +# 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 +#include +#include + +#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 diff --git a/main.c b/main.c new file mode 100644 index 0000000..b5a8593 --- /dev/null +++ b/main.c @@ -0,0 +1,422 @@ +/* + * + * E16 / LTA37 / E502 / L502 ( ). + * + * + * + * + */ + +#include "l502api.h" +#include "e502api.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev_funcs.h" +#include "timespec_funcs.h" + +#ifndef _WIN32 + #include + #include + #include + #include +#endif + +//#define DEBUG +#ifdef DEBUG + #define dbg_printf(...) fprintf(stderr, __VA_ARGS__) +#else + #define dbg_printf(...) +#endif + + +/* */ +static volatile int f_out = 0; + +#define DAC_BUF_SIZE (1024 * 1024) +/* () */ +#define SEND_TOUT 500 + +double dac_freq = 200000; +// +double cycle_delay; + +// +int cycle_mode = 1; + +#ifndef _WIN32 +/* Linux */ +static void f_abort_handler(int sig) { + f_out = 1; +} +#endif + +int32_t f_setup_params(t_x502_hnd hnd) { + int32_t err; + + X502_SetSyncMode(hnd, X502_SYNC_INTERNAL); + X502_StreamsStop(hnd); + X502_StreamsDisable(hnd, X502_STREAM_ALL_IN|X502_STREAM_ALL_OUT); + + err = X502_SetOutFreq(hnd, &dac_freq); + if (err) { + fprintf(stderr, "X502_SetOutFreq err=%d dout_freq = %.1f\n", err, dac_freq); + } + + /* */ + if (err == X502_ERR_OK) { + err = X502_Configure(hnd, 0); + } + + if (err == X502_ERR_OK) { + /* - */ + fprintf(stderr, " : %0.0f Hz\n", dac_freq); + } + + return err; +} + +void parse_params(int argc, char **argv) { + for (int i = 1; (int)i < argc - 1; i++) { + if (sscanf(argv[i], "dac_freq:%lf", &dac_freq) == 1) { + fprintf(stderr, " : %0.0f Hz\n", dac_freq); + } else + if (sscanf(argv[i], "cycle_delay:%lf", &cycle_delay) == 1) { + fprintf(stderr, "cycle_delay=%lf sec\n", cycle_delay); + } else + if (strcmp(argv[i], "once") == 0) { + cycle_mode = 0; + fprintf(stderr, "cycle_mode=0\n"); + } + } +} + +#define BUF_SIZE (64 * 1024) + +#define CH_ENABLED 2 + +void show_help(char *name) { + fprintf(stderr, + "Usage: %s [dac_freq:500000] [cycle_delay:0.0001] [once] input.file\n" + "\tdac_freq: DAC freq in Hz\n" + "\tcycle_delay: delay DAC output in seconds before new cycle start\n" + "Select module by ip: %s [E16:192.168.0.1] [dac_freq:500000] [once] input.file\n" + "\nTest input file (2 DAC):\n" + "\t0.000000; -5.000000\n" + "\t1.000000; -4.000000\n" + "\t2.000000; -3.000000\n" + "\t3.000000; -2.000000\n" + "\t4.000000; -1.000000\n" + "\t5.000000; -0.000000\n" + "\t4.000000; -1.000000\n" + "\t3.000000; -2.000000\n" + "\t2.000000; -3.000000\n" + "\t1.000000; -4.000000\n" + , name, name); +} + +int out_dac_from_file(t_x502_hnd hnd, FILE* f); + +int main(int argc, char **argv) { + int32_t err = 0; + uint32_t ver; + t_x502_hnd hnd = NULL; + FILE* f; +#ifndef _WIN32 + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + /* Linux , + */ + sa.sa_handler = f_abort_handler; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); +#endif +#ifdef _WIN32 + /* , - CP1251 OEM */ + setlocale(LC_CTYPE, ""); +#endif + + if (argc == 1) { + show_help(argv[0]); + return 1; + } + + /********** , ******************/ + hnd = select_dev_from_list(argc, argv, 0); + + if (hnd == NULL) { + fprintf(stderr, "Error! Device not found!\n"); + return 1; + } + + parse_params(argc, argv); + + /* - */ + + err = f_setup_params(hnd); + if (err) { + return err; + } + + /********************************** **************************/ + + /* ( + ), + L502_PrepareData */ + err = X502_StreamsEnable(hnd, X502_STREAM_ALL_OUT); + if (err != X502_ERR_OK) { + fprintf(stderr, " (%d): %s!", err, + X502_GetErrorString(err)); + } + + f = fopen(argv[argc - 1], "rb"); + if (!f) { + fprintf(stderr, "Could not open file '%s' error %d\n", argv[argc - 1], errno); + show_help(argv[0]); + return 1; + } + + err = out_dac_from_file(hnd, f); + fclose(f); + + /* */ + X502_Close(hnd); + /* */ + X502_Free(hnd); + + return err; +} + +static struct timespec start_time; +static uint32_t* out_buf; +static int dac_size; +static double *dac_data[CH_ENABLED]; + +int send_data(t_x502_hnd hnd, uint32_t *send_ptr, uint32_t send_size) { + static int started = 0; + static uint32_t g_snd_cnt = 0; + struct timespec cur_time; + double spent_secs; + struct timespec spent_time; + + while (send_size && !f_out) { + int32_t sent; + +#ifdef _WIN32 + /* */ + if (_kbhit()) { + f_out = 1; + } +#endif + + sent = X502_Send(hnd, send_ptr, send_size, SEND_TOUT); + if (sent < 0) { + fprintf(stderr, "Errror: X502_Send ret = %d\n", sent); + return sent; + } + if (f_out) { + return 0; + } + g_snd_cnt += sent; + send_size -= sent; + send_ptr += sent; + + if (started == 0) { + int err; + + started = 1; + err = X502_StreamsStart(hnd); + if (err) { + fprintf(stderr, "Error: X502_StreamsStart ret = %d\n", err); + return err; + } + } + } + + clock_gettime(CLOCK_MONOTONIC, &cur_time); + + timespec_diff(&cur_time, &start_time, &spent_time); + spent_secs = timespec_to_double(&spent_time); + + if (spent_secs > 5) { + fprintf(stderr, "snd speed=%f wrds/sec\n", (g_snd_cnt) / (spent_secs)); + g_snd_cnt = 0; + start_time = cur_time; + } + return send_size; +} + +int send_dac_data(t_x502_hnd hnd) { + int err; + + if (dac_size != DAC_BUF_SIZE) { + return 0; + } + +#if 0 + for (int i = 0; i < dac_size; i++){ + fprintf(stderr, "[%d] %f; %f\n", i, dac_data[0][i], dac_data[1][i]); + } +#endif + // TODO: LTA37 PrepareData2() + err = X502_PrepareData(hnd, + dac_data[0], + dac_data[1], + NULL, + dac_size, X502_DAC_FLAGS_VOLT | X502_DAC_FLAGS_CALIBR, + out_buf); + + if (err) { + fprintf(stderr, "Error: X502_PrepareData ret = %d\n", err); + return err; + } + + err = send_data(hnd, out_buf, dac_size * CH_ENABLED); + + dac_size = 0; + + return err; +} + +int out_dac_from_file(t_x502_hnd hnd, FILE* f) { + int32_t err; + char *buf; + int items_read; + double dac_val; + char *read_start; + int cntr = 0; + int dac_ch = 0; + bool newline = false; + bool comment_start = false; + bool data_added = false; + char *last_endptr; + double last_dac_data[CH_ENABLED]; + + for (int ch = 0; ch < CH_ENABLED; ch++) { + dac_data[ch] = (double*)malloc(sizeof(double) * DAC_BUF_SIZE); + if (!dac_data[ch]) { + fprintf(stderr, "Out of memory\n"); + return 1; + } + } + + out_buf = (uint32_t*)malloc(sizeof(uint32_t) * DAC_BUF_SIZE * CH_ENABLED); + buf = (char*)malloc(BUF_SIZE); + if (!out_buf || !buf) { + fprintf(stderr, "Out of memory\n"); + return 1; + } + + read_start = buf; + last_endptr = &buf[BUF_SIZE]; + + clock_gettime(CLOCK_MONOTONIC, &start_time); + + while (!f_out) { + size_t buf_ready = (read_start - buf); + +#ifdef _WIN32 + /* */ + if (_kbhit()) { + f_out = 1; + } +#endif + + if (feof(f) && cycle_mode) { + int delay_cntr = cycle_delay * dac_freq; + do { + for (; (dac_size != DAC_BUF_SIZE) && delay_cntr; dac_size++, delay_cntr--) { + for (int ch = 0; ch < CH_ENABLED; ch++) { + dac_data[ch][dac_size] = last_dac_data[ch]; + } + } + if ((err = send_dac_data(hnd)) < 0) { + return err; + } + } while(delay_cntr); + } + + if (feof(f)) { + if (cycle_mode) { + fseek(f, 0, SEEK_SET); + } else { + break; + } + } + + items_read = fread(read_start, 1, BUF_SIZE - buf_ready, f); + dbg_printf("read_start=::::%.*s::::\n", (int)buf_ready, buf); + dbg_printf("read=%d '''''%.*s'''''\n", items_read, items_read, read_start); + + for (char *ptr = buf, *endptr = buf; ; ptr = endptr) { + char *buf_end = &buf[buf_ready + items_read]; + + dac_val = strtod(ptr, &endptr); + if (endptr >= buf_end) { + memmove(buf, last_endptr, buf_end - last_endptr); + read_start = buf + (buf_end - last_endptr); + break; + } else + if (endptr == ptr) { + endptr++; + if (*ptr == '\n') { + newline = true; + comment_start = false; + } + if (*ptr == '#') { + comment_start = true; + } + } else { + last_endptr = endptr; + for (char *n_ptr = ptr; n_ptr < endptr; n_ptr++) { + if (*n_ptr == '\n') { + newline = true; + comment_start = false; + break; + } + } + if (comment_start) { + continue; + } + if (newline) { + dac_ch = 0; + } + + if (dac_ch >= CH_ENABLED) { + fprintf(stderr, "dac_ch = %d >= %d (CH_ENABLED)\n", dac_ch, CH_ENABLED); + dac_ch %= CH_ENABLED; + } + + if (newline && data_added) { + data_added = false; + dac_size++; + for (int ch = 0; ch < CH_ENABLED; ch++) { + dac_data[ch][dac_size] = dac_data[ch][dac_size - 1]; + } + } + + data_added = true; + newline = false; + + dbg_printf("dac_val=%lf cntr=%d\n", dac_val, cntr); + + if ((err = send_dac_data(hnd)) < 0) { + return err; + } + + dac_data[dac_ch][dac_size] = dac_val; + last_dac_data[dac_ch] = dac_val; + dac_ch++; + } + } + } + return 0; +} diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..955ba2f --- /dev/null +++ b/main.cpp @@ -0,0 +1,1000 @@ +#ifdef _WIN32 + #ifndef NOMINMAX + #define NOMINMAX + #endif +#endif + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4995) +#endif +#include "x502api.h" +#include "e502api.h" +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +enum class StopMode { + TargetFrames, + DiSyn2Rise, + DiSyn2Fall +}; + +struct Config { + std::string serial; + std::optional ip_addr; + + uint32_t mode = X502_LCH_MODE_DIFF; + uint32_t range = X502_ADC_RANGE_5; + uint32_t ch1 = 2; + uint32_t ch2 = 3; + + double sample_clock_hz = 2000000.0; + double duration_ms = 40.0; + + uint32_t sync_mode = X502_SYNC_EXTERNAL_MASTER; + uint32_t sync_start_mode = X502_SYNC_DI_SYN1_RISE; + StopMode stop_mode = StopMode::TargetFrames; + + uint32_t recv_block_words = 8192; + uint32_t recv_timeout_ms = 100; + uint32_t start_wait_ms = 10000; + uint32_t input_buffer_words = 262144; + uint32_t input_step_words = 8192; + + bool pullup_syn1 = false; + bool pullup_syn2 = false; + bool pulldown_conv_in = false; + bool pulldown_start_in = false; + + std::string csv_path = "capture.csv"; + std::string svg_path = "capture.svg"; +}; + +[[noreturn]] void fail(const std::string& message) { + throw std::runtime_error(message); +} + +std::string trim_copy(const std::string& text) { + const auto first = text.find_first_not_of(" \t\r\n"); + if (first == std::string::npos) { + return {}; + } + const auto last = text.find_last_not_of(" \t\r\n"); + return text.substr(first, last - first + 1); +} + +bool starts_with(const std::string& value, const std::string& prefix) { + return value.rfind(prefix, 0) == 0; +} + +uint32_t parse_u32(const std::string& text, const std::string& field_name) { + const std::string clean = trim_copy(text); + char* end = nullptr; + const auto value = std::strtoull(clean.c_str(), &end, 0); + if ((end == clean.c_str()) || (*end != '\0') || (value > std::numeric_limits::max())) { + fail("Invalid integer for " + field_name + ": " + text); + } + return static_cast(value); +} + +double parse_double(const std::string& text, const std::string& field_name) { + const std::string clean = trim_copy(text); + char* end = nullptr; + const double value = std::strtod(clean.c_str(), &end); + if ((end == clean.c_str()) || (*end != '\0') || !std::isfinite(value)) { + fail("Invalid floating point value for " + field_name + ": " + text); + } + return value; +} + +uint32_t parse_ipv4(const std::string& text) { + std::array parts{}; + std::stringstream ss(text); + std::string token; + for (std::size_t i = 0; i < parts.size(); ++i) { + if (!std::getline(ss, token, '.')) { + fail("Invalid IPv4 address: " + text); + } + parts[i] = parse_u32(token, "ip"); + if (parts[i] > 255) { + fail("IPv4 byte out of range: " + token); + } + } + if (std::getline(ss, token, '.')) { + fail("Invalid IPv4 address: " + text); + } + return (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]; +} + +std::string ipv4_to_string(uint32_t ip_addr) { + std::ostringstream out; + out << ((ip_addr >> 24) & 0xFF) << '.' + << ((ip_addr >> 16) & 0xFF) << '.' + << ((ip_addr >> 8) & 0xFF) << '.' + << (ip_addr & 0xFF); + return out.str(); +} + +uint32_t parse_range(const std::string& text) { + const double value = parse_double(text, "range"); + if (std::fabs(value - 10.0) < 1e-9) { + return X502_ADC_RANGE_10; + } + if (std::fabs(value - 5.0) < 1e-9) { + return X502_ADC_RANGE_5; + } + if (std::fabs(value - 2.0) < 1e-9) { + return X502_ADC_RANGE_2; + } + if (std::fabs(value - 1.0) < 1e-9) { + return X502_ADC_RANGE_1; + } + if (std::fabs(value - 0.5) < 1e-9) { + return X502_ADC_RANGE_05; + } + if (std::fabs(value - 0.2) < 1e-9) { + return X502_ADC_RANGE_02; + } + fail("Unsupported E-502 range: " + text); +} + +double range_to_volts(uint32_t range) { + switch (range) { + case X502_ADC_RANGE_10: + return 10.0; + case X502_ADC_RANGE_5: + return 5.0; + case X502_ADC_RANGE_2: + return 2.0; + case X502_ADC_RANGE_1: + return 1.0; + case X502_ADC_RANGE_05: + return 0.5; + case X502_ADC_RANGE_02: + return 0.2; + default: + fail("Unknown ADC range enum"); + } +} + +uint32_t parse_mode(const std::string& text) { + const std::string value = trim_copy(text); + if ((value == "comm") || (value == "gnd") || (value == "single_ended")) { + return X502_LCH_MODE_COMM; + } + if ((value == "diff") || (value == "differential")) { + return X502_LCH_MODE_DIFF; + } + fail("Unsupported input mode: " + text); +} + +uint32_t parse_sync_mode(const std::string& text) { + const std::string value = trim_copy(text); + if ((value == "conv_in") || (value == "start_in") || (value == "external_master")) { + return X502_SYNC_EXTERNAL_MASTER; + } + if (value == "di_syn1_rise") { + return X502_SYNC_DI_SYN1_RISE; + } + if (value == "di_syn1_fall") { + return X502_SYNC_DI_SYN1_FALL; + } + if (value == "di_syn2_rise") { + return X502_SYNC_DI_SYN2_RISE; + } + if (value == "di_syn2_fall") { + return X502_SYNC_DI_SYN2_FALL; + } + if ((value == "internal") || (value == "immediate")) { + return X502_SYNC_INTERNAL; + } + fail("Unsupported sync mode: " + text); +} + +std::string sync_mode_to_string(uint32_t mode, bool for_start) { + switch (mode) { + case X502_SYNC_INTERNAL: + return for_start ? "immediate" : "internal"; + case X502_SYNC_EXTERNAL_MASTER: + return for_start ? "start_in" : "conv_in"; + case X502_SYNC_DI_SYN1_RISE: + return "di_syn1_rise"; + case X502_SYNC_DI_SYN1_FALL: + return "di_syn1_fall"; + case X502_SYNC_DI_SYN2_RISE: + return "di_syn2_rise"; + case X502_SYNC_DI_SYN2_FALL: + return "di_syn2_fall"; + default: + return "unknown"; + } +} + +StopMode parse_stop_mode(const std::string& text) { + const std::string value = trim_copy(text); + if ((value == "frames") || (value == "duration") || (value == "none")) { + return StopMode::TargetFrames; + } + if (value == "di_syn2_rise") { + return StopMode::DiSyn2Rise; + } + if (value == "di_syn2_fall") { + return StopMode::DiSyn2Fall; + } + fail("Unsupported stop mode: " + text); +} + +std::string stop_mode_to_string(StopMode mode) { + switch (mode) { + case StopMode::TargetFrames: + return "target_frames"; + case StopMode::DiSyn2Rise: + return "di_syn2_rise"; + case StopMode::DiSyn2Fall: + return "di_syn2_fall"; + default: + return "unknown"; + } +} + +bool sync_uses_di_syn1(uint32_t mode) { + return (mode == X502_SYNC_DI_SYN1_RISE) || (mode == X502_SYNC_DI_SYN1_FALL); +} + +bool sync_uses_di_syn2(uint32_t mode) { + return (mode == X502_SYNC_DI_SYN2_RISE) || (mode == X502_SYNC_DI_SYN2_FALL); +} + +std::string phy_channel_name(uint32_t mode, uint32_t phy_ch) { + if (mode == X502_LCH_MODE_DIFF) { + return "X" + std::to_string(phy_ch + 1) + "-Y" + std::to_string(phy_ch + 1); + } + if (phy_ch < 16) { + return "X" + std::to_string(phy_ch + 1); + } + if (phy_ch < 32) { + return "Y" + std::to_string((phy_ch - 16) + 1); + } + return "CH" + std::to_string(phy_ch); +} + +void print_help(const char* exe_name) { + std::cout + << "Usage:\n" + << " " << exe_name << " [serial:SN] [ip:192.168.0.10] [ch1:2] [ch2:3]\n" + << " [mode:diff|comm] [range:5] [clock:conv_in]\n" + << " [start:di_syn1_rise] [stop:frames] [sample_clock_hz:2000000]\n" + << " [duration_ms:40] [csv:capture.csv] [svg:capture.svg]\n" + << " [recv_block:8192] [start_wait_ms:10000]\n" + << " [pullup_syn1] [pullup_syn2] [pulldown_conv_in] [pulldown_start_in]\n" + << "\n" + << "Defaults for E-502:\n" + << " ch1:2, ch2:3 -> X3-Y3 and X4-Y4\n" + << " mode:diff -> differential measurement\n" + << " range:5 -> +/-5 V range\n" + << " clock:conv_in -> external sample clock on CONV_IN\n" + << " start:di_syn1_rise-> start on DI_SYN1 rising edge\n" + << " stop:frames -> stop after duration_ms worth of frames\n" + << " duration_ms:40 -> capture one 40 ms chirp or max length when stop is external\n" + << "\n" + << "Differential physical channel mapping:\n" + << " 0..15 -> X1-Y1 .. X16-Y16\n" + << "\n" + << "Common-ground physical channel mapping:\n" + << " 0..15 -> X1..X16\n" + << " 16..31 -> Y1..Y16\n" + << "\n" + << "Useful sync lines on E-502:\n" + << " clock: conv_in | di_syn1_rise | di_syn1_fall | di_syn2_rise | di_syn2_fall\n" + << " start: immediate | start_in | di_syn1_rise | di_syn1_fall | di_syn2_rise | di_syn2_fall\n" + << " stop: frames | di_syn2_rise | di_syn2_fall\n" + << "\n" + << "Stop on DI_SYN2 is polled asynchronously via X502_AsyncInDig(), so ADC stream stays\n" + << "ADC-only. For reliable stop detection hold DI_SYN2 active until the program stops.\n" + << "\n" + << "Recommended working example:\n" + << " " << exe_name + << " clock:di_syn1_rise start:start_in stop:di_syn2_rise sample_clock_hz:2000000" + << " duration_ms:40 csv:chirp.csv svg:chirp.svg\n"; +} + +Config parse_args(int argc, char** argv) { + Config cfg; + + for (int i = 1; i < argc; ++i) { + const std::string arg = argv[i]; + if ((arg == "help") || (arg == "--help") || (arg == "-h")) { + print_help(argv[0]); + std::exit(0); + } + if (arg == "pullup_syn1") { + cfg.pullup_syn1 = true; + continue; + } + if (arg == "pullup_syn2") { + cfg.pullup_syn2 = true; + continue; + } + if (arg == "pulldown_conv_in") { + cfg.pulldown_conv_in = true; + continue; + } + if (arg == "pulldown_start_in") { + cfg.pulldown_start_in = true; + continue; + } + if (starts_with(arg, "serial:")) { + cfg.serial = arg.substr(7); + continue; + } + if (starts_with(arg, "ip:")) { + cfg.ip_addr = parse_ipv4(arg.substr(3)); + continue; + } + if (starts_with(arg, "mode:")) { + cfg.mode = parse_mode(arg.substr(5)); + continue; + } + if (starts_with(arg, "range:")) { + cfg.range = parse_range(arg.substr(6)); + continue; + } + if (starts_with(arg, "ch1:")) { + cfg.ch1 = parse_u32(arg.substr(4), "ch1"); + continue; + } + if (starts_with(arg, "ch2:")) { + cfg.ch2 = parse_u32(arg.substr(4), "ch2"); + continue; + } + if (starts_with(arg, "clock:")) { + cfg.sync_mode = parse_sync_mode(arg.substr(6)); + continue; + } + if (starts_with(arg, "start:")) { + cfg.sync_start_mode = parse_sync_mode(arg.substr(6)); + continue; + } + if (starts_with(arg, "stop:")) { + cfg.stop_mode = parse_stop_mode(arg.substr(5)); + continue; + } + if (starts_with(arg, "sample_clock_hz:")) { + cfg.sample_clock_hz = parse_double(arg.substr(16), "sample_clock_hz"); + continue; + } + if (starts_with(arg, "duration_ms:")) { + cfg.duration_ms = parse_double(arg.substr(12), "duration_ms"); + continue; + } + if (starts_with(arg, "recv_block:")) { + cfg.recv_block_words = parse_u32(arg.substr(11), "recv_block"); + continue; + } + if (starts_with(arg, "recv_timeout_ms:")) { + cfg.recv_timeout_ms = parse_u32(arg.substr(16), "recv_timeout_ms"); + continue; + } + if (starts_with(arg, "start_wait_ms:")) { + cfg.start_wait_ms = parse_u32(arg.substr(14), "start_wait_ms"); + continue; + } + if (starts_with(arg, "buffer_words:")) { + cfg.input_buffer_words = parse_u32(arg.substr(13), "buffer_words"); + continue; + } + if (starts_with(arg, "step_words:")) { + cfg.input_step_words = parse_u32(arg.substr(11), "step_words"); + continue; + } + if (starts_with(arg, "csv:")) { + cfg.csv_path = arg.substr(4); + continue; + } + if (starts_with(arg, "svg:")) { + cfg.svg_path = arg.substr(4); + continue; + } + fail("Unknown argument: " + arg); + } + + if (cfg.duration_ms <= 0.0) { + fail("duration_ms must be > 0"); + } + if (cfg.sample_clock_hz <= 0.0) { + fail("sample_clock_hz must be > 0"); + } + if (cfg.recv_block_words == 0) { + fail("recv_block must be > 0"); + } + if (cfg.input_step_words == 0) { + cfg.input_step_words = cfg.recv_block_words; + } + if (cfg.input_buffer_words < cfg.recv_block_words) { + cfg.input_buffer_words = cfg.recv_block_words; + } + if (sync_uses_di_syn1(cfg.sync_mode) && sync_uses_di_syn1(cfg.sync_start_mode)) { + fail("clock and start cannot both use DI_SYN1; use start_in or immediate start"); + } + if (sync_uses_di_syn2(cfg.sync_mode) && sync_uses_di_syn2(cfg.sync_start_mode)) { + fail("clock and start cannot both use DI_SYN2; use start_in or immediate start"); + } + if ((cfg.stop_mode != StopMode::TargetFrames) && sync_uses_di_syn2(cfg.sync_mode)) { + fail("DI_SYN2 cannot be used simultaneously for clock and stop"); + } + if ((cfg.stop_mode != StopMode::TargetFrames) && sync_uses_di_syn2(cfg.sync_start_mode)) { + fail("DI_SYN2 cannot be used simultaneously for start and stop"); + } + + if (cfg.mode == X502_LCH_MODE_DIFF) { + if ((cfg.ch1 >= X502_ADC_DIFF_CH_CNT) || (cfg.ch2 >= X502_ADC_DIFF_CH_CNT)) { + fail("For differential mode E-502 channels must be in range 0..15"); + } + } else { + if ((cfg.ch1 >= X502_ADC_COMM_CH_CNT) || (cfg.ch2 >= X502_ADC_COMM_CH_CNT)) { + fail("For common-ground mode E-502 channels must be in range 0..31"); + } + } + + return cfg; +} + +template +Fn load_symbol(HMODULE module, const char* name) { + const auto addr = GetProcAddress(module, name); + if (addr == nullptr) { + fail(std::string("GetProcAddress failed for symbol: ") + name); + } + return reinterpret_cast(addr); +} + +struct Api { + HMODULE x502_module = nullptr; + HMODULE e502_module = nullptr; + + decltype(&X502_Create) Create = nullptr; + decltype(&X502_Free) Free = nullptr; + decltype(&X502_Close) Close = nullptr; + decltype(&X502_GetErrorString) GetErrorString = nullptr; + decltype(&X502_GetDevInfo2) GetDevInfo2 = nullptr; + decltype(&X502_SetMode) SetMode = nullptr; + decltype(&X502_StreamsStop) StreamsStop = nullptr; + decltype(&X502_StreamsDisable) StreamsDisable = nullptr; + decltype(&X502_SetSyncMode) SetSyncMode = nullptr; + decltype(&X502_SetSyncStartMode) SetSyncStartMode = nullptr; + decltype(&X502_SetLChannelCount) SetLChannelCount = nullptr; + decltype(&X502_SetLChannel) SetLChannel = nullptr; + decltype(&X502_SetAdcFreqDivider) SetAdcFreqDivider = nullptr; + decltype(&X502_SetAdcInterframeDelay) SetAdcInterframeDelay = nullptr; + decltype(&X502_SetStreamBufSize) SetStreamBufSize = nullptr; + decltype(&X502_SetStreamStep) SetStreamStep = nullptr; + decltype(&X502_SetDigInPullup) SetDigInPullup = nullptr; + decltype(&X502_SetExtRefFreqValue) SetExtRefFreqValue = nullptr; + decltype(&X502_Configure) Configure = nullptr; + decltype(&X502_StreamsEnable) StreamsEnable = nullptr; + decltype(&X502_StreamsStart) StreamsStart = nullptr; + decltype(&X502_AsyncInDig) AsyncInDig = nullptr; + decltype(&X502_Recv) Recv = nullptr; + decltype(&X502_ProcessAdcData) ProcessAdcData = nullptr; + + decltype(&E502_OpenUsb) OpenUsb = nullptr; + decltype(&E502_OpenByIpAddr) OpenByIpAddr = nullptr; + + Api() { + x502_module = LoadLibraryA("x502api.dll"); + if (x502_module == nullptr) { + fail("Cannot load x502api.dll"); + } + e502_module = LoadLibraryA("e502api.dll"); + if (e502_module == nullptr) { + fail("Cannot load e502api.dll"); + } + + Create = load_symbol(x502_module, "X502_Create"); + Free = load_symbol(x502_module, "X502_Free"); + Close = load_symbol(x502_module, "X502_Close"); + GetErrorString = load_symbol(x502_module, "X502_GetErrorString"); + GetDevInfo2 = load_symbol(x502_module, "X502_GetDevInfo2"); + SetMode = load_symbol(x502_module, "X502_SetMode"); + StreamsStop = load_symbol(x502_module, "X502_StreamsStop"); + StreamsDisable = load_symbol(x502_module, "X502_StreamsDisable"); + SetSyncMode = load_symbol(x502_module, "X502_SetSyncMode"); + SetSyncStartMode = load_symbol(x502_module, "X502_SetSyncStartMode"); + SetLChannelCount = load_symbol(x502_module, "X502_SetLChannelCount"); + SetLChannel = load_symbol(x502_module, "X502_SetLChannel"); + SetAdcFreqDivider = load_symbol(x502_module, "X502_SetAdcFreqDivider"); + SetAdcInterframeDelay = load_symbol(x502_module, "X502_SetAdcInterframeDelay"); + SetStreamBufSize = load_symbol(x502_module, "X502_SetStreamBufSize"); + SetStreamStep = load_symbol(x502_module, "X502_SetStreamStep"); + SetDigInPullup = load_symbol(x502_module, "X502_SetDigInPullup"); + SetExtRefFreqValue = load_symbol(x502_module, "X502_SetExtRefFreqValue"); + Configure = load_symbol(x502_module, "X502_Configure"); + StreamsEnable = load_symbol(x502_module, "X502_StreamsEnable"); + StreamsStart = load_symbol(x502_module, "X502_StreamsStart"); + AsyncInDig = load_symbol(x502_module, "X502_AsyncInDig"); + Recv = load_symbol(x502_module, "X502_Recv"); + ProcessAdcData = load_symbol(x502_module, "X502_ProcessAdcData"); + + OpenUsb = load_symbol(e502_module, "E502_OpenUsb"); + OpenByIpAddr = load_symbol(e502_module, "E502_OpenByIpAddr"); + } + + ~Api() { + if (e502_module != nullptr) { + FreeLibrary(e502_module); + } + if (x502_module != nullptr) { + FreeLibrary(x502_module); + } + } +}; + +std::string x502_error(const Api& api, int32_t err) { + const char* text = api.GetErrorString ? api.GetErrorString(err) : nullptr; + std::ostringstream out; + out << "err=" << err; + if ((text != nullptr) && (*text != '\0')) { + out << " (" << text << ")"; + } + return out.str(); +} + +void expect_ok(const Api& api, int32_t err, const std::string& what) { + if (err != X502_ERR_OK) { + fail(what + ": " + x502_error(api, err)); + } +} + +constexpr uint32_t kE502DiSyn2Mask = + (static_cast(1U) << 13U) | (static_cast(1U) << 17U); + +bool read_di_syn2_level(const Api& api, t_x502_hnd hnd) { + uint32_t din = 0; + expect_ok(api, api.AsyncInDig(hnd, &din), "Read digital inputs"); + return (din & kE502DiSyn2Mask) != 0; +} + +struct DeviceHandle { + const Api& api; + t_x502_hnd hnd = nullptr; + bool opened = false; + bool streams_started = false; + + explicit DeviceHandle(const Api& api_ref) : api(api_ref), hnd(api.Create()) { + if (hnd == nullptr) { + fail("X502_Create failed"); + } + } + + ~DeviceHandle() { + if (hnd != nullptr) { + if (streams_started) { + api.StreamsStop(hnd); + } + if (opened) { + api.Close(hnd); + } + api.Free(hnd); + } + } +}; + +void print_device_info(const t_x502_info& info) { + std::cout << "Device: " << info.name << "\n" + << "Serial: " << info.serial << "\n" + << "FPGA version: " << static_cast(info.fpga_ver >> 8) << "." + << static_cast(info.fpga_ver & 0xFF) << "\n" + << "PLDA version: " << static_cast(info.plda_ver) << "\n" + << "Board revision: " << static_cast(info.board_rev) << "\n" + << "MCU firmware: " << info.mcu_firmware_ver << "\n"; +} + +struct PlotPoint { + std::size_t sample_index = 0; + double value = 0.0; +}; + +std::vector build_min_max_trace(const std::vector& data, std::size_t max_columns) { + std::vector result; + if (data.empty()) { + return result; + } + + const std::size_t bucket_size = std::max(1, (data.size() + max_columns - 1) / max_columns); + result.reserve(max_columns * 2); + + for (std::size_t begin = 0; begin < data.size(); begin += bucket_size) { + const std::size_t end = std::min(begin + bucket_size, data.size()); + std::size_t min_index = begin; + std::size_t max_index = begin; + for (std::size_t i = begin + 1; i < end; ++i) { + if (data[i] < data[min_index]) { + min_index = i; + } + if (data[i] > data[max_index]) { + max_index = i; + } + } + + if (min_index <= max_index) { + result.push_back({min_index, data[min_index]}); + if (max_index != min_index) { + result.push_back({max_index, data[max_index]}); + } + } else { + result.push_back({max_index, data[max_index]}); + result.push_back({min_index, data[min_index]}); + } + } + + if (result.back().sample_index != (data.size() - 1)) { + result.push_back({data.size() - 1, data.back()}); + } + return result; +} + +std::string polyline_points(const std::vector& trace, + double max_time_s, + double y_min, + double y_max, + double left, + double top, + double width, + double height) { + std::ostringstream out; + out << std::fixed << std::setprecision(3); + const double y_span = std::max(1e-12, y_max - y_min); + const std::size_t max_index = trace.empty() ? 1 : trace.back().sample_index; + const double time_scale = (max_time_s > 0.0) ? max_time_s : 1.0; + + for (const auto& point : trace) { + const double time_s = (max_index == 0) + ? 0.0 + : (static_cast(point.sample_index) / static_cast(max_index)) * time_scale; + const double x = left + (time_s / time_scale) * width; + const double y = top + height - ((point.value - y_min) / y_span) * height; + out << x << "," << y << " "; + } + return out.str(); +} + +void write_csv(const std::string& path, + const std::vector& ch1, + const std::vector& ch2, + double frame_freq_hz) { + std::ofstream file(path, std::ios::binary); + if (!file) { + fail("Cannot open CSV for writing: " + path); + } + + file << "frame_index,time_s,ch1_v,ch2_v\n"; + file << std::fixed << std::setprecision(9); + const std::size_t frames = std::min(ch1.size(), ch2.size()); + for (std::size_t i = 0; i < frames; ++i) { + const double time_s = static_cast(i) / frame_freq_hz; + file << i << "," << time_s << "," << ch1[i] << "," << ch2[i] << "\n"; + } +} + +void write_svg(const std::string& path, + const std::vector& ch1, + const std::vector& ch2, + double frame_freq_hz, + double nominal_range_v) { + std::ofstream file(path, std::ios::binary); + if (!file) { + fail("Cannot open SVG for writing: " + path); + } + + const std::size_t frames = std::min(ch1.size(), ch2.size()); + const double total_time_s = (frames > 1) ? (static_cast(frames - 1) / frame_freq_hz) : 0.0; + + double min_y = std::numeric_limits::infinity(); + double max_y = -std::numeric_limits::infinity(); + for (double v : ch1) { + min_y = std::min(min_y, v); + max_y = std::max(max_y, v); + } + for (double v : ch2) { + min_y = std::min(min_y, v); + max_y = std::max(max_y, v); + } + if (!std::isfinite(min_y) || !std::isfinite(max_y) || (min_y == max_y)) { + min_y = -nominal_range_v; + max_y = nominal_range_v; + } else { + const double pad = std::max(0.1, (max_y - min_y) * 0.08); + min_y -= pad; + max_y += pad; + } + + const auto trace1 = build_min_max_trace(ch1, 1800); + const auto trace2 = build_min_max_trace(ch2, 1800); + + const double width = 1400.0; + const double height = 800.0; + const double left = 90.0; + const double right = 40.0; + const double top = 40.0; + const double bottom = 80.0; + const double plot_w = width - left - right; + const double plot_h = height - top - bottom; + const double zero_y = top + plot_h - ((0.0 - min_y) / std::max(1e-12, max_y - min_y)) * plot_h; + + file << "\n"; + file << " \n"; + file << " \n"; + + for (int i = 0; i <= 10; ++i) { + const double x = left + (plot_w * i / 10.0); + const double y = top + (plot_h * i / 10.0); + file << " \n"; + file << " \n"; + } + + if ((0.0 >= min_y) && (0.0 <= max_y)) { + file << " \n"; + } + + file << " \n"; + file << " \n"; + + file << " E-502 capture: CH1 and CH2\n"; + file << " time, s\n"; + file << " V\n"; + + file << std::fixed << std::setprecision(6); + for (int i = 0; i <= 10; ++i) { + const double x = left + (plot_w * i / 10.0); + const double t = total_time_s * i / 10.0; + file << " " << t << "\n"; + + const double y = top + plot_h - (plot_h * i / 10.0); + const double v = min_y + (max_y - min_y) * i / 10.0; + file << " " << v << "\n"; + } + + const double legend_y = height - 48.0; + file << " \n"; + file << " CH1\n"; + file << " \n"; + file << " CH2\n"; + file << "\n"; +} + +int run(const Config& cfg) { + Api api; + DeviceHandle device(api); + + int32_t err = X502_ERR_OK; + if (cfg.ip_addr.has_value()) { + err = api.OpenByIpAddr(device.hnd, *cfg.ip_addr, 0, 5000); + } else { + err = api.OpenUsb(device.hnd, cfg.serial.empty() ? nullptr : cfg.serial.c_str()); + } + expect_ok(api, err, "Open device"); + device.opened = true; + + t_x502_info info{}; + err = api.GetDevInfo2(device.hnd, &info, sizeof(info)); + expect_ok(api, err, "Get device info"); + print_device_info(info); + + expect_ok(api, api.SetMode(device.hnd, X502_MODE_FPGA), "Set FPGA mode"); + api.StreamsStop(device.hnd); + api.StreamsDisable(device.hnd, X502_STREAM_ALL_IN | X502_STREAM_ALL_OUT); + + expect_ok(api, api.SetSyncMode(device.hnd, cfg.sync_mode), "Set sync mode"); + expect_ok(api, api.SetSyncStartMode(device.hnd, cfg.sync_start_mode), "Set sync start mode"); + + if (cfg.sync_mode != X502_SYNC_INTERNAL) { + const int32_t ext_ref_err = api.SetExtRefFreqValue(device.hnd, cfg.sample_clock_hz); + if (ext_ref_err != X502_ERR_OK) { + if (cfg.sample_clock_hz <= 1500000.0) { + expect_ok(api, ext_ref_err, "Set external reference frequency"); + } else { + std::cerr << "Warning: X502_SetExtRefFreqValue(" << cfg.sample_clock_hz + << ") failed, continuing with manual divider configuration: " + << x502_error(api, ext_ref_err) << "\n"; + } + } + } + + expect_ok(api, api.SetLChannelCount(device.hnd, 2), "Set logical channel count"); + expect_ok(api, api.SetLChannel(device.hnd, 0, cfg.ch1, cfg.mode, cfg.range, 1), "Set logical channel 0"); + expect_ok(api, api.SetLChannel(device.hnd, 1, cfg.ch2, cfg.mode, cfg.range, 1), "Set logical channel 1"); + expect_ok(api, api.SetAdcFreqDivider(device.hnd, 1), "Set ADC frequency divider"); + expect_ok(api, api.SetAdcInterframeDelay(device.hnd, 0), "Set ADC interframe delay"); + expect_ok(api, api.SetStreamBufSize(device.hnd, X502_STREAM_CH_IN, cfg.input_buffer_words), "Set input buffer size"); + expect_ok(api, api.SetStreamStep(device.hnd, X502_STREAM_CH_IN, cfg.input_step_words), "Set input stream step"); + + uint32_t pullups = 0; + if (cfg.pullup_syn1) { + pullups |= X502_PULLUPS_DI_SYN1; + } + if (cfg.pullup_syn2) { + pullups |= X502_PULLUPS_DI_SYN2; + } + if (cfg.pulldown_conv_in) { + pullups |= X502_PULLDOWN_CONV_IN; + } + if (cfg.pulldown_start_in) { + pullups |= X502_PULLDOWN_START_IN; + } + expect_ok(api, api.SetDigInPullup(device.hnd, pullups), "Set digital input pullups/pulldowns"); + + expect_ok(api, api.Configure(device.hnd, 0), "Configure device"); + expect_ok(api, api.StreamsEnable(device.hnd, X502_STREAM_ADC), "Enable ADC stream"); + + const double frame_freq_hz = cfg.sample_clock_hz / 2.0; + const std::size_t target_frames = std::max( + 1, static_cast(std::llround((cfg.duration_ms / 1000.0) * frame_freq_hz))); + + std::cout << "Capture settings:\n" + << " clock source: " << sync_mode_to_string(cfg.sync_mode, false) << "\n" + << " start source: " << sync_mode_to_string(cfg.sync_start_mode, true) << "\n" + << " stop source: " << stop_mode_to_string(cfg.stop_mode) << "\n" + << " sample clock: " << cfg.sample_clock_hz << " Hz\n" + << " per-channel frame rate: " << frame_freq_hz << " Hz\n" + << " duration: " << cfg.duration_ms << " ms\n" + << " channel 1: " << phy_channel_name(cfg.mode, cfg.ch1) << "\n" + << " channel 2: " << phy_channel_name(cfg.mode, cfg.ch2) << "\n" + << " ADC range: +/-" << range_to_volts(cfg.range) << " V\n" + << " target frames per channel: " << target_frames << "\n"; + + expect_ok(api, api.StreamsStart(device.hnd), "Start streams"); + device.streams_started = true; + + std::vector raw(cfg.recv_block_words); + std::vector processed(cfg.recv_block_words); + std::array, 2> channels; + channels[0].reserve(target_frames); + channels[1].reserve(target_frames); + + bool capture_started = false; + bool stop_requested = false; + bool stop_prev_initialized = false; + bool stop_prev_level = false; + bool stopped_by_external_signal = false; + uint32_t next_lch = 0; + const ULONGLONG start_wait_deadline = GetTickCount64() + cfg.start_wait_ms; + + while (!stop_requested && + ((channels[0].size() < target_frames) || (channels[1].size() < target_frames))) { + const int32_t recvd = api.Recv(device.hnd, raw.data(), cfg.recv_block_words, cfg.recv_timeout_ms); + if (recvd < 0) { + fail("X502_Recv failed: " + x502_error(api, recvd)); + } + if (recvd == 0) { + if (!capture_started && (GetTickCount64() >= start_wait_deadline)) { + std::ostringstream message; + message << "Timeout before first ADC data. start=" + << sync_mode_to_string(cfg.sync_start_mode, true) + << ", clock=" << sync_mode_to_string(cfg.sync_mode, false) << ". "; + + if (cfg.sync_start_mode == X502_SYNC_EXTERNAL_MASTER) { + message << "With start:start_in the module waits for START_IN after StreamsStart(); " + "until that condition occurs the external clock is ignored. "; + } else if (cfg.sync_start_mode == X502_SYNC_INTERNAL) { + message << "Start is immediate, so this usually means there is no valid external clock on the selected clock line. "; + } else { + message << "This usually means the selected start condition did not occur after StreamsStart(), " + "or no valid external clock arrived afterwards. "; + } + + message << "For a quick clock-only check, try start:immediate. " + "If you use a separate start pulse, it must arrive after the program starts waiting. " + "You can also increase start_wait_ms."; + fail(message.str()); + } + continue; + } + + uint32_t adc_count = static_cast(recvd); + expect_ok(api, + api.ProcessAdcData(device.hnd, raw.data(), processed.data(), &adc_count, X502_PROC_FLAGS_VOLT), + "Process ADC data"); + + if (adc_count == 0) { + continue; + } + + capture_started = true; + for (uint32_t i = 0; i < adc_count; ++i) { + const uint32_t lch = next_lch; + next_lch = (next_lch + 1U) % 2U; + if (channels[lch].size() < target_frames) { + channels[lch].push_back(processed[i]); + } + if ((channels[0].size() >= target_frames) && (channels[1].size() >= target_frames)) { + break; + } + } + + if ((cfg.stop_mode != StopMode::TargetFrames) && capture_started) { + const bool stop_level = read_di_syn2_level(api, device.hnd); + if (!stop_prev_initialized) { + stop_prev_level = stop_level; + stop_prev_initialized = true; + } else { + const bool is_edge = + ((cfg.stop_mode == StopMode::DiSyn2Rise) && !stop_prev_level && stop_level) || + ((cfg.stop_mode == StopMode::DiSyn2Fall) && stop_prev_level && !stop_level); + if (is_edge) { + stop_requested = true; + stopped_by_external_signal = true; + } + stop_prev_level = stop_level; + } + } + } + + expect_ok(api, api.StreamsStop(device.hnd), "Stop streams"); + device.streams_started = false; + + const std::size_t frames = std::min(channels[0].size(), channels[1].size()); + channels[0].resize(frames); + channels[1].resize(frames); + + write_csv(cfg.csv_path, channels[0], channels[1], frame_freq_hz); + write_svg(cfg.svg_path, channels[0], channels[1], frame_freq_hz, range_to_volts(cfg.range)); + + std::cout << "Captured " << frames << " frames per channel\n" + << "Stop reason: " + << (stopped_by_external_signal ? "DI_SYN2 edge" : "target frame count") << "\n" + << "CSV: " << cfg.csv_path << "\n" + << "SVG: " << cfg.svg_path << "\n"; + + return 0; +} + +} // namespace + +int main(int argc, char** argv) { + try { + const Config cfg = parse_args(argc, argv); + return run(cfg); + } catch (const std::exception& ex) { + std::cerr << "Error: " << ex.what() << "\n"; + return 1; + } +} diff --git a/main.exe b/main.exe new file mode 100644 index 0000000..adaad89 Binary files /dev/null and b/main.exe differ diff --git a/main.obj b/main.obj new file mode 100644 index 0000000..4db6de1 Binary files /dev/null and b/main.obj differ diff --git a/test.svg b/test.svg new file mode 100644 index 0000000..f543604 --- /dev/null +++ b/test.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + E-502 capture: CH1 and CH2 + time, s + V + 0.000000 + -2.531741 + 0.100000 + -1.818070 + 0.200000 + -1.104399 + 0.300000 + -0.390728 + 0.400000 + 0.322943 + 0.500000 + 1.036614 + 0.599999 + 1.750285 + 0.699999 + 2.463956 + 0.799999 + 3.177627 + 0.899999 + 3.891298 + 0.999999 + 4.604969 + + CH1 + + CH2 + diff --git a/x502&e16api.pdf b/x502&e16api.pdf new file mode 100644 index 0000000..88db9db Binary files /dev/null and b/x502&e16api.pdf differ diff --git a/x502_api_extracted.txt b/x502_api_extracted.txt new file mode 100644 index 0000000..96f312f --- /dev/null +++ b/x502_api_extracted.txt @@ -0,0 +1,347 @@ +Современные у стройс тва сбор а данных L-502/E-502/E16/L T A37 Рук ово дство прогр аммист а Р евизия 1.1.13 Октябрь 2025 +Автор рук ово дства: Борисов Алек сей ООО Л Кар д 117105, г . Москва, Варшавск ое ш., д. 5, к орп. 4, стр. 2 тел.: +7 (495) 785-95-25 фак с: +7 (495) 785-95-14 Адреса в Интернет: http://www.lcard.ru E-Mail: От дел про даж: sale@lcard.ru Т ехничес к ая по ддер жк а: supp ort@ l card.ru От дел к адров: job@lcard.ru Модули L-502 E-502 и E16 © Cop yrigh 2026, ООО Л Кар д. Все права защищены. 1 +Т аблица 1: Р евизии текущего документ а Р евизия Дат а Описание 1.0.0 27.06.2012 Первая ревизия данного документ а 1.0.1 22.11.2012 Добавлено описание использования библиотеки с программами на C# и в LabView, добавлено описание у ст ановки для ОС Lin ux, а т акж е опи- сание функций д ля циклическ ого выво да 1.0.2 20.02.2013 Добавлена ссылк а на ис х о дные к о ды SDK. Опи- сание у ст ановки пак етов для Lin ux вынесено в от дельный документ 1.0.3 16.02.2015 Исправлена последовательность шагов для ра- боты с мо ду лем при синхронном поток овом вы- во де. Добавлено примечание о переда чи масси- вов в к а честве вых о дных параметров в LabView 1.1.0 02.06.2015 Описание изме нено в с оответствии с изменени- ями, внесенными в библиотеку для по ддер жки мо ду ля E-502 (введение общих и специализи- рованных функций). Включено кратк ое описа- ние различий мо ду лей с программной стороны. Добавлены от дельные г лавы, описыва ю щ и е на- стройку мо ду ля при работе по Ethernet и поиск мо ду лей в лок альной сети. 1.1.1 06.07.2015 Добавлено описание возмо жности о жидания завершения у ст ановки цикли че ск ого сигнала, добавленной в версии 1.1.2 библиотеки. В раз- деле от личий мо ду лей при описании наличия ARM-к онтроллера в E-502 ук азан путь для ск а- чивания обновлений прошивки с рек омендаци- ей обновления. 1.1.2 10.07.2015 Добавлено описание нового алгоритма расчет а мак симального размера циклическ ого сигнала для E-502 с прошивк ой ARM 1.0. 3 и выше 1.1.3 28.07.2015 Добавлено описание функций X502_SetExtRefF reqV alue() и X502_GetRefF r e qV alue() 1.1.4 29.06.2016 Ук азано, что у ст ановк а час тоты выво да до- ступна в L-502, на чиная с версии 0.5 про- шивки ПЛИС. Р ек омендация при синхрон- ном выво де на ЦАП предворительно асинхрон- но у ст ановить на чальные зна чения. Добавле- но описание функций X502_Chec kF eature() и X502_OutGetStatusFlags(). 1.1.5 03.08.2016 Добавлено описание использования библиотеки в Visual Basic 6 1.1.6 23.08.2016 Изменена ссылк а во вступлении на обновленное общее низк оуровневое описание программист а для L-502 и E-502 2 +1.1.7 16.11.2016 Добавлено описание функций X502_CalcA dcF req(), X502_CalcDinF req(), X502_CalcOutF req() 1.1.8 27.02.2015 При описании синхр о н ног о и асинхронного ре- жимов работы добавле н о описание ограниче- ния их совместного использования при запу ск е синхронного вво да-выво да от внешнего сигнала 1.1.9 25.12.2019 Добавлено описание функции X502_IsOp ened(). Добавлено общее опи- сание процедуры открытия соединения с мо ду лем, г де в ч а стности описана ситу ация, к ог да соединение мо ж ет ост атьс я открытым, несмотр я на возвращенную ошибку п ри его открытии 1.1.10 21.09.2020 Исправление с сылок на ис х о дные к о ды. Пере- именование lqmeasstudio в X502Studio 1.1.11 26.07.2022 В информацию о мо ду ле д о бавлены флаги для определения типа ЦАП и типа процессора 1.1.12 11.04.2024 Для E502-P1 добавлено описание функций для работы с метк ами времени 1.1.13 30.09.2024 По ддер жк а E16 со стороны x502api 1.1.14 02.10.2025 По ддер жк а L T A37 со стороны x502api 3 +Ог лавление 1 О чем этот документ 11 1.1 О чем этот документ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2 У ст ановк а и по дключение библиотеки к пр ое к ту 12 2.1 По дклю че ни е библиотеки . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 2.1.1 По дключение библиотеки при написании программы на язык ах C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.1.2 Использов ани е библиотеки в проекте на Delphi . . . . . . . . . . . 13 2.1.3 Использов ани е библиотеки в проекте на C# . . . . . . . . . . . . . 14 2.1.4 Использов ани е библиотеки в проекте LabView . . . . . . . . . . . . 16 2.1.5 Использов ани е библиотеки в Vi sual Basic 6 . . . . . . . . . . . . . . 17 2.1.6 64-битная версия библиотеки . . . . . . . . . . . . . . . . . . . . . . 17 2.1.7 У ст ановк а библиотеки и драйвера для ОС Lin ux . . . . . . . . . . 18 2.1.8 Ис х о дные к о ды SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 3 Общий по дх о д к работе с библиотек ой 21 3.1 Общий по дх о д к использованию интерфейсных функций . . . . . . . . . 21 3.1.1 От личия при работе с мо ду лям L-502, E-502 и E16 . . . . . . . . . 21 3.1.1.1 От личие возмо жностей мо ду лей . . . . . . . . . . . . . . . 21 3.1.1.2 Особенности пр и работе с мо ду лями E16 . . . . . . . . . . 23 3.1.1.3 Особенности пр и работе с мо ду лями L T A37 . . . . . . . . 23 3.1.1.4 Общие и специализированные ф ункции для работы с мо- ду лем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3.1.1.5 Совместимость проектов, раз работ анных до введения библиотеки x502api . . . . . . . . . . . . . . . . . . . . . . 24 3.1.2 Общий алгоритм для работы с мо ду лем . . . . . . . . . . . . . . . 25 3.1.2.1 Р абот а с мо ду лем при синхр онном вво де . . . . . . . . . . 25 3.1.2.2 Р абот а с мо ду лем при синхр онном поток овом выво де . . 26 3.1.2.3 Р абот а с мо ду лем при ц иклическ ом выво де . . . . . . . . 26 3.1.2.4 Р абот а с мо ду лем при асинхрон ном вво де-выво де . . . . . 27 3.1.3 Создание и освобо ждение описателя мо ду ля . . . . . . . . . . . . . 27 3.1.4 Открытие связи с мо ду лем . . . . . . . . . . . . . . . . . . . . . . . 27 3.1.4.1 Общее описание процедуры у ст ановки связи с мо ду лем . 27 3.1.4.2 У ст ановк а связи с мо ду лем L-502 по интерфейсу PCI-Express . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.1.4.3 У ст ановк а связи с мо ду лем E-502 по интерфейсу USB . . 30 3.1.4.4 У ст ановк а связи с мо ду лем E-502 по интерфейсу Ethernet 30 3.1.4.5 У ст ановк а связи с мо ду лями с использованием записей о у стройстве . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.1.5 Р ежимы работы с сигнальным процессором и без него . . . . . . . 34 4 +3.1.6 У ст ановк а настроек мо ду ля . . . . . . . . . . . . . . . . . . . . . . . 35 3.1.6.1 Настройк а последовательности опроса к аналов АЦП . . . 35 3.1.6.2 Настройк а частоты синхронного вво да/выво да . . . . . . 37 3.1.6.3 Коэффициент у сре д не н ия для логическ ог о к анала (не ре- ализовано в Е16) . . . . . . . . . . . . . . . . . . . . . . . 38 3.1.6.4 Настройк а режимов синхронизации . . . . . . . . . . . . . 39 3.1.7 Синхронный и асинхронный режимы работы . . . . . . . . . . . . 39 3.1.7.1 Асинхронный режим работы . . . . . . . . . . . . . . . . . 40 3.1.7.2 Синхронный режим работы . . . . . . . . . . . . . . . . . 41 3.1.7.3 Циклический выво д . . . . . . . . . . . . . . . . . . . . . . 43 3.1.7.4 Р азмер буфера и шаг для синхронного режима . . . . . . 45 3.1.8 Особенност и работы по интерфейсу Ethernet и настройк а сетевых параметров . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.1.9 Обнаруж ение мо ду лей в лок альной сети . . . . . . . . . . . . . . . 48 3.1.10 Сигналы внешней синхронизации мо ду ля Е16 . . . . . . . . . . . . 49 4 Конст анты, типы данных и функции би б л иотеки 51 4.1 Конст анты и перечисления . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.1.1 Конст анты и макроопределения . . . . . . . . . . . . . . . . . . . . 51 4.1.2 События поиск а сетевых сервисов . . . . . . . . . . . . . . . . . . . 55 4.1.3 Ко ды ошибок библиотеки . . . . . . . . . . . . . . . . . . . . . . . . 56 4.1.4 Интерфейс соединения с мо ду лем . . . . . . . . . . . . . . . . . . . 60 4.1.5 Флаги, управляющие поиск ом присутствующих мо ду лей . . . . . . 61 4.1.6 Флаги для управления цифровыми вых о дами . . . . . . . . . . . . 61 4.1.7 Конст анты для выбора опорной час тоты . . . . . . . . . . . . . . . 61 4.1.8 поля io_mo de в регистре io_hard . . . . . . . . . . . . . . . . . . . 61 4.1.9 Диапазоны измерения для к анала АЦП . . . . . . . . . . . . . . . 62 4.1.10 Диапазоны измерения для к анала АЦП E16 . . . . . . . . . . . . . 62 4.1.11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.1.12 Р ежим измерения для логическ ого к анала . . . . . . . . . . . . . . 62 4.1.13 Р ежимы синхронизации . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.1.14 Флаги, управляющие обработк ой принятых данных . . . . . . . . 63 4.1.15 Флаги для обозна ч е ни я синхронных поток ов данных . . . . . . . . 64 4.1.16 Конст анты, определяющие тип передаваемог о отсчет а из ПК в мо- ду ль . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.1.17 Р ежим работы мо ду ля . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.1.18 Номера к аналов ЦАП . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.1.19 Флаги, использу емые при выво де данных на ЦАП . . . . . . . . . 65 4.1.20 Номера к аналов для переда чи поток ов данных . . . . . . . . . . . 65 4.1.21 Цифровые линии, на к оторых мо жно включить по дт ягивающие резисторы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.1.22 Флаги, определяющие наличие опций в мо ду ле и наличие необ х о- димых параметров . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.1.23 Тип со дер жимого строки с располо ж ением у стройства . . . . . . . 68 4.1.24 Флаги для режима циклическ ого выво да . . . . . . . . . . . . . . . 69 4.1.25 Дополнительные возмо жности мо ду ля . . . . . . . . . . . . . . . . 70 4.1.26 Флаги состо яния для синхронного выво да . . . . . . . . . . . . . . 70 4.1.27 Параметры мо ду лей . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 4.2 Типы данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 5 +4.2.1 Запись о у стройстве . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.2.2 Калибровочные к оэфф ициенты диапазона. . . . . . . . . . . . . . . 71 4.2.3 Коэффициенты для к алибровки фильра к оррекции А ЧХ . . . . . 72 4.2.4 Калибровочные к оэфф ициенты мо ду ля . . . . . . . . . . . . . . . . 72 4.2.5 Информация о мо ду ле L-502/E-502. . . . . . . . . . . . . . . . . . . 72 4.2.6 Описатель к онф игурации сетевого интерфейса . . . . . . . . . . . 73 4.2.7 Описатель к онтек ст а поиск а у с тройств в сети . . . . . . . . . . . . 73 4.2.8 Описатель сетевого сервиса . . . . . . . . . . . . . . . . . . . . . . 73 4.2.9 Внутренняя информация записи о у с тройстве . . . . . . . . . . . . 74 4.2.10 Описатель мо ду ля . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.2.11 Список серийный номеров . . . . . . . . . . . . . . . . . . . . . . . 74 4.3 Функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.3.1 Функции для создания и освобо ждения описателя мо ду ля . . . . . 74 4.3.1.1 Создание о п ис ателя мо ду ля . . . . . . . . . . . . . . . . . 74 4.3.1.2 Освобо ждение описателя мо ду ля . . . . . . . . . . . . . . 75 4.3.2 Функции для открытия и получения информации о мо ду ле . . . . 75 4.3.2.1 Г лобавльные переменные . . . . . . . . . . . . . . . . . . . 75 4.3.2.2 Получение с пи с к а серийных номеров мо ду лей L-502. . . . 75 4.3.2.3 Открытие мо ду ля L-502 по его серийному номеру . . . . 76 4.3.2.4 Получение списк а серийных номеров мо ду лей E-502, по д- ключенных по USB. . . . . . . . . . . . . . . . . . . . . . . 76 4.3.2.5 Р абот ает аналогично E502_Usb G etSerialList, тольк о для мо ду лей E16. . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.2.6 Открытие мо ду ля E-502, по дключенного по USB, по его серийному номеру . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.2.7 Р абот ает аналогично E502_Op enUsb, тольк о для мо ду лей E16. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.3.2.8 Открытие мо ду ля E-502 п о IP-адресу . . . . . . . . . . . . 78 4.3.2.9 Открытие мо ду ля E-16 по IP-адресу . . . . . . . . . . . . 78 4.3.2.10 Закрытие соединения с мо ду лем . . . . . . . . . . . . . . . 79 4.3.2.11 Проверк а, открыто ли с оединение с мо ду лем . . . . . . . 79 4.3.2.12 Получение информации о мо ду ле . . . . . . . . . . . . . . 79 4.3.2.13 Получение информации о мо ду ле . . . . . . . . . . . . . . 80 4.3.3 Функции для работы с запис я ми об у стройстве . . . . . . . . . . . 80 4.3.3.1 Получить список записей, соответствующих по дключен- ным мо ду лям L502. . . . . . . . . . . . . . . . . . . . . . . 80 4.3.3.2 Получить список записей, соответствующих по дключен- ным мо ду лям E502. . . . . . . . . . . . . . . . . . . . . . . 81 4.3.3.3 Аналогично E502_UsbGetDevRecordsList, получить с п и- сок записей, соответствующих по дключенным мо ду лям E16. 81 4.3.3.4 Аналогично E502_UsbGetDevRecordsList, получить с п и- сок записей, с оответствующих по д ключенным мо ду лям E14-440. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.3.3.5 Получить список записей, соответствующих по дключен- ным мо ду лям E502. . . . . . . . . . . . . . . . . . . . . . . 82 4.3.3.6 Создание з аписи о у стройстве с ук азанным IP-адресом . 82 4.3.3.7 Создание з аписи о у стройстве с ук азанным IP-адресом . 83 4.3.3.8 У ст ановк а TCP-порт а управляющего соединения для за- писи о у ст р ойс тве . . . . . . . . . . . . . . . . . . . . . . . 83 6 +4.3.3.9 У ст ановк а TCP-порт а сое ди не н ия переда чи данных для записи о у стройстве . . . . . . . . . . . . . . . . . . . . . . 84 4.3.3.10 Создание записи о у стройстве по описателю сетевого сер- виса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4.3.3.11 Открыть соединение с мо ду лем по записи о у стройстве . 85 4.3.3.12 Освобо ждение записей об у ст р о й с твах . . . . . . . . . . . 85 4.3.4 Функции для изменения настроек мо ду ля . . . . . . . . . . . . . . 86 4.3.4.1 Переда ча у ст ановленных настроек в мо ду ль . . . . . . . . 86 4.3.4.2 У ст ановк а параметров логическ ого к анала . . . . . . . . . 86 4.3.4.3 Получение м ассива диапазонов мо ду ля E16. . . . . . . . . 86 4.3.4.4 Получение м ассива диапазонов мо ду ля E502. . . . . . . . 87 4.3.4.5 Получение м ассива диапазонов мо ду ля . . . . . . . . . . . 87 4.3.4.6 У ст ановк а к оличества логических к аналов . . . . . . . . . 87 4.3.4.7 Получение к оличества логических к аналов . . . . . . . . 88 4.3.4.8 У ст ановк а делителя частоты сбора для АЦП . . . . . . . 88 4.3.4.9 У ст ановк а зна чения межк адровой задер жки для АЦП . . 88 4.3.4.10 У ст ановк а делителя частоты синхронного вво да с цифро- вых линий. . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 4.3.4.11 У ст ановк а делителя ч а стоты синхронного выво да . . . . 89 4.3.4.12 У ст ановк а частоты сбора АЦП . . . . . . . . . . . . . . . 90 4.3.4.13 У ст ановк а частоты синхр о н ног о вво да с цифровых вх о дов 91 4.3.4.14 У ст ановк а частоты синхр о н ног о выво да . . . . . . . . . . 91 4.3.4.15 Получить текущие зна чения частот сбора АЦП . . . . . . 92 4.3.4.16 У ст ановк а зна чения внутренней опорной частоты синхро- низации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 4.3.4.17 У ст ановк а зна чения внешней опорной частоты синхрони- зации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 4.3.4.18 У ст ановк а зна чения для аналоговой синхронизации (толь- к о для E16) . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 4.3.4.19 Получение зна чения опорной час тоты синхронизации . . 94 4.3.4.20 У ст ановк а режима генерации частоты синхронизации . . 94 4.3.4.21 У ст ановк а режима запу ск а ч ас тоты синхронизации . . . 95 4.3.4.22 У ст ановить режим работы мо ду ля . . . . . . . . . . . . . 95 4.3.4.23 Получение текущего режима работы мо ду ля . . . . . . . 96 4.3.4.24 У ст ановить к оэффициенты для к алибровки зна чений АЦП 96 4.3.4.25 Получение текущих к алибровочных к оэффициентов АЦП 97 4.3.4.26 У ст ановить к оэффициенты для к алибровки зна чений ЦАП 97 4.3.4.27 Получение текущих к алибровочных к оэффициентов ЦАП 98 4.3.4.28 Р а ссчет частоты сбора АЦП . . . . . . . . . . . . . . . . . 99 4.3.4.29 Р а ссчет частоты сбора АЦП . . . . . . . . . . . . . . . . . 100 4.3.4.30 Р а ссчет частоты синхронного вво да с цифровых вх о дов . 101 4.3.4.31 Р а ссчет частоты синхронного вво да с цифровых вх о дов . 101 4.3.4.32 Р а ссчет частоты синхронного выво да . . . . . . . . . . . . 102 4.3.4.33 Р а ссчет частоты синхронного выво да . . . . . . . . . . . . 103 4.3.5 Функции асинхронного вво да-выво да . . . . . . . . . . . . . . . . . 103 4.3.5.1 Асинхронный выво д дан ных на к анал ЦАП . . . . . . . . 103 4.3.5.2 Асинхронный выво д дан ных на к анал ЦАП . . . . . . . . 104 4.3.5.3 Асинхронный выво д дан ных на цифровые вых о ды . . . . 105 4.3.5.4 Асинхронный вво д зна чений с цифровых вх о дов . . . . . 106 7 +4.3.5.5 Асинхронный вво д о дного к адра АЦП . . . . . . . . . . . 107 4.3.6 Функции для работы с синхронным поток овым вво дом-выво дом . 108 4.3.6.1 Р азрешение синхронных поток ов на вво д/выво д . . . . . 108 4.3.6.2 Запрещение синхронных поток ов на вво д/выво д . . . . . 108 4.3.6.3 Получить зна чение, к акие синхронные потоки разреше ны 109 4.3.6.4 Запу ск синхронных поток ов вво да/выво да . . . . . . . . . 109 4.3.6.5 Ост анов синхронных поток ов вво да/выво да . . . . . . . . 109 4.3.6.6 Проверк а, запущен ли синхронный вво д/выво д . . . . . . 1 10 4.3.6.7 Чтение данн ых АЦП и цифровых вх о дов из мо ду ля . . . 110 4.3.6.8 Переда ча поток овых данных ЦАП и цифровых вых о дов в мо ду ль . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 4.3.6.9 Обработк а принятых отсчетов АЦП от мо ду ля . . . . . . 112 4.3.6.10 Обработк а принятых от мо ду ля данных . . . . . . . . . . 113 4.3.6.11 Обработк а принятых от мо ду ля данных с пользователь- скими данными . . . . . . . . . . . . . . . . . . . . . . . . 114 4.3.6.12 По дготовк а данных для выво да в мо ду ль . . . . . . . . . 115 4.3.6.13 По дготовк а данных для переда чи в мо ду ль . . . . . . . . 116 4.3.6.14 По дготовк а о дн о го слова для выво да в ЦАП . . . . . . . 117 4.3.6.15 Получить к оличество отсчетов в буфере поток а на вво д . 117 4.3.6.16 Получить размер свобо дного мест а в буфере поток а на выво д . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 4.3.6.17 Получить номер следующего о жидаемог о логичес к ого к а- нала АЦП для обработки . . . . . . . . . . . . . . . . . . . 118 4.3.6.18 На чал о по дготовки выво да синхронных данных . . . . . . 119 4.3.6.19 На чал о загрузки циклическ ого сигнала на выво д . . . . . 119 4.3.6.20 У ст ановк а ранее загруж енного циклическ ого сигнала на выво д . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 4.3.6.21 Ожидание у ст ановки ранее загруж енного циклическ ого сигнала на выво д . . . . . . . . . . . . . . . . . . . . . . . 120 4.3.6.22 Ост анов выво да циклическ ого сигнала . . . . . . . . . . . 121 4.3.6.23 Проверк а, завершена ли у ст ановк а или ост анов цикл иче- ск ого сигнала . . . . . . . . . . . . . . . . . . . . . . . . . 122 4.3.6.24 Чтение флагов ст ату са выво да . . . . . . . . . . . . . . . 123 4.3.6.25 У ст ановк а размера буфера для синхронного вво да или вы- во да . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 4.3.6.26 У ст ановк а шаг а при переда че поток а на вво д или выво д . 124 4.3.7 Функции для настройки сетевых параметров мо ду л я E502 . . . . . 124 4.3.7.1 Получение те кущего IP-адреса у стройства . . . . . . . . . 124 4.3.7.2 Создание о п ис ателя к онфигурации сетевого интерфейса . 124 4.3.7.3 Освобо ждение описателя к онфигурации сетевого интер- фейса. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 4.3.7.4 Чтение текущей сетевой к онфигурации интерфейса . . . 125 4.3.7.5 Запись сетевой к онфигурации интерфейса . . . . . . . . . 126 4.3.7.6 Копирование со дер жимого сетевой к онфигурации интер- фейса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 4.3.7.7 Определение, разрешен ли интерфейс Ethernet. . . . . . . 127 4.3.7.8 Р азрешение интерфейса Ethernet. . . . . . . . . . . . . . . 127 4.3.7.9 Определение, разрешено ли автоматическ ое получение параметров IP . . . . . . . . . . . . . . . . . . . . . . . . . . 127 8 +4.3.7.10 Р а зрешение автоматическ ого получения параметров IP . . 128 4.3.7.11 Получить состо я н ие автоматичес к ого получения парамет- ров IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 4.3.7.12 Определение, разрешен л и пользовательский MA C-адрес 128 4.3.7.13 Определение, разрешен л и пользовательский MA C-адрес 129 4.3.7.14 Получение у ст ановленного ст атическ ого IP-адреса . . . . 129 4.3.7.15 У ст ановк а ст атическ ого IP-адреса . . . . . . . . . . . . . . 129 4.3.7.16 Получение у ст ановленной ст атическ ой маски по дсети . . 130 4.3.7.17 У ст ановк а ст атическ ой маски п о дсети . . . . . . . . . . . 130 4.3.7.18 Получение у ст ановленного ст атическ ого адреса шлюза . 130 4.3.7.19 У ст ановк а ст атическ ого адреса шлюза . . . . . . . . . . . 131 4.3.7.20 Получение у ст ановленного пользовательск ого MA C-адреса 131 4.3.7.21 У ст ановк а пользовательск ого MA C-адреса . . . . . . . . . 131 4.3.7.22 Получение заво дск ого MA C-адреса у стройства . . . . . . 132 4.3.7.23 Получение у ст ановленного имени экзе мпляра у стройства 132 4.3.7.24 У ст ановк а имени экз емпляра у стройства . . . . . . . . . . 133 4.3.7.25 У ст ановк а нового пар о л я для смены к онфигурации . . . 133 4.3.8 Функции для поиск а мо ду л е й в лок альной сети . . . . . . . . . . . 133 4.3.8.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 4.3.8.2 На чало сеанса поиск а мо ду лей в лок альной сети . . . . . 134 4.3.8.3 Получение информации о изме нении присутствия мо ду- лей в лок альной сети . . . . . . . . . . . . . . . . . . . . . 135 4.3.8.4 Ост анов сеанса поиск а мо ду лей в лок альной сети . . . . . 136 4.3.8.5 Освобо ждение описателя сетевого сервиса . . . . . . . . . 136 4.3.8.6 Получить имя экземпляра по опи с ателю сервиса . . . . . 136 4.3.8.7 Получить серийный номер мо ду ля по описателю сетевого сервиса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 4.3.8.8 Получить имя у сройства мо ду ля по описателю сетевог о сервиса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 4.3.8.9 Получить IP адрес сетевого сервиса . . . . . . . . . . . . 137 4.3.8.10 Проверк а, ук азывают ли оба описателя на о д ин экзем- пляр сервиса . . . . . . . . . . . . . . . . . . . . . . . . . . 138 4.3.8.11 Получить список записей, присутствующих в лок альной сети . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 4.3.8.12 Получить список записей, присутствующих в лок альной сети . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 4.3.8.13 У ст ановк а номера tc p порт а для к оманд . . . . . . . . . . 140 4.3.8.14 У ст ановк а номера tc p порт а для данных . . . . . . . . . . 140 4.3.8.15 Получение номера tcp порт а для к оманд . . . . . . . . . . 141 4.3.8.16 Получение номера tcp порт а для данных . . . . . . . . . . 141 4.3.9 Функции для работы с сигнальным процессором . . . . . . . . . . 141 4.3.9.1 Загрузк а прошивки сигнального процессора Bla c kFin. . . 141 4.3.9.2 Проверк а, загруж ена ли прошивк а Blac kFin. . . . . . . . 142 4.3.9.3 Чтение блок а данных из памяти сигнального процессора 142 4.3.9.4 Запись блок а данных в память сигнального процессора . 143 4.3.9.5 Переда ча управляющей к ома н ды сигнальному процессору 144 4.3.10 Функции для раб оты с Flash-памятью мо ду ля . . . . . . . . . . . . 145 4.3.10.1 Чтение блок а данных из Flash-памяти . . . . . . . . . . . 145 4.3.10.2 Запись блок а данных во Flash-память мо ду ля . . . . . . . 145 9 +4.3.10.3 Стирание блок а во Flash-памя ти . . . . . . . . . . . . . . 146 4.3.10.4 Р а зрешение записи в пользовательскую область Flash-памяти . . . . . . . . . . . . . . . . . . . . . . . . . . 146 4.3.10.5 Запрет записи в пользовательскую область Flash-памяти 146 4.3.11 Дополнительные вспомог ательные функц ии . . . . . . . . . . . . . 14 7 4.3.11.1 Получить версию драйвера мо ду ля L-502. . . . . . . . . . 147 4.3.11.2 Перево д мо ду ля E-502 в режим загрузчик а . . . . . . . . 147 4.3.11.3 Перезагрузк а прошивки ПЛИС . . . . . . . . . . . . . . . 148 4.3.11.4 Переда ча управляющей к оманды к онтроллеру Cortex-M4. 1 48 4.3.11.5 Получить версию библиотеки . . . . . . . . . . . . . . . . 149 4.3.11.6 Получение строки об ошибк е . . . . . . . . . . . . . . . . 149 4.3.11.7 Морг ание свето дио дом . . . . . . . . . . . . . . . . . . . . 149 4.3.11.8 У ст ановк а по дт ягивающих резисторов на вх о дных линиях 150 4.3.11.9 Получение параметра pullups для мо ду ля . . . . . . . . . 150 4.3.11.10 Проверк а по ддер жки мо ду лем заданной возмо жности . . 151 4.3.11.11 Эк сперимент альная функция. Игнорировать ошибку с за- данным номером . . . . . . . . . . . . . . . . . . . . . . . . 151 4.3.11.12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 4.3.11.13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 4.3.11.14 Функция задания параметров мо ду ля . . . . . . . . . . . 152 4.3.11.15 Функция задания п а р ам етров цифрового вво да для мо ду- ля L T A37. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 5 Метки времени в поток е данных (тольк о для E502-P1) 153 5.1 Р ежим синхронизации времени по проток олу PTP . . . . . . . . . . . . . 15 3 5.1.1 Р абот а с мо ду лем п ри использовании меток в р е мени . . . . . . . . 154 5.1.2 Описание регистров PTP . . . . . . . . . . . . . . . . . . . . . . . . 154 5.1.3 PTP-совме стимое обору дование . . . . . . . . . . . . . . . . . . . . 155 5.2 Конст анты и перечисления . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 5.2.1 Конст анты и макроопределения . . . . . . . . . . . . . . . . . . . . 155 5.2.2 Структура для хранения к онтек ст а при обработк е поток а слов на вво д с включенными метк ами вре мени . . . . . . . . . . . . . . . . 157 5.2.3 Тип данных для хранения времени Время хранитс я в секундах прошедшее с на чала этой эпо хи (00:00:00 UTC, 1 Январ я 1970 го- да) Дробный формат хранения 32. 31: 32 целых бит , 31 дробных бит , ст аршие 32 бит а - секунды, младшие 31 бит - доли секунды (SubSecond) = 1 / (1 << 31) секунд . . . . . . . . . . . . . . . . . . . 158 5.3 Функции для работы с метк ами времени . . . . . . . . . . . . . . . . . . . 158 5.3.1 Инициализация tstp_ state, в нем хранитс я текущий к онте к ст для операций с метк ами времени из поток а на вво д. . . . . . . . . . . 158 5.3.2 Обработ ать очередное слово wrd из поток а на вво д. . . . . . . . . 159 5.3.3 Узнать время текущего обработ анного слова . . . . . . . . . . . . . 159 5.3.4 Возвращае т признак того что часы синхронизированы . . . . . . . 159 10 +Г лава 1 О чем этот документ 1.1 О чем этот документ Данный документ предназна чен в первую очередь для программистов, к оторые со- бираютс я писать свои программы для работы с мо ду лями L-502, E-502 и E16 с исполь- зованием предост авляемой фирмой  Л Кар д библиотеки. В данн о м документе рассматриваетс я вопрос по дключения библиотеки к проекту пользователя, даетс я по дробное описание интерфейсных функций, предост авляемых библиотек ой, а т акж е даетс я описание основных по дх о дов к использованию этих и нте р- фейсных функций. Сама библиотек а написана на язык е C и все объявления функций и типов, а т ак- ж е примеры в данном документе приво дятс я на язык е C , о днак о все привязки к дру- гим язык ам программирования являютс я лишь обе ртк ами над библиотек ой C и все функции, типы и параметры со храняют свое зна чения и для других язык ов програм- мирования. Поэтому э тот документ необ х о димо прочит ать и пользователям, пишущим на других язык ах программирования. Кроме того в документе даетс я описание от ли- чий и общих принципов использования библиотек на по ддер живаемых других язык ах программирования. Примеры для других язык ов мо жно у ст ановить вместе L-Card L502/E502 SDK . В насто ящем документе не рассматриваютс я к акие-либо вопросы, к асающиес я по д- ключения сигналов и х арактеристик мо ду ля, а т акж е лишь в общем затрагивают- с я при нципы работы самого мо ду ля. Эти вопросы рассматриваютс я в Руководстве пользователя L-502 и Руководстве пользователя E-502 , с к о торыми рек оменду- етс я ознак омитс я перед прочтением данного документ а. Т акж е в данном документе не рассматриваетс я зада ча написания своей прошив- ки для сигнального процессора мо ду ля и работ а с мо ду лем без использования предо- ст авляемой  Л Кар д библиотеки. Эти вопросы рассм атриваютс я в Низкоуровневом описании программиста . 11 +Г лава 2 У ст ановк а и по дключение библиотеки к проекту 2.1 По дключение библиотеки Для написания собственного програм много обеспечения, работ а ю щ его с мо ду лями L-502 и E-502, необ х о димо выполнить следующее: 1. У ст ановить драйвер для мо ду лей: € Для работы с мо ду лями, по дключенными по инте р фейс у PCI Express, необ- х о дим специальный драйвер, предост авляе мый фирмой  Л Кар д € Для работы с мо ду лями, по дключенными по интерфейсу USB, использу етс я библиотек а libusb-1.0 . По д Windo ws сама библиотек а включена в ст ан- дартную библиотеку e502api.dll , а в к а честве др айве ра использу етс я ст ан- дртный драйвер WinUSB . По д ОС Lin ux необ х о димо у ст ановить библиотеку libusb-1.0 , при этом ник аких специальных драйверов не требу етс я. € Для работы с мо ду лями, по дключенными по интерфейсу Ethernet (TCP/IP), специальных драйверов не требу етс я. Для возмо жности выполнять поиск мо- ду лей в лок альной сети должна быть у с т ановлена соответствующа я служба (см. г лаву Обнаруж ение мо ду лей в лок альной сети ). 2. У ст ановить необ х о димые динамические библиотеки (.dll для Windo ws или .so для Lin ux) в директорию, присутствующую в соответствующей переменной окруж е- ния, либо в директорию с проектом. Динамическ ая библиотек а необ х о дима при написании программ на любом язык е программирования, т ак к ак все привязки к язык ам работ ают через ук азанные библиотеки.. В с его предост авляетс я три биб- лиотеки: € x502api  со дер жит общие функции для обоих мо ду лей. Должна включать- с я в любой проект , работ ающий с о дним из мо ду лей, за исплючением проек- тов, н апис ан ных тольк о для L-502 до по явления библиотеки x502api, к оторые могут использова ть тольк о l502api € l502api  со дер жит специфические ф ункции для мо ду ля L-502, а т акж е функции, ост авле н ные для совместимости с прое к т ами, написанными до по- явления x502api. € e502api  со дер житспецифические функции дл я мо ду ля E-502. 12 +3. По дключить библиотеку к проекту . Для ОС Windo ws предост авляетс я общий у ст ановщик L-Card L502/E502 SDK , к оторый автоматически у ст анавливает вс е необ х о димые драйвера, динамические биб- лиотеки в системную директорию, а т акж е все файлы, необ х о ди м ы е для по дключе- ния библиотеки к проекту и примеры в ук азанную директорию. В дальнейшем в дан- ной г лаве с помощью SDK_DIR б у дет обозна чатьс я ук азанная пр и у ст ановк е L-Card L502/E502 SDK директория. У с т ановк а для ОС Lin ux описана в разделе У ст ановк а библиотеки и драйвера для ОС Lin ux . По дключение к проекту зависит от использу емого язык а и среды программирова- ния. 2.1.1 По дключение библиотеки при написании программы на язык ах C/C++ При написании на C/С++ при по дключении необ х о димо выполнить следующее: 1. Включ ить в проект заголовочный файл  l502api.h и/или  e502api.h , добавив при этом в проекте к пут ям для заголовочных файлов директорию SDK_DIR/include. 2. Добавить в проект файл линк ера нужных библиотек для использу емого к омпи- лятора: € Microsoft Visual С++ : SDK_DIR/lib/msv c € Microsoft Visual С++ 64-битный к омпилятор (по дробнее о 64-битной вер- сии описано ниж е ) : SDK_DIR/lib/msv c64 € Borland C++/Borland C++ B uilder : SDK_DIR/lib/b orland € Borland C++/Borland C++ Bui lder 64-битный к омпилятор: SDK_DIR/lib/b orland64 € MinGW : SDK_DIR/lib/mi n gw € MinGW 64-битный к омпилятор: SDK_DI R /l ib/mingw64 Примеры программ на C нах о дятс я в SDK_DIR/examples/c . Специальные при- меры для Borland C++ Builder  в SDK_DIR/examples/CppBuilder . 2.1.2 Использование библиотеки в проекте на Delphi Для написания программ на Delphi с использованием библиотеки для работы с мо ду лями L-502 и E-502, необ х о димо включить в проект программы файл SDK_DIR/pas/x502api.pas , а т акж е файл SDK_DIR/pas/l502api.pas и/или SDK_DIR/pas/e502api.pas , к оторые предст авляют собой обертку над библиотек ами на C . В файлах проект а, к оторые используют типы и функции из этого документ а, необ х о димо по дключить мо ду ль x502api, а т акж е l502api и/или e 502api с помощью uses x502ap i; , uses l502api; и uses e502ap i; соответственно. При этом для 64-битного к омпилятора используютс я те ж е файлы, что и для 32-битного (см. 64-битная версия библиотеки ). Следу ет отметить, что по сравнению с версиями до по ддер жки E-502, файл SDK_DIR/pas/lp cieapi.pas больше не использу етс я. Т .к. этот файл не долж ен был использоватьс я в проект ах напр ямую, то он не включен в новых версиях библиотеки. 13 +Все функции, типы и к онст анты библиотеки отображ аютс я в Delphi о дин к о дному , за исключением следующих моментов: € все строки (се ри йные номера, строки с описанием к о дов ошибок) пр е образуютс я обертк ой в тип string , к ото р ый использу етс я ст андартно для предст авления строк в Delphi (следу ет не забывать, что в последних версиях среды этот тип предст авляет собой юник о дную строку). Исключением являетс я структура t_x502_info с и нформацией о мо ду ле, в к оторой строки предст авлены массивом AnsiChar фик сированной длины. € все функ ции, работ ающие с массивами, принимают в к а честве параметра откры- тый массив (op en arra y parameter), что озна чает , что в эти функции мо жно пе- редать к ак ст атический массив, т ак и динамичес ки й (у ст ановив предварительно его дл ину с помощью SetLength() ). При этом, т ак к ак массивы Delphi со дер- ж ат в себе длину , то в функции L502_GetSerialList() и E502_UsbGetSerialList() , а т акж е L502_GetDevRecordsList() и E502_UsbGetDevRec ord sLi st( ) от дельно пере- давать размер массива не требу етс я. Однак о в функциях для работы с данными (например, X502_Recv() ) длина пере д ае тс я т ак ж е, к ак и в функциях C , что - бы мо жно было использовать для приема не об я зательно весь массив. При этом дополнительно провер яетс я, что переданная от дельным параметром длина не пре- вышает реальную длину массива. В случае превышения бу дет возвращена ошибк а X502_ERR_INSUFFICIENT_ARRA Y_SIZE . Пример программы на Delphi нах о дитс я в SDK_DIR/examples/Delphi . 2.1.3 Использование библиотеки в проекте на C# Для напи с ания программ, работ ающих с мо ду лями L-502 и E-502, на язык е C# (или н а любом другом, п о ддер живаемым NetF ramew ork), реализована специальная библиотек а-обертк а lp cieNet.dll. Она использу ет описанные ранее библиотеки на C , в к оторых реализована вс я л о гик а работы с у с тройством. У ст ановщик позволяет у ст ановить lp c ieNet.dll в системный кэш (GA C), что позволяет не к опировать библиотеку вместе с Вашим проектом. Однак о, к со ж алению, Visual Studio не позволяет добавлять в проект ссылки из системного к еша и Вам вс е равно придетс я саму ссылку делать на лок альную к опию (просто ее не об язательно бу дет распространять вместе с проектом). Библиотек а в к еше имеет пр е имущество перед лок альной и бу дет всег да использованна именно она, если у ст ановлена. Для использования библи от еки дост аточно добавить в проект ссылку на lp cieNet.dll и в ис х о дник ах по дключить нужные пространс тва имен: 0 using x502api; using lpcieapi; Для совместимости с программами, написанными до включения по ддер жки L-502, ост авлена ст арая версия всех определений в пространстве имен l502api со ст арой вер- сией класса L502. По сравнению с функциями язык а C в обертк е C# с деланы следующие изменения: 14 +€ Т ак к ак С#  объектно ориентированны й язык, то для управления мо ду лями созданы специальные классы L502 и E502, к оторые наследуютс я от общего класса X502. € Все функции, к оторые принимают описатель мо ду ля первым параметром реализо- ваны мето дами классов L502, E502 или X502, при этом сам префик с L502_, E502_ или X502_ не использу етс я. Например, вместо L502_Open(hnd, serial) , исполь- зу етс я hnd.Open(serial) . Для сетевой к онфигурации мо д у ля E-502 использу етс я от дельный класс E50 2.Eth Cong. € Функции X502_Cr e ate() и X502_F ree() вызываетс я в к онструкторе и деструк- торе класса X502, от дельными функциями не реализованы. Аналогично обсто и т дело c X502_F reeDevRecordList() и классом X502.DevRec, а т акж е с функциями E502_EthCongCreate() и E50 2_ EthCongF ree() и класс ом E502.EthCong. € Для создания нужного объект а у стройства (L502 или E502) по имени мо ду ля ре- ализован ст атический мето д X502.Create(devname) . € Функции, к оторые не требуют экземпля р а мо ду ля (не принимают описатель первым параметром), реализованы к ак ст атические функции соответству- ющих классов. Например X502_GetErrorString(err) раеализована к ак X502.GetErrorString(err) . € Функции типа Get/Set, к оторые принимают описатель мо ду ля и о дин параметр, реализованы в виде свойств (prop erties). Например, вместо X502_SetLChannelCount(hnd, value) , использу етс я hnd.LChannelCount = value . Однак о следу ет быть внимательным, т ак к ак неправильно у ст анавливаемое зна чение вызовет исключение X502.Exception . € Конст анты объявлены внутри классов и без префик са L502_, E502_ или X502_. € Перечисления т акж е объявлены к ак перечисления внутри класса и без префик са X502_ПЕРЕЧИСЛЕНИЕ . Например не X502_SYNC_INTERNAL , а X502.Sync.INTERNAL . € Ко ды ошибок, т ак к ак планиру етс я использовать общие к о ды ошибок и для бу ду- щих мо ду лей, вынесены в перечисление ERR в классе lp cie . € Все функции, использующие в C строки в виде char  , используют в обертк е строки типа String . € Функции L502.GetSerialList() , E502.UsbGetSerialList() , а т а к ж е фун кции L502.GetDevRecordsList() и E502.UsbGetDevRecordsList() возвращают созданный внутри функ ции динамический массив строк/записе й о у стройстве (а не заполняет переданный), к оторый уж е со дер жит длину . Поэ тому дополнительный параметр размера массива не требу етс я. € Как и в Delphi, при работе с массивам и д а н ных пере даетс я длина дополнитель- ным параметром, т ак к ак мо жно принимать меньше данных, чем в выделенном массиве. € Функции, принимающие ук азатели в C , принимают параметры со специфик ато- рами out или ref, в зависимости от того, должна ли быть переменная проинциа- лизирована перед вызовом функции или я вляетс я вых о дным параметром. 15 +Пример программы на C# нах о дитс я в SDK_DIR/examples/cs . 2.1.4 Использование библиотеки в проекте LabView Вы мо ж ете управлять мо ду лями L-502 и E-502 из L abView , использу я тот факт , что L abView по ддер живает управляемые библиотеки NetF ramew ork. Соответственно, Вы имеете доступ к о все м функциям, к оторые реализу ет оболочк а C# lp cieNet.dll , т . е. все доступные функции библиотеки, с учетом от личий, описанных в предыдущем разделе ). В от личие от Visual Studio LabView автоматиче ски по дхватывает .Net библиотеки из системного кэша (GA C) и Вы мо ж ете ссылатьс я на нее, а не хранить лок альную к опию вместе с программой. Для работы с классами .Net в LabView есть специальная панель Connectivit y - > .Net . Вам необ х о димо использовать следующие блоки: € Constructor No de - с оздает объект . Долж ен быть создан дл я к аждого мо ду ля L-502 или E-502, с к оторым бу дете работ ать. Пр и создании LabView предло жит выбрать библиотеку и класс (нужно выбрать lp c ieNet.dll и L-502 или E-502 из пространства x502api). Одним из вых о дов этого блок а являетс я ссылк а на объ- ект , к оторая используютс я к ак вх о д для ост альных блок ов для работы с мо ду лем. Т акж е с помощью к онструктора создаетс я объект логическ ого к анала со всеми настройк ами. Аль тернативным вариантом создания объект а мо ду ля являетс я ис- пользование мето да X502.Create, к оторый создает нужный объект по име н и мо- ду ля. € Close Reference - закрывает и у д а л я ет объект . Долж ен вызыватьс я для к аждого созданного объ ект а по завершению работы. € In v ok e No de - выз ов функции (мето да класса). При работе с объектом на вх о д по даетс я ссылк а и вх о дные параметры, а на вых о де  вых о дные параметры и обновленная ссылк а (к оторая должна использоватьс я для блок ов, к оторые бу дут вызваны после текущего). Вх о дная ссылк а и определяет , мето ды к ак ого объек- т а используютс я (после заведения ссылки на вх о д и м я класса по явитс я в вер хней строк е, а при наж атии на вторую бу де т предло ж ен на выбор его мето д). Для фун к- ций, к оторые не работ ают с к онкретным объектом (GetErrorString, GetSerialList и т .д.  э ти функции ст атичес к ие и при выборе помечены [S] в на чале) ссылку на вх о д по давать не об язательно. Однак о они все равно принадлеж ат классу , к оторый надо выбрать наж ав правой кнопк ой на блок и далее Select Class/.Net € Prop ert y No de - использу етс я для у ст ановки или получения свойств. Через свойства у ст анавливаетс я часть параметров (логическ ая т аблица, режим синхро- низации) и т акж е мо жно получить информацию о мо ду ле (в виде класса, к аж- дое поле к оторого являетс я т акж е от дельным свойством). Мо жно у ст анавливать неск ольк о свойств о дним блок ом, расширив его вниз. Т акж е с помощью свойств мо жно задавать к онст анты из перечислений (что мо ж ет быть более понятно, чем просто по давать на вх о д числа) - в этом случае надо выбрать класс перечисление, а к аждому з н а чению соответству ет свое свойст во. Следу ет отметить особенность переда чи массивов в к а честве вых о дных параметров. Сами функци и библиотеки для эффективности не выделяют массивов данных внутри себ я, а используют переданные массивы для со хранения рез у ль т атов. Поэтому т аки е 16 +параметры в L abView являютс я вх о дными и вых о дными о дн ов р е менно. На вх о д необ х о- димо по дать массив размера, дост аточного для со хранения рез у ль т атов (при этом с ами данные не и м еют зна чения), а в к а честве вых о дного параметра возвращаетс я тот ж е массив, н о уж е заполненный резу ль т ат ами выполнения функции. Примером т аки х пара- метров могут служить параметр buf функции X502_Recv() , параметры adc_data и din_data функции X502_Pro cessData() , а т акж е параметр out_buf функции X502_PrepareData() . Примеры программ на L abView нах о дитс я в SDK_DIR/examples/LabView . 2.1.5 Использование библиотеки в Visual Basic 6 Для работы с мо ду лями из программы на Visual Basic 6 нужно в проект добавить файлы мо ду лей x502api.bas , e502api.bas и l502api.bas , к оторые мо жно взять из при- мера SDK_DIR/examples/vb6/x502_general . Файлы со дер ж ат объявления всех типов, к онст ант и функций. Параметры функций совпадают с функциями язык а C , за исключением следующих особенностей: € т ак к ак в Visual Basic не используютс я ук азатели, то для всех описателей исполь- зу етс я просто тип Long € Функции L502_GetSerialList() , E502_UsbGetSerialList() , а т акж е функции L502_GetDevRecordsList() и E502_UsbGetDevRecordsList() принимают в к а честве параметра динамический массив и изменяют его размер в соответствии с к оличеством найденных элементов. Соответственно, дополнительные явные параметры, задающие размер массива на вх о д и к оличество н а й де н ных элементов не требуютс я. € Строки в функциях преобразовываютс я в строки Visual Basic автоматически. Строки ж е в структурах предст авлены массивом байт . Для пе р е во да их в String мо жно воспользоватьс я ф ункцией X502_StrConvert() € Для освобо ждения ресурсов о дной записи дополнительно введена функция X502_FreeDevRecord() , вызывающая X502_F reeDevRecordList() для о дного элемент а, чтобы не преобразовывать элеме нт в массив вручную Следу ет отметить, что при от ладк е из среды Visaul Basi c 6 при ост анове незавер- шенной программы, если на момент ост анова были незакрытые соединения с мо ду ля ми, то эти соединения могут не закрыватьс я автоматически до перезапу ск а среды. Соответ- ственно, т .к. к оличество о дновременных соединений ограничено, то мо ду ль мо ж ет быть не видим в списк е н а й де н ных у стройств или с ним нельзя бу дет у ст ановить соединение до перезапу ск а среды. 2.1.6 64-битная версия библиотеки На 64-биной версии Windo ws могут выполнятьс я программы, к ак собранные 32- битным, т ак и 64-битным к омпилятором, поэтому большинство программ для Windo ws существу ет тольк о в 32-битном варианте. 64-битный к омпилятор используют к ак пра- вило для программ, работ ающих с большим к оличеством данных, т ак к ак это позволяет иметь процессу вирту альное пространство больше 4 Гбайт . Для 64-битной Windo ws у ст ановщик L-Card L50 2/E502 SDK ст авит в соответ- ствующие системные директории 32-битную версию библиотек, т ак и 64-битную. При 17 +этом директория Windo ws/system32 ук азывает на о дну из этих директорий в зави- симости от разр ядности самого прило ж ения, к оторое обращаетс я по ук азанному пути. Для 32-битного прило ж ения в Windo ws/system32 нах о дятс я 32-битные библиотеки, а 64-битные в Windo ws/Sysnativ e , а для 64-битного в Windo ws/system32 нах о дятс я 64-битные, а Windo ws/Sysnativ e не существу ет . При этом в Windo ws/SysW O W64 всег да леж ат 32-битные библиотеки и она всег да сущес тву ет не зависимо от разр ядности прило ж ения. При загрузк е прило ж ения, если используютс я с и с темные библиотеки, то они ищутс я по пут я м из переменной окруж ения P A TH, среди к оторых есть Windo ws/system32 . Т ак к ак эт а директория ссылаетс я на разные мест а в зависимости от разр ядности запу ск аемого прило ж ения, то выбор библиотеки нужной разр ядности из Windo ws/system32 проис х о дит автоматически. Если библиотеки распространяютс я вме сте с программой, то нужно с ледить, чтобы разр ядность собранного прило ж ения и библиотек в о дной директории совпадала. Единственным от личием при написании программ на C или C++ являетс я необ х о- димость по дключить lib-файл в соответствии с разр ядностью использу емого к омпиля- тора. Для программ на Delphi необ х о димо тольк о ук азать, для к ак ой платформы бу дет собиратьс я проект (win32 или wi n64) и собранная прог р а мма бу дет ис пол ь зовать биб- лиотеку той разр я д нос ти, для к оторой программа была ск омпилирована. Программы на язык е C# (или на любом другом, использующем NetF ramew ork) к ом- пилируютс я в машинный к о д при выполнении. При этом о дин раз созданная програм- ма мо ж ет выполнятьс я к ак на 32-битной версии, т ак и на 64-битной версии вирту аль- ной машины NetF ramew ork (в проекте мо жно ук азать явно, для к ак ой разр ядности NetF rame w ork предназна чена программа). Т аким образом, о дна и т а ж е программ а в 32-битной версии Windo ws бу дет выполнятьс я с ис п ольз ованием 32-битной версии биб- лиотек, а в 64-битной  с использованием 64-битной. Для библи о теки .Net разр ядность определяетс я разр ядностью использующего его прило ж ения. Соответственно, в проекте на L abView , к оторый использу ет .Net библиотеку , раз- р ядность использу емой библиотеки определяетс я разр ядностью использу емой среды L abView . 2.1.7 У ст ановк а библиотеки и драйвера для ОС Lin ux Для у ст ановки драйвера и библиотеки по д ОС Lin ux существу ет два вариант а: € Воспользоватьс я г отовыми собранными пак ет ами, предост авляемыми  Л Кар д . Это рек омендованный способ для дистрибутивов, для к оторых предост авляютс я собранные пак еты. Список по д де р живаемых дистрибутивов мо жно посмотреть в документе Использование внешних репозиториев ' Л Кард ' для дистрибу тивов Linux € Ск а чать ис х о дные к о ды L-Card L502/E502 SDK и собрать их самосто ятельно (по дробнее в с л е дую щ ем разделе ). Для примеров р а боты с мо ду лями L-502 и E-502 на C по д Lin ux мо жно ск а чать ар хив с ис х о дник ами SDK и п ос мотреть на примеры в api/x502api/examples/msv c . Не смот- р я на название , они могут быть собраны GCC п о д ОС Lin ux. Для к аж д ог о примера есть mak ele (с к оммент ариями), а т акж е файл CMak eList.txt для предпочит ающих сб ор ку с использованием cmak e . 18 +О том, к ак по дключить внешний репозиторий, у ст ановить собранные п а к еты и о пре- имуществах данного мето да у ст ановки описано в документе Использование внешних репозиториев ' Л Кард ' для дистрибу тивов Linux . Здесь ж е бу дет приведен список самих пак етов, использующих с я п ри работе с мо ду лями L-502 и E-502, с ук азанием зависимостей. При по дключении вне шнего репозитория зависимости разрешаютс я ав- томатически (за исключением пак ет а lp cie-dkms , о чем описано ниж е). При у ст ановк е пак етов вручную без по дключения внешнего репозитория, следу ет учитывать зависимо- сти при у ст ановк е пак етов (например библиотеки следу ет с т авить в следующем пор ядк е: сперва lib x502api1 , зат ем libl502api1 и lib e502api1 , и тольк о затем при необ х о димо- сти lib x502api1-dev или lib x502api1-dev el ). Для работы с мо ду лями L-502 и E-502 используютс я пак еты: € lib x502api1-dev или lib x502api1-dev e l  Пак ет с файлами для разработчик а: заголовочные файлы и ссылки на библиотеки нужной версии. Нуж ен при написа- нии своих программ с использованием описанных в данном документе библиотек (зависит от lib x502api1 , libl502api1 и lib e502api1 , благо дар я чему сами биб- лиотеки то ж е ст авятс я авт оматически при у ст ановк е файлов разработчик а) € lib x502api1 , libl502api1 и lib e502api1  Пак еты не п ос редственно с библиотек а- ми нужной ве рсии. Если вы распространяете свою программу , то Вам дост аточно включить в зависимости тольк о пак ет , соответствующие использу емым библиоте- к ам (без пак ет а с файлами для разработчик а), что при создании rpm и deb пак е- тов выполняетс я автоматически. Пак ет lib x502api1 со дер жит библи от еку общих функций, к оторая использ ую т с я в libl502api1 и lib e502api1 , поэтому последние завис ят от первой. Пак ет lib e502api1 т акж е зависит от пак ет а с библиотек ой libusb-1.0 для данного дистрибутива, чтобы она у ст анавливалась автоматиче- ски, а т акж е ст ав и т правила udev для предост авле н ия прав доступа к у ст р ойс тву E-502, по дключенного по USB. € lp cie-dkms  Пак ет с ис х о дник ами драйвера (мо ду ля ядра) для работы с мо ду- лями по интерфейсу PCI-Express (L-502), ис п о л ь зующий систему сборки внешних мо ду лей dkms (по дробнее описано ни ж е). € lxfw-up date  Ут и лит а для обновления прошивок ПЛИС мо ду лей L-502 и E- 502. Пак ет включает в себ я после д нюю версию прошивок и с кр ипты l502-fpga- up date-all.sh и e502-fpga-up date-all.sh для обновления прошивок всех найденных у стройств L-502 или E-502 соответственно. Т ак к ак драйвер долж ен быть собран по д к онкретную версию ядра (а ядро мо ж ет обновлятьс я в о дной версии дистрибутива или даж е могут использоватьс я разные ва- рианты ядра), то драйвер не мо ж ет распространятс я в уж е собранном виде. Его сборк а выполняетс я непосредственно при у ст ановк е пак ет а. Пр и этом необ х о димо предвари- тельно пост авить пак ет с заголовочными файлами текущего ядра (обычно в пак ет ах с именами lin ux-headers или k ernel-dev el ). Для нек оторых дистрибутивов мо ж ет быть неск ольк о вариантов ядра (и соотве тственно неск ольк о пак е тов), более того Вы мо ж е- те использовать свое ядро. Именно по этой причине пак ет не задан зависимостью для lp cie-dkms , в от личие от других зависимостей. Узнать текущую в ерсию ядра мо жно к омандой: uname -r . Убедитьс я, что нужные файлы у ст ановлены мо жно проверив на- личие файлов в директории /lib/mo dules/ uname -r /build (обычно э то ссылк а на заголовки ядра в /usr/src/lin ux- < v ersion > или /usr/src/k ernels/ < v ersion > ). 19 +Если заголовки текущего ядра у с т ановлены, то при у ст ановк е пак ет а lp cie-dkms бу дет выполнена сборк а драйверов с использованием DKMS (пак ет dkms вх о дит в зави- симости lp cie-dkms , к ак и mak e и gcc, необ х о димые для сборки). DKMS это дост аточно широк о распространенная система с борки и управления внешними мо ду лями ядра (она нах о дитс я в основном репозитории большинства дистрибутивов Lin ux, х от я ее нет в Op enSuse, н о для нее р а спространяетс я пак ет dkms через тот ж е Op en Build System). DKMS позволяе т: € централизованно отслеживать, к аки е сторонние мо ду ли ядра, к акие их версии и для к аких версий ядра у ст ановлены (dkms status) € хранит всег да ис х о дники драйвера разных версий в централизованном месте ( /usr/src/lp cie- < v ersion > ) € позволяет авт оматически пересобирать драйвер при перех о де на новое ядро € позволяет в любой момент у далить драйвер или любую его версию и все связанные с ним файлы (dkms remo v e -m lp cie -v < v ersion > all) Т аким образом, х от я в пак ете нах о дятс я ис х о дники драйвера, а не собранный драй- вер, у ст ановк а мало чем от личаетс я от у ст ановки др уг их пак етов, кроме того, что тре- бу ет дополнительной у ст ановки заголовочных файлов ядра и у ст ановк а пак ет а требу ет зна чительного времени на сборку . При у ст ановки нового ядра мо ду ль бу дет пересобран по д него автоматически л ибо при у ст ановк е пак ет а, либо при первом вх о де в систему с новым ядром. 2.1.8 Ис х о дные к о ды SDK Ис х о дные к о ды всех сост авных к омпонентов SDK открыты. Пользователю предо- ст авляетс я доступ на чтение к репозиторию системы к онтроля версий git , располо- ж енному по адре су https://gitlab.com/l-card/acq/devices/x502/sdk/lpcie_sdk . Т акж е возмо жно ск а чать ар хив со всеми ис х о дными к о дами SDK по ссылк е https://lcard.ru/download/lpcie_sdk_src.zip . Инструкции по сборк е нах о дятс я в файле ис х о дник ов INST ALL.txt. 20 +Г лава 3 Общий по дх о д к работе с библиотек ой 3.1 Общий по дх о д к испол ьзованию интерфейсных функций 3.1.1 От личия при работе с мо ду лям L-502, E-50 2 и E16 3.1.1.1 От л ичие возмо жностей мо ду лей Функциональные возмо жности мо ду лей L-502, E-502 и E16 очень с х о жи, о днак о есть существенные от личая. 1. Основное от личие заключаетс я в использованных интерфейсах  PCI-Express для L-502 и USB или Et he r ne t для E-502 и E16. В связи с этим неск ольк о от личает- с я процедура у ст ановки связи с у стройством. Кроме того, работ а по интерфейсу Ethernet требу ет н а стройки дополнительных параметров. 2. В E-502 использу етс я дополнительно к онтроллер ARM Cortex-M4 для реализации логики интерфейсов (USB/Ethernet). У данного к онтроллера есть сво я прошивк а, к оторую мо жно обновлять и в к оторой могут быть реализованы дополнительные возмо жности ( в первую очередь при работе через Ethernet). Р е к оменду етс я всег да использовать последнюю версию прошивки, к оторую мо жно ск а чать по адресу https://lcard.ru/e502-m4.bin и обновить с помощью программы X502Studio . Кроме того, теоретически возмо жно создание пользователем своей прошивки для данного к онтроллера, т ак к ак  Л Кар д предост авляет ис х о дные к о ды данной прошивки (git-репозиторий с ис х о дник ами прошивки мо жно найти по адресу https://gitlab.com/l-card/acq/devices/x502/e502/firmware/e502_m4 ), о днак о к ак ого-либо рук ово д с тва по данной прошивк е  Л Кар д для этого не предост авляет . Т акж е возм о жно рассмотрение предло ж ений по зак азу на доработку прошивки ARM Cortex-M4 по д нужные пользователю зада чи. 3. Существу ет ограничение ск орости переда чи данных для E-50 2. Если L-502 позво- ляет о дновременно осуще ствить вво д и выво д всех данных с аналоговых к аналов и цифровых линий на мак симальной ск орости, то в мо ду ле E-502 есть ограничения, к оторые завис ят от использу емого интерфейса: € при работе п о USB суммарная мак симальная ск орость пе реда чи сост авля ет пор ядк а 5 млн. отсчетов в секунду . Т . е. допу стимо использовать например вво д с АЦП и цифровых линий на 2 МГц и при этом выво д тольк о на о дин 21 +к анал ЦАП/DOUT на 1 МГц, или на два на 500 КГц. Если идет вво д тольк о с АЦП на 2 МГц, то возмо жно использовать все т р и к анала выво да на 1 МГц и т .д. При этом это ограничение обу словлено ограничением ск орости интерфейса между к онтроллером ARM Cortex-M4 и ПЛИС, а не самим интерфейсом USB. € при работе по Ethernet (TCP/IP) мак симальная с к орость уж е ограничена ск оростью переда чи п о сети по проток олу TCP . При работе мо ду ля тольк о на вво д ск орость ограничена 2.5 млн. отсчетов в секунду . Ск орость на выво д и влияние ее на ск орость вво да бу дет уточнена в дальнейшем. Для выво да ре- к оменду етс я по возмо жности использоват ь циклический режим выво да. Сле- ду ет т акж е уч итывать загрузку самой сети при переда че данных по Ethernet, т ак к ак она мо ж ет сильно влиять на мак симальную ск орость переда чи. 4. В связи с ограничением ск о р о сти переда чи в E-502 по ддер живаетс я возмо жность задать общий делитель для частот ы выво да , к оторый мо жно задать с помощью X502_SetOutF reqDivide r( ) или X502_SetOutF req() . В L -502 т акж е была введена данная возмо жность в версии прошивки ПЛИС 0.5, т аким образом для ее исполь- зования мо ж ет быть необ х о димо обновить прошивку . 5. При циклическ ом выво де в L-502 буфер нах о дитс я в драйвере на ПК, а в E-502 хранение циклическ ого буфера реализовано внутри памяти к онтроллера ARM Cortex-M4 мо ду ля, что поз воляет избеж ать загрузки интерфейса и ПК во вре- мя работы, о днак о приво дит к ограничению размера буфера. Т .е. при работе по сети циклический выво д не влияет на ограничение интерфейса, о днак о ограниче- ние в суммарную ск орость в 5 млн. отсче тов в секунду для мо ду ля с о храняетс я. Для версии прошивки ARM ниж е 1.0.3 буфер выво да в 3 млн. отсчетов (суммарно на все к аналы) делилс я на 2 равные части (о дна использу етс я для выво да сигнала, друг ая для загрузки следующего, чтобы мо жно было сменить сигнал без ост ано- ва предыдущего), поэтому о дин сигнал ограничен в 1.5 млн. отсчетов. На чиная с 1.0.3 буфер мо ж ет делитс я произвольно (в зависимости от размера з агруж аемог о сигнала), поэ тому размер сигнала ограничен зна чением  3 млн. отсчетов мину с размер выд а ваемого сейчас сигнала (0  если при загрузк е не идет генерация предыдущего). Т аким образом , если не использу етс я возмо жность с мены сигнала на лету (т .е. всег да после X502_OutCycleSetup() идет X502_OutCycleStop() или X502_StreamsStop() до с л е дую щ ей загрузки сигнала), то мо жно для о дного сигна- ла использ овать все 3 млн. отсчетов. Т акж е следу ет учитывать, что переда ча сиг- нала в ARM к онтроллер занимает время и пр и необ х о димости выда чи сиг н а л а о д- новременно с запу ск ом сбора необ х о димо до ждатьс я загрузки сигнала, что мо ж н о с делать например с помощью флаг а X502_OUT_CYCLE_FLA GS_W AIT_DONE в X502_OutCycleSetup() . 6. При работе по интерфейсу Ethernet не реализована функция X502_GetSendReadyCoun t() , а ф ункция X502_GetRecvReadyCoun t() г арантировано работ ает тольк о п о д ОС Windo ws. 7. При чтении зна чений цифровых вх о дов для E-502 ст аршие линии DI14, DI15, DI16 объединены с линиями с инхр ониза ц ии DI_SYN2, CONV_IN и ST AR T_IN со- ответственно. При этом, т ак к ак в обоих мо ду лях линии 17 и 18 объединены с 22 +DI_SYN1 и DI_SYN2, то зна чение 18-ой и 14-ой линии для E-502 всег да о дина- к овы. 8. Настройки по дт яж ек для цифровых вх о дов в E-502 от личаютс я от L-502 (см. опи- сание типа t_x502_pullups ) 9. В E-502 использу етс я друг ая микрос х ема ЦАП, к оторая т акж е планиру етс я к ис- пользованию в последующих ревизиях мо ду ля L-502. 3.1.1.2 Особенности при работе с мо ду лями E16 1. Т .к. по ст андарту USB потребление ток а в моме нт включения должно быть огра- ничено, в мо ду ле с делано управление запу ск ом вторичного пит ания из прошив- ки МК. По умолчанию вторичное пит ание включаетс я при первом обращении к у стройству из API и выключаетс я е сли было закрыто соединение по Ethernet или отключение USB к абеля. 1. E16 по цок олевк е сигнальных разъемов и диапазонам из мерений вх о дного сигна- ла это про долж ение линейки мо ду лей E14 . API вер хнего уровня с д е лано с ов- местимым с e502api. Для задания час тоты работы ЦАП и АЦП использу етс я опорная частот а 48 Мгц. Есть режим совместимости с мо ду лем E14-440 и работы с E14-440 API . В к а честве интерфейсного процессора использу етс я к онтроллер W CH32V307. Cигнальные разъемы по цок олевк е несовместимы с E502! 2. В E16 к ак и в Е14 реализован ст арт сбора по уровню аналогового сигнала - вы- ше/ниж е уровня, при пересечении границы уровня снизу-ввер х/свер ху-вниз. 3. Идентифик атор USB у стройства для E16 (VID_2A52&PID_0E16) от личаетс я от E502 и E14, поэтому в нек оторых случаях придетс я у ст ановить новые драйвера. 4. В E16 для циклическ ого выво да (выво да из внутреннего буфера без внешней по д- к а чки), доступен о дин буфер размером 11264 слов (в новых прошивк ах к ол-во мо ж ет изменитьс я). 5. В от личие от E502, в E16 н е т выделенных вых о дов синхронизации ST AR T_OUT и CONV_OUT, но их роль могут исполнять вых о ды TRIG или INT, к оторые мо жно переключать на вх о д или на вых о д, при к онфигурации  на вх о д эти к онт акты мо жно использовать к ак ST AR T_IN или CONV_IN. 6. Конт акты 17 и 18 цифрового разъјма с деланы унифицированными, по умолчанию на них выведены +3,3В и GND к ак в Е14-440, при по да че к оманды включения реле (см. t_x502_pullups ) на эти выво ды выво дитс я +15 и -15В к ак в Е14-140. 3.1.1.3 Особенности при работе с мо ду лями L T A37 Мо ду ли L T A37 со дер ж ат 10 к аналов ЦАП. Для к аждого к анала на вых о дном разъеме присутствуют два вых о да: +-20 В (1:1) и +-2В (1:10). Вых о ды ЦАПов к омутируютс я через встроенное в мо ду ль реле. Три фик сированные частоты дискретиза ц ии на все ЦАП: 192, 96, 48 кГц. 8 цифровых вых о дов и 2 вх о да могут работ ать в синхронном и асинхронном режиме. На вых о дах к аналов ЦАПов в мо ду лях L T A37 у ст ановлены реле (1 реле на 2 к анала), к оторыми мо жно управлять че- рез функцию X502_SetDigInPullup. У ст ановк а частоты цифрового вво да произво дитс я 23 +через X502_SetDinF req, при этом счит аетс я по дх о дящий делитель. Для L T A37 резу ль- тирующая частот а digin = 24576KHZ / p o w2(1..6) Из мо ду ля передаютс я слова, к аждое из к оторых со д е р жит 24 измеренных зна че н ий состо яний вх о дов.  при опросе о дного к анала все 24 бит а соответствуют последовательным 24-м измерениям состо яния вх о да DI1 или D I2, при этом ст арший бит соответству ет первому измерению, а младший  последнему .  при опросе обоих к аналов ст аршие 12 бит соответствуют опросу состо я- ния вх о да DI2, а младшие 12 бит  DI1. Аналогично в к аждой последовательности из 12 бит ст арший бит соответствуют первому измерению, а младший  последнему 3.1.1.4 Общие и специ ализированные функции для работы с мо ду лем В связи с тем, что большая часть функциональности мо ду лей L-502, E-502 и E16 сов- падают , то большинство функций реализовано общими для обоих мо ду лей. Все общие функции реализованы в библиотек е x502api . При этом названия функций и к онст ант на чинаютс я с X502_, а типов с t_x502_. Соответственно, д ля работы с обоими мо ду- лями использу етс я о дин и тот ж е тип описателя мо ду ля t_x502_hnd . Основное от личие при работе, завис ящее от интерфейса связи с мо ду лем, заклю- чаетс я в процедуре у ст ановки самой связи. Эти функции реализованы в от дельных библиотек ах l502api и e502api для мо ду ля L-502, E-502 и E16 соответстве нн о . При у ст ановки связи, вс я необ х о димая информация о том, к ак работ ать с мо ду лем по нуж- ному интерфейсу , со храняетс я внутри н е прозра чного описателя мо ду л я , а пользователь после открытия связи мо ж ет работ ать с мо ду лем о ди нак ово с использ ованием о дних и тех ж е общих функций из x502api независимо от типа мо ду ля и использу емого интер- фейса. Т акж е в от дельную группу специализированных функци й выделены функции по настройк е интерфейса Ethernet, к оторые реализованы тольк о в e502api и описаны в разделе Функции для настройки сетевых параметров мо ду л я E502 . 3.1.1.5 Совместимость проектов, разработ анных до введения библиотеки x502api Для реализации полной совместимости с проект ами, работ ающими тольк о с мо ду- лем L-5 02 и разработ анными до введения по ддер жки работы с мо ду лем E-502 (к оторая введена с версии 1.1.0) и создания общей библиотеки, в l502api реализованы функции из данной библиотеки предыдущих версий (1.0.x). При этом эти объявления этих функ- ций и соответсвующих типов вынесены в от дельный файл  l502api_compat.h , к оторый включаетс я из  l502api.h для со хранения совместимости. Эти типы определены через общие типы из  x502api.h , а функции реально тольк о вызывают аналогичные общие функции из x502api . Соответственно, проекты, раз работ анные для предыдущей версии без учет а общих функций, должны к орректно собиратьс я и при н о вой в ерсии библи о тек. Г лавное от личие, к оторое следу ет учитывать, что ес л и эти проекты распространяютс я с новой версией l502api , то необ х о димо распространять и библиотеку x502api , т ак к ак ее функции используютс я функциями новой версии l502api . Т ак к ак данные функции и типы полностью повтор яют большинство обобщенных функций (за исключением префик сов в названиях), то они не приво дятс я в данном документе. 24 +3.1.2 Общий а лгоритм для работы с мо ду лем Данный раздел описывает тип ичную последовательность вызова функций для ра- боты с мо ду лями L-502, E-502 и E16. Более по дробно к аждый шаг бу дет опи с ан в по- следующих разделах. Типичная последовательность вызовов имеет следующий вид: 1. При работе с мо ду лями по инте р фейс ам PCI-Express или U S B получить список серийных номеров с помощью функций L502_GetSerialList() и E502_UsbGetSerialList() , соответственно, или получить список записей о мо ду лях с п ом ощью L502_GetDevRecordsList() и E502_UsbGetDevRecordsList() . При работе по Ethernet мо жно использовать функции обнаруж ения у стройств в лок альной сети, описанные в г лаве Обнаруж ение мо ду лей в лок альной сети , ил и, если извес тен IP-адрес у стройства, перейти сразу к пунк ту 2. 2. Если в систем е присутств у ет нужный мо ду ль, со здать описате ль мо ду ля с помо- щью X502_Create() . 3. У ст ановить соединение с мо ду лем. При использовании записей о у стройстве от- крытие всег да выполняетс я с помощью X502_Op enByDevRecord() . При исполь- зовании серийного номера используютс я L502_Op en() или E502_O p enUsb() для L-502 и E-502, по дключенного по USB, соответственно. Чтобы у ст ановить связь с мо ду лем по Ethernet с использованием IP-адреса, не об х о димо использовать функ- цию E502_Op enByIpA ddr() . 4. При необ х о димости, п олучить дополнительную информацию о у стройстве с помо- щью X502_GetDevInfo() (в час тности для проверки наличия сигнально процессо- ра Blac kFin). 5. При наличии сигнального процессора (и ж елании работ ать с его использованием) загрузить прошивку сигнального процессора с помощь ю X 502_B f LoadFirm w are() . 6. У ст ановк а параметров мо ду ля с помощ ью набора функций дл я изменения настроек мо ду ля (названия функций на чинаютс я с X502_Set) 7. Переда ча у ст ановле н ных параметров в мо ду ль с помощью X502_Congure() . 8. Р абот а с мо ду лем в синхронном и/или асинхронном режиме (описана в пос л е ду- ющих по дразделах). 9. Закрытие мо ду ля X502_Close() . 10. Освобо ж дение описателя мо ду ля функцией X502_F ree() . 3.1.2.1 Р абот а с мо ду лем при синхронном вво де Типичная работ а с мо ду лем при синхронном вво де состоит из следующих шаго в: 1. Р азреш ение нужных с и нхронных поток ов (АЦП и/или цифровых данных) с по- мощью X502_StreamsEnable() . 2. Запу ск синхронных поток ов X502_StreamsStart() . 3. Чтение принятых данных из мо ду ля с помощью X502_Recv() . 25 +4. Обработк а пр очит анных данных с помощью X502_Pro cessData() , X502_Pro cessA dcData() или X502_Pro cessDataWithUserExt() . 5. При необ х о димости приема и обработки следующего блок а, перех о д к пун кту 3. 6. Ост анов синхронных поток ов с помо щью X502_StreamsStop() . 3.1.2.2 Р абот а с мо ду лем при синхронном поток ово м выво де Типичная работ а с мо ду лем при синхронном выво де состоит из следующих шагов : 1. У ст ановк а на чальных зна чений для ЦАП с помощью асинхронного выво да X502_AsyncOutDac() . 2. Р азреш ение нужных синхронных поток ов (к аналы ЦАП, цифровые вых о ды) с по- мощью X502_StreamsEnable() . 3. Запу ск предварительной загрузки данных н а выво д с помощью X502_PreloadStart() . 4. По дготов к а блок а данных на запись с помощью X502_PrepareData() . 5. Запись по дготовленного блок а в мо д у ль с помощью X502_Send() . 6. При необ х о димости повторить пунк т ы 4. и 5. нужное к оличество раз. При этом общий размер предварительно загруж енных данных не долж ен превысить размер буфера (по умолчанию 9 МСлов) 7. Запу ск синхронных поток ов вызовом X502_StreamsStart() . 8. Каждый раз при необ х о димости по д г рузить новые данные в буфер выполнить пункты 4. и 5. 9. По з авершению рабо ты выполнить ост анов синхронных поток ов с помощью X502_StreamsStop() . 3.1.2.3 Р абот а с мо ду лем при циклическ ом выво де Для выст авления циклическ ого сигнала без по дк а чки типичная последовательность выг лядит т ак: 1. У ст ановк а на чальных зна чений для ЦАП с помощью асинхронного выво да X502_AsyncOutDac() . 2. Р азреш ение нужных синхронных поток ов (к аналы ЦАП, цифровые вых о ды) с по- мощью X502_StreamsEnable() . 3. Выделение циклическ ого буфера ук азанного размера с помощью X502_OutCycleLoadStart() . 4. Загрузк а данных ук азанного размера для циклическ ог о выво да с помощью о дного или неск ольких вызовов X502_Send() . 5. Сделать загруж енный сигнал активным с помощ ью X502_OutCycleSetup() с фла- гом X502_OUT_CYCLE_FLA GS_W AIT_DONE . 26 +6. Запу ст и ть синхронный вво д-выво д через X502_StreamsStart() . 7. При необ х о димости вывести новый сигнал выполнить шаги 3.-5. 8. По завершению работы ост а н о вить с ин хронный вво д-выво д с помощью X502_StreamsStop() или тольк о циклический выво д через X502_OutCycleStop() . 3.1.2.4 Р абот а с мо ду лем при асинхронном вво де-выво де Типичная работ а при асинхронном вво де-выво де состо и т из вызова о дной из функ- ций: € X502_AsyncInDig() - асинхронный вво д зна чений цифровых линий € X502_AsyncOutDig() - асинхронный выво д зна чений на цифровые линии € X502_AsyncOutDac() - асинхронный выво д зна чения на о дин из к аналов ЦАП € X502_AsyncGetA dcF rame() - асинхронный прием о дного к адра АЦП 3.1.3 Создание и освобо ждение описател я мо ду ля Вс я работ а с мо ду лями L-502, E-502 и E16 осуществляетс я через описатель мо ду ля типа t_x502_hnd . Описатель м о ду ля предст авляет собой непрозра чный ук азате л ь на структуру , к оторая хранит всю информацию о мо ду ле и состо янии соединения с ним. Пользователь не имеет пр ямого доступа к полям структуры и все действия с мо ду- лем выполняютс я посредством вызова соответствующих ф ункций библиотеки, к оторые принимают описатель мо ду ля в к а честве первого параметра. Перед попытк ой у ст ановить связь с мо ду лем необ х о димо создать описатель, вызвав функцию X502_Create() , к оторая выделяет память по д с трук туру , инициализиру ет ее поля зна чениями п о умолчанию и возвращае т ук азатель на нее  описатель м о ду ля. После того к ак работ а с мо ду лем завершена, выделенная функцией X502_Create() память должна быть освобо ждена посредством вызова X502_F ree() . После ос вобо жде- ния описатель уж е не мо ж ет использоватьс я. 3.1.4 Открытие связи с мо ду лем 3.1.4.1 Общее описание п роцедуры у ст ановки связи с мо ду лем Для работ ы с мо ду лем необ х о димо у ст ановить с ним соединение с использованием ранее созданног о описателя. Функции для у ст ановки соединения с мо ду лем завис ят от использу емого интерфейса и описаны в последующих по дразделах. Если функция от к рытия связи с мо ду лем выполнена у спешно, то соединение с мо- ду лем у ст ановлено и дальше мо жно использ овать любые функции управления мо ду- лем. По завершению работы с мо ду лем необ х о димо закрыть соединение с помощью X502_Close() . Если ж е функция открытия связи верну ла ошибку , то это мо ж ет соответствовать о дной из следующих ситу аций: 27 +€ Связь с мо ду лем не у далось у ст ановить, т .к. мо ду ль не найден или не отвечает к орректно на запросы. В этом случае по заве ршению вызова функции описатель мо ду ля ост аетс я в ис х о дном состо янии, не связанном с к аким-либо соединением и его мо жно использовать тольк о для открытия нового соединения. € Связь с мо ду лем у ст ановлена, но обнаруж ены проблемы в работе мо ду ля. В этом случае соединение с мо ду лем все равно ост аетс я откр ытым, о дн а к о больша я часть функций работы с мо ду лем не доступна. При необ х о димости различить эти два разных состо яния мо жно с помощью функ- ции X502_IsOp ened() , к оторая провер яет , открыто л и соединение с мо ду лем в данный момент для ук азанного описателя. В большинстве случаев явно различать эти ситу ации не требу етс я и дост аточно вызвать функцию X502_Close() , к оторая закроет соедине- ние, если оно не закрыто, при любой ошибк е открытия соединения. Если функцию закрытия не вызывать по ошибк е открытия соединения, то с оединение мо ж ет ост атьс я открытым до освобо ждения памяти о п ис ателя с помощью X502_F ree() или до повтор- ного открытия соединения с помощ ью данного описателя. Соединение мо ж ет ост аватьс я открытым при следующих ошибк ах: € X502_ERR_FPGA_NOT_LO ADED  прошивк а ПЛИС не была у спешно загру- ж ена и ПЛИС нах о дитс я в нерабочем с осто янии. Ошибк а акту альна тольк о для мо ду ля E-502, т .к. в мо ду ле L-502 в ПЛИС реализован са м интерфейс PCI-Express и без загрузки прошивки ПЛИС мо ду ль не бу дет даж е определен в системе. В мо ду ле E-502 прошивк а ПЛИС загруж аетс я микрок онтроллером из Flash-памяти при ст арте мо ду ля. Ошибк а мо ж ет возник ать, если повреждена информация во Flash-памяти или по к аким-то причинам возникла ош ибк а при ее чтении из Flash- памяти или при е е загрузк е в ПЛИС. В данном р е жиме доступны тольк о функции работы с Flash-памятью, фу нкции управления сетевыми настройк ами мо ду л я и функция перезагрузки прошивки ПЛИС ( E502_ReloadFPGA() ). € X502_ERR_REF_FREQ_NOT_LO CKED  ош ибк а захват а опорной частоты синхронизации, идущей от г альваноотвязанной части управления вво дом-выво дом. Хот я доступ к Flash-памяти и регистрам ПЛИС мо ж ет работ ать нормально, любые функции вво да-выво да аналоговых или цифровых данных не могут быть осуществлены при данной ошибк е. 3.1.4.2 У ст ановк а связи с мо ду лем L-502 по интерфейсу PCI-Express Для на чала работы с мо ду лем необ х о димо у ст ановить с ним связь с помощью функ- ции L502_Op en() . Для различия мо ду лей использу етс я их серийные номера. Получить список серийных номеров всех найденных мо ду лей L-502 мо жно с по- мощью функции L502_GetSerialList() . Данная функци я принимает плоский масс ив, в к оторый бу дут со хранены найденные серийные номера, и мак симальное к оличество се- рийных номеров, к оторое мо жно со хранить в пере д анный массив. В простейшем случае мо жно задать мак симальное зна чение мо ду лей и для серийных номеров использовать ст атически выделенный массив: 0 #define MAX_MOD ULES_CNT 16 char serial_lis t[MAX_MODULES_CNT][ X50 2_SERIAL_SIZE ]; 28 +int32_t get_list _res = L502_GetSerialList (ser ial_list, MAX_MODULES_CNT , 0, NU LL); if (get_list_res <0) { /* Ошибка получени я с писка серийных номеров */ } else if (get_list_res ==0) { /* Не найдено ни одного модул я * / } else { /* Найдено get_lis t_res модулей */ } В общем случае для работы с произвольным мак симальным к оличеством мо ду лей мо жно воспользоватьс я т р е тьим параметром функции для получения к оличества най- денных мо ду лей в системе. При этом в к а че стве массива серийных номеров мо жно передать ну лево й ук азатель и ук а зать ну левой размер массива. После этого мо жно ди- намически выделить массив по д полученное к оличество серийных номеров и повт ор но вызвать L502_Ge t Se r i alList() для получения с ерийны х номеров всех мо ду лей L-502: 0 uint32_t dev_cnt ; int32_t res; /* Получаем количес тво модулей в системе */ res = L502_GetSerialLi st (NULL, 0, 0, &dev_cnt); if (res<0) { /* Ошибка получени я с писка серийных номеров */ } else if (dev_cnt==0) { /* Не найдено ни одного модул я * / } else { /* Выделяем плоски й м ассив под dev_cnt серийных номеров разме ром dev_cnt*L50 2_SERIAL_SIZE */ t_x502_ser ial_list serial_list= ( t_x502_seri al_list ) malloc(dev_c nt* X502_SERIAL_SIZE ); if (serial_lis t == NU LL) { /* Ошибка выделения па мяти */ } else { res = L502_GetSeria lList (serial_list, dev_cn t, 0 , NULL); if (res>0) { /* Получено res серийны х но меров */ 29 +} /* Освобождаем выде ленный массив под серийные номера */ free(serial _list); } } Следу ет отметить, что с о дн им мо ду лем о дновременно мо ж ет быть у ст ановлено толь- к о о дно соединение. При попытк е открыть мо ду ль, с к оторым уж е у ст ановлено соеди- нение через другой описатель (возмо жно, в другой программе) L502_Op en() вернет X502_ERR_DEVICE_A CCESS_DENIED . При этом L502_GetSerialList() по умолча- нию возвращает список всех серийных номеров мо ду л я , включая те, с к оторыми уж е у ст ановлено соединение. Если нужно получить список тольк о тех у стройств, с к ото- рыми еще не у ст ановлено соединения, то в L502_GetSerialList() мо жно передать флаг X502_GETDEVS_FLA GS_ONL Y_NOT_OPENED . Если в к а честве серийного номера в L502_Op en() передать ну левой ук азатель или пу стую с троку , то бу дет предпринят а попытк а открыть первый мо ду ль, с к оторым у дастс я у спешно у ст ановить соединение. Если ни с о дним мо ду лем у с т ановить соеди- нение не у далось, то бу де т возвращена ошибк а, полученная при попытки откры ть п о - следний мо ду ль. Т о есть, при наличии двух мо ду лей L-502 в системе, первый вызов L502_Op en() у ст ановит соединение с первым мо ду лем L-502, второй вызов - со вторым, а третий вернет уж е ошибку доступа X502_ERR_DEVICE_A CCESS_ D ENIED . 3.1.4.3 У ст ановк а связи с мо ду лем E-502 по интерфейсу USB При работе по USB алгоритм у ст ановления связи абсолютно аналогичен откр ытию мо ду ля L-502, с той разницей, что для получения списк а серийных номеров использу етс я функция E502_UsbGetSerialList() , а для открытия мо ду ля E-502 по серийному номеру использу етс я E502_Op enUsb() . 3.1.4.4 У ст ановк а связи с мо ду лем E-502 по интерфейсу Ethernet У с т ановить связь с мо ду ле м по Ethernet мо жно к ак по явно заданному IP-адресу у стройства, т ак и воспользо ватьс я функциями обнаруж ения у стройств в л о к альной се- ти, по дробно описанными в г лаве Обнаруж ение мо ду лей в лок альной сети . При у ст ановк е связи по IP-адресу дост аточно вызва ть функцию E502_Op enByIpA ddr() . Следу ет отметить, что в от личие от других интерфейсов, для к орректной работы по Ethernet должны быть настроены необ х о димые параметры, о чем описано в г лаве Особенности работы по интерфейсу Ethernet и настройк а сетевых п а р а метров . 3.1.4.5 У ст ановк а связи с мо ду лями с использованием записей о у стройстве Одним из мину сов функций открытия по серийному номеру являетс я то, что в мо- мент открытия необ х о димо знать, у стройству , по дключенному по к ак ому интерфейсу , соответству ет данны й номер, чтобы выбрать с оответствующую функцию для откры- тия у стройства. Для избеж ания этого вве ден специальный тип t_x502_devrec , соот- ветствующий запис и о найденном у стройстве. Данн ый тип со дер жит информацию о 30 +найденном у стройстве (название, серийный номер, интерфейс, флаги с по ддер живаю- щимис я возмо жност ями и т .п.), а т акж е со дер жит всю необ х о димую информацию о том, к ак у ст ановить связь и работ ать с соответствующим у стройством. Соответственно, о т у стройства и интерфейса завис ят тольк о функции получения записей о у стройстве, а у ст ановк а связи осуществляе тс я общей функцией X502_Op e nB yD evRecord() . Это позволяет получить все необ х о димые записи на от дельном эт а п е и со хранить их в общий массив, а в дальнейшем уж е выполнить от к рытие связи по нужным запис ям, не разбирая от дельно, что это за у стройство и по к ак ому интерфейсу по дключено. Особенностью являетс я необ х о димост ь пользователю очищать память, выде л е нн ую на эт апе инициализации записи об у стройстве. Очистк а памяти выполняетс я с помощью X502_F ree DevRecordList() . Запись об у стройстве использу етс я исключи те льно внутри X502_Op enByDevRecord() и при ж елании мо ж ет быть освобо ждена сразу после вызо- ва данной фун кции, если список записе й больше не нуж ен. Т акж е следу ет учес ть, что перед тем, к ак проинициализированную ранее запись передавать в функцию для полу- чения или инициализации нов ой записи (например для обновления списк а), необ х о димо ее сперва очистить для избе ж ания утечек памяти. Доступны следующие функции для инициализации записе й : € L502_GetDevRecordsList() инициализиру ет записи, соответст вую щ ие по дключен- ным мо ду лям L-502 по интерфейсу PCI-Express. По параметрам и использованию аналогична L502_GetSerialL ist( ) с учетом н е об х о димости освобо ждать записи. € E502_UsbGetDevRecordsList() инициализиру ет записи, соответствующие по дклю- ченным мо ду лям E-502 по интерфейсу USB. По параметрам и использованию ана- логична E502_UsbGetSerialLi s t() с учетом нео б х о димости освобо ждать записи. € E502_Mak eDevRecordByIpA ddr() инициализиру ет запись для у ст ановления соеди- нения с мо ду лем E-50 2 с заданным ад ре сом по интерфейсу Eth e rn e t. € E502_Mak eDevRecordByEthSv c() инициализиру ет запись для у ст ановления соеди- нения с мо ду лем E-502, соответствующем автоматически обнаруж енному сервису , по интерфейсу Ethernet Ниж е приведен пример, к оторый соз дает записи для все х найденных мо ду лей, по д- ключенных по интерфейсам USB и PCI-Express. Кроме того, предполаг аетс я, что в массиве ip_addr_list со дер житс я ip_cn t адресов, для к оторых т акж е создаютс я записи, а определение TCP_CONNECTION_TOUT задает т айма ут в мс на по д- ключение по сетевому ин те рф е йсу . Затем предост авляетс я выбор нужного у стройства, после чего с ним у ст анавливаетс я связь и все записи после этого очищаютс я. 0 uint32_t ip_add r_list[] = { .... } ; /* с писок ip-адресов устройств */ uint32_t ip_cnt = ... ; /* размер это го с писка */ uint32_t pci_de vcnt = 0 ; uint32_t usb_de vcnt = 0 ; int32_t fnd_dev cnt = 0; /* общ ее к ол-во найденных записей */ t_x502_devre c * devrec_list = NULL; /* список записей о устройст вах */ t_x502_hnd hnd = NULL; /* опис атель открытого устройства */ 31 +/* получаем количес тво подключенных устройств по интерфе йсам PCI и USB */ L502_GetDevR ecordsList (NULL, 0, 0, &pci_devcn t); E502_UsbGetD evRecordsList (NULL, 0, 0, &usb_de vcnt); if ((pci_devcnt+ usb_devcnt + ip_cnt) != 0) { /* выделяем память дл я ма ссива для сохранения найденного количества запи сей */ devrec_lis t = mall oc((pci_devcnt + usb_devcnt + ip_cnt ) * sizeof ( t_x 502_devrec )); if (devrec_lis t != NU LL) { unsigned i; /* получаем записи о модул ях L -502, но не больше pci_devcnt */ if (pci_devcnt! =0) { int32_t res = L502_GetD evRecordsList (&devrec_ list[fnd_devcnt], pci_devcnt , 0, NUL L); if (res >= 0) { fnd_devcnt += res; } } /* добавляем записи о моду лях E-502, подключенных по USB, в конец массива */ if (usb_devcnt! =0) { int32_t res = E502_UsbG etDevRecordsList (&devr ec_list[fnd_devcnt], usb_devcnt, 0, NUL L); if (res >= 0) { fnd_devcnt += res; } } /* создаем записи для пере данного массива ip-адресов */ for (i=0; i < ip_cnt; i++) { if ( E502_MakeDev RecordByIpAddr (&devrec _list[fnd_devcnt], ip_addr_list [i], 0, TCP_CONNECTI ON_TOUT) == X502_ERR_OK ) { fnd_devcnt ++; } 32 +} } } if (fnd_devcnt != 0) { uint32_t dev_ind ; /* обработка списка и выбор нуж ного устройства, индекс которого для примера сохран яется в dev_ind */ ..... if ( <устройство выбр ано> ) hnd = X502_Create () ; if (hnd==NULL) { /* Ошибка создания опис ателя модуля! */ } else { /* устанавливаем св язь с мо дулем по записи */ int32_t err = X502_Open ByDevRecord (hnd, &devrec_l ist[dev_ind]); if (err != X502_ERR_OK ) { /* ошибка установл ения соединения */ X502_Free ( hnd); hnd = NULL; } } } /* освобождени е ре сурсов действительных записей из спи ска */ X502_FreeD evRecordList (devrec_li st, fnd_devcnt); } /* очистка памяти самог о ма ссива */ free(devrec_ list); if (hnd != NULL) { /* работа с модулем */ 33 +X502_Close (hnd); X502_Free ( hnd); } В данном примере все ресурсы записе й освобо ждаютс я сразу после выбора нужного у стройства и у ст ановления с ним связи. При ж елании мо жно использовать другой по д- х о д, например, с о храняя записи вместе с созданными описате лями у стройства, чтобы в любой нужный момент мо жно было открыть, закрыть и снова открыть у стройство, освобо ждая к аждую запись тольк о в м омент завершения работы или получения ново- го списк а у с тройств. При э том с л е ду ет учитывать, что к опировать запись о у ст р ойс тве мо жно, но X502_F reeDevRecordList должна вызыватьс я т ол ь к о о дин раз на о дну к опию к аждой записи. Следу ет отметить, что все функции получения серийных номеров и у ст ановления связи с мо ду лями из предыдущих разделов реально реализованы через описанные в данном разделе функции и являютс я лишь обертк ами, созданными для упрощения про- цедуры поиск а и у ст ановления связи с у стройствами. 3.1.5 Р ежимы работы с сигнальным процессором и без него Мо ду ли L-502 и E-502 могут работ ать в двух режимах: € В шт атном режиме ( X502_MODE_FPGA ) вс я обработк а д а н ных выполняетс я ап- паратно в ПЛИС мо ду ля, а управление мо ду лем осуществляетс я путем пр ямой за- писи зна чений в регистры ПЛИС. В этом режиме доступны все шт атные функции сбора данных, о днак о у п о л ь зователя нет возмо жности расширить функ циональ- ные возмо жности самого мо ду ля. Этот режим доступен для всех мо дифик аций L-502 и E-502. € В режим работы с сигнальным процессором ( X502_MODE_DSP ) (отсутству ет в E16) всј управление сбором данных выполняетс я с и г нальны м процессором Blac kFin и все потоки данных на вво д и выво д идут через него. Т аким образом, пользователь мо ж ет путем создания мо дифицированной прошивки Blac kFin реализовать дополнительные в озмо жности (например, обратную связь в режиме реального времени). Э т от ре жим дос туп е н тольк о для мо дифик аций L-502-P-G, L-502-P-G-D и E-502-P-EU-D. Узнать о наличие сигнального процессора программно мо жно т акж е по флагу X502_DEVFLA GS_BF_PRESENT в флаг ах в за п ис и о у стройстве или в флаг ах информации о мо ду ле , к оторая мо ж ет быть получена после у ст ановления свя зи с мо ду лем через функцию L502_GetDevInfo(). При включении пит ания мо ду ль всег да нах о дитс я в шт атном режиме работы без ис- пользования сигнального процессора. Для работы сигнального процессора необ х о димо предварительно загрузить в нег о программу (прошивку). Это мо жно с делать из файла формат а l d r с помощью функции X502_BfLoadFirm w are() . После этого мо ду ль бу дет автоматически переве ден в режим с сигнальным процессором. При необ х о димости, мо жно специально переключить режим работы с помощью X502_SetMo de() . Это мо ж ет потребоватьс я, например, если прошивк а загруж ена в Blac kFin п о интерфейсу JT A G. Кроме того, следу ет иметь ввиду , что при открытии 34 +связи с у стройством не произво дитс я изменение режима работы мо ду ля. Т .е. если о дна программа у ст ановила режим X502_MODE_DSP , то при последующем открытии мо ду ля из другой программы этот режим со хранитс я. В этой связи мо ж ет понадобитьс я явно перевести мо ду ль в шт атный режим с помощь ю X502_SetMo de() . Поэтому ес л и программа не предполаг ает , что мо ду ль мог работ ать в режиме X502_MODE_DSP и выполнять к акие-то функции, к оторые не нужно прерывать, а работ ает с мо ду лем с  чистого лист а , рек оменду етс я сразу после у ст ановки связи у ст ановить явно нужный режим работы. Все настройки мо ду ля и работ а с синхронным вво дом-выво дом должны в ы полнять с я после у ст ановки нужного режима. В любой момент мо жно узнать текущий режим работы с помощью X502_GetMo de() . 3.1.6 У ст ановк а настроек мо ду ля Перед использованием мо ду ля, к ак правило, необ х о димо выполнить настройку его параметров. Сперва все настройки записываютс я в поля структуры описателя мо ду ля с помощью функций, на чинающих с я с X502_Set, к оторые бу дут описаны в последующих по дразделах, после чего у с т ановленные параметры передаютс я в мо ду ль с помощью X502_Congure() . 3.1.6.1 Настройк а последовательности опроса к аналов АЦП Мо ду ли L-502, E-502 и E16 предст авляют собой АЦП с последовательной к омм у - т ацией к аналов. Т о есть измерение неск ольких к аналов проис х о дит последовательно, путем переключения вх о дного к оммут атора АЦП. Как и в большинстве мо делей  Л Кар д последовательность опроса к аналов задаетс я с п о мощью управляющей т аблицы логических к аналов АЦП. Всего т аблица мо ж ет со дер ж ать от о дного до X502_L T ABLE_MAX_CH_CNT логических к аналов. Каждый логический к анал задает следующие параметры: € номер физическ ого к анала, с к оторого произво дитс я измерение. Номер физиче- ск ого к анала з адаетс я, счит ая от 0, то есть 0 оз н а чает первый к анал, 1  второй и т .д. Т аким образом, в дифференциальном ре жиме номер к анала мо ж ет быть от 0 до 15, а в режиме измерения с общей землей  от 0 до 31. € режим измерения АЦП из t_x502_lc h_mo de . € использу емый диапазон измерения (из t_x502_adc_range или t_e16_adc_range ). € к оэффициент у среднения по заданному логичес к ому к аналу (с м. раздел Коэффициент у среднения для логическ ого к анала (не реализов ан о в Е16) ). Задать параметры логическ ого к анала с нужным номером мо жно с помощью функ- ции X502_SetLChannel() , а к оличество логических к аналов в управляющей т аблице  с помощью X502_SetLChannelCoun t( ) . Например, необ х о димо измерить сперва напр яж ение вх о да X1 относительно общей земли для диапазона + /- 10В, затем измерить зна чение на 16 к анале в дифференци- альном ре жиме (между вх о дами X16 и Y16) с диапазоном +/-1В, а затем измерить напр яж ение между Y1 и общей землей (17 к анал в реж и м е с общей землей) с диа- пазоном +/-0.2В (Назна чение выво дов сигнального разъема и по дключение сигналов к мо ду лю описано в Руководстве пользователя ). В этом случае настройк а логическ ой т аблицы бу дет выг лядеть следующим образом: 35 +0 /* устанавливаем 3 логи ческих канала */ int32_t err = X502_SetL ChannelCount (hnd, 3); if (err == X502_ERR_OK ) { /* первый логическ ий канал соответствует измерению 1 канал а относительно об щей земли */ err = X502_SetLCha nnel (hnd,0,0, X502_LCH _MODE_COMM , X502_ADC_RA NGE_10 ,0); } if (err == X502_ERR_OK ) { /* второй логическ ий канал соответствует измерению 16 кана ла в диф. режиме */ err = X502_SetLCha nnel (hnd,1,15, X502_LCH _MODE_DIFF , X502_ADC_R ANGE_1 , 0); } if (err == X502_ERR_OK ) { /* третий логическ ий канал - измерение 17-го канала относительн о об щей земли */ err = X502_SetLCha nnel (hnd,2,16, X502_LC H_MODE_COMM , X502_ADC_RANG E_02 , 0); } if (err == X502_ERR_OK ) { /* установка други х н астроек */ } if (err == X502_ERR_OK ) { /* передаем настро йки в м одуль */ err = X502_Configu re (hnd,0); } if (err != X502_ERR_OK ) { /* произошла ошибк а п ри н астройке параметров... */ } После завершения измерения с настройк ами, соответс твующими последнему логиче- ск ому к аналу , следу ет измерение, соответствующее снова первому (с ну левым номером) логическ ому к аналу . Последовательность изме рений соответствующая о дному про х о ду логическ ой т аблицы называетс я к адром. При ж елании, между завершением измерения, соответствующего последнем у лог и - ческ ому к аналу к адра, и на чалом измерения, соответствующего первому логическ ому к аналу следующего к адра, мо ж ет быть вст авлена межк адровая задер жк а. 36 +3.1.6.2 Настройк а частоты синхронного вво да/выво да Все частоты поток ового сбо р а и выда чи данных основываютс я на опорной частоте синхронизации. В к а честве опорной частоты мо ж е т использоватьс я внутренний источ- ник частоты или внешний. В первом случае, опорная частот а мо ж ет быть 2М Гц либо 1.5МГц. По умолчанию использу етс я 2МГц. Изменить ее мо жно с помощью функции X502_SetRefF re q( ) . При внешней опорной частоты мо ж ет использов атьс я сигнал с произвольной ча- стотой до 1.5 МГц. При э том для того, чтобы функции библиоте к и мог ли оптималь- но по добрать настройки переда чи данных (если они не задаютс я вручную), а т акж е для того, чтобы к орректно работ али функции по дбирающие делители (см. ниж е) для получения нужных частот вво да/выво да необ х о димо з адать зна чение внешней опор- ной частоты, к оторая бу дет по дана. Это зна чение мо жно задать с помощью функции X502_SetExtRefF reqV alue() . Частот а сбора АЦП получаетс я с помощью деления зна чения опорной частоты на у ст ановленный к оэффициент , к оторый мо ж ет быть в д иапаз оне от 1 до X502_ADC_FREQ_DIV_MAX . Кроме того, к ак уж е упоминалось в предыдущем разделе , между измерением последнего логическ ого к анала о дного к адра и на чалом следующего к адра, мо ж ет быть добавлена межк адровая задер жк а. Межк адровая задер жк а задаетс я в виде к оличества перио дов опорной частоты синхронизации. Делитель частоты сбора АЦП и к оличество перио дов опорн ой частоты для меж- к адровой задер жки мо жно задать явно с помощью функций X502_SetA dcF reqDivider() и X5 02_ Se t A dcIn terframeDela y() соответственно. Вместо этих функций для у добства мо жно использовать функцию X502_SetA dcF req() , к оторой мо жно пере дать зна че ни я частоты сбора АЦП и частоты к адр ов в Г ерцах, а функция сама рассчит ает нужный делитель и зна чение межк адровой з адер жки, чтобы полученные част оты были наибо- лее близки к ук азанным. При этом функция вернет реально у ст ановившиес я зна чения частот . По д частотой сбора АЦП (f_acq) понимаетс я величина, обратная времени о дного преобразования, со ответствующего о дному логическ ому к аналу . По д частотой к адров (f_frame) понимаетс я величина, обратная времени от на чала измерения первого логи- ческ ого к анала о дного к адра до на чала измерения первог о логическ ого к анала с ледую - щего к адра. Это частот а соответству ет ч ас тоте сбора для о дного логическ ого к анала. Ниж е приведена диаграмма, иллюстрирующая на примере сб ора при заданных трех логических к аналах, к ак определяютс я упомянутые выше частоты. Рис. 3.1: Диаграмма сбора АЦП для трех логических к аналов 37 +Если межк адровая задер жк а не нужна, то мо жно передать ну левой ук азатель в к а честве второго параме тра X502_SetA dcF req() , тог да бу дет использоватьс я всег да ну- левая межк адровая задер жк а (т .е. и з мерение следующего к адра на чнетс я сразу после завершения п ре д ыдуще го). Помимо синхронного вво да с АЦП мо ду ли L-502, E-502 и E16 позволяют осуществлять с ин хронный вво д с цифровых вх о дов (к оличество зависит от типа мо ду ля, что описано в разделе От личие возмо жностей мо ду лей ). Т акж е к ак и для синхронного сбора данных АЦП, частот а синхронн ог о цифрового вво да определяетс я к ак опорная частот а, деленная на к оэффициент , к оторый мо жно у ст ановить с помощью X502_SetDinF r e qDivider() . Т ак ж е м о жно вызывать функцию X502_SetDinF req() , чтобы она рассчит ала этот к оэфф ициент для получения наи б олее близк ой частоты к ук азанной. Для синхронного вво да цифровых линий нет ни логичес к ой т аблицы (т ак к ак к аждый раз считываетс я зна чение в сех цифровых вх о дов и передаетс я в виде о дного слова), ни межк адровой задер жки  при запу ск е синхронного вво да все измерения выполняютс я че рез о динак овые промежутки вре мени. При этом частот а для вво да с цифровых линий мо ж ет от личатьс я от частоты сбора АЦП. Т акж е мо ду ли L-502, E-502 и E16 позволяют осуществить синхронный выво д па- раллельно на два к анала ЦАП (опция) и цифровые выво ды. При этом мак сималь- ная частот а выво да к аждого к анал а в два раза меньшей зна чения опорной частоты. Для мо ду ля E-502, а т акж е L-502 с прошивк ой ПЛИС версии 0.5 или выше, мо жно у ст ановить делитель частоты выво да (относительно опорной частоты в диапазоне от X502_OUT_FREQ_DIV_MIN до X502_OUT_FREQ_DIV_MAX ) либо явно с помо- щью функции X502_SetOutF reqDivider() , либо вызвать функцию X502_SetO utF req() , чтобы она по добрала т ак ой делитель т ак, чтобы частот а была наиболее близк а к задан- ной. При этом частот а задаетс я общая для всех поток ов выво да. 3.1.6.3 Коэффициент у среднения для логическ о го к анала (не реализовано в Е16) Р еально микрос х ема АЦП всег да работ ает на частоте равной опорной частоте син- хронизации. В случае, если час тот а сбора АЦП у ст ановлена меньше, чем опорная ча- стот а синхронизации, то на о дно измерение зна чения логическ ого к ан а л а п рих о дитс я n измерений АЦП (n = f_acq/f_ref  отнош ение у ст ановленной частоты сбора АЦП к опорной частоте дискретизации). При отключенном у среднении, первые n-1 измерений отбрасываетс я, что увеличи- вает время у ст ановления сигнала. При необ х о димости мо жно использовать неск ольк о последних отсчетов (na vg) для получения резу ль тирующего зна чения. Т ог да резу ль ти- рующего зна чение бу дет являтьс я средним между na vg пос л е дн ими измерениями, о д- нак о это со к ращ ает соответственно время на у ст ановления сигнала. Естественно na vg всег да меньше либо равно n. Кроме того na vg не мо ж ет превышать мак симальног о зна чения, равного X502_LCH_A V G_SIZE_MAX . Зна чение n a vg задаетс я последним параметром функции X502_SetLChannel() . Зна- чение равное 1 озна чает отсутствие у среднения. Зна чения равное 0 озна чает , что к оэф- фициент у среднения мо ж ет быть выбран по у смотрению библиотеки. В текущей реали- зации зна чение 0 аналогично зна чению 1, но это мо ж ет быть и з менено в последующих версиях. 38 +3.1.6.4 Настройк а режимов синхронизации По умолчанию в к а честве опорной частоты синхронизации использу етс я внутренняя частот а мо ду ля, а запу ск всех синхронных измерений осуществляетс я при выполнении функции X502_StreamsStart() . Однак о, при необ х о димости, воз мо жно задать к ак внешний источник опорной ча- стоты, т ак и внешний сигнал запу ск а синхрон ног о сбора/выда чи данных. Для э того могут быть использованы вх о ды цифрового разъема D I_SYN1 и DI_SYN2 (мо ж ет использоватьс я к ак фронт , т ак и спад о дного из этих сигналов), либо т акж е мо ж ет использоватьс я разъ ем синхронизации для орг анизации синхронного сбора данных по принципу ведущий-ведомые. В мо ду ле E16 для этих ж е целей используютс я к онт акты INT (19 к онт акт цифрового разъ ема) и TRIG (20 к онт акт аналогового разъема), при этом в E16 нет выделенных портов (ST AR T/CONV)_(IN/OUT), а TRIG и INT могут быть настроены к ак на вх о д, т ак и на вых о д и и г рать роль вх о дов или вых о дов сигналов ST AR T и CONV. Выбор внешнег о сигнала для задания опорной частоты синхронизации задаетс я с помощью X502_SetSyncMo de() , а у словие запу ск а с помощью функции X502_SetSyncStartMo de() . Следу ет отметить, что ес ли задано внешнее событие запу ск а, то для того, чтобы мо ду ль перешел в режим о жидания этого события, необ х о димо вызвать X502_StreamsStart() . Ост анов синхронного сбо р а /выд а чи данных всег да осуществляетс я прог р ам мно с помощью X502_StreamsStop() . При использовании разъема синхронизации для орг анизации сбора данных по принципу ведущий-ведомые, для ведущего мо ду ля источник ом опорной частоты синхронизации ост аетс я внутренняя частот а (режим X502_SYNC_INTERNAL ), а к аждый ве домый мо ду ль использу ет опорную частоту и/или признак запу с к а сбора от внешнего мастера, т .е. дл я к аждого ведомого мо ду ля долж ен быть у ст ановлен режим X502_SYNC_EXTERNAL_MASTER . 3.1.7 Синхронный и асинхронный режимы рабо ты Для мо ду лей L-502, E -5 02 и E16 дост у пны следующие данные на вво д: € отсчеты с АЦП € зна чения цифровых вх о дов Т акж е мо ду ль мо ж ет быть использована для выво да: € отсчетов на первый к анал ЦАП € отсчетов на второй к анал ЦАП € зна чений на цифровые вых о ды Т аким образом, имеетс я 2 к анала на вво д и 3 к анала на выво д. Каждый из этих к аналов мо ж ет работ ать к ак в синхронном режиме, т ак и асин- хронно. При этом к аждый к анал мо ж ет быть настроен индивиду ально, то есть мо жно выполнять, например, асинхронный вво д цифровых линий на фоне с инх ронног о пото- к ового сбора с АЦП или выво дить на о дин к анал ЦАП сигнал в синхронном поток овом режиме, в то время к ак в другой выст авлять зна чения асинхронно. Единственное ис- ключение  н е возмо жно осуществить асинхронный вво д с АЦП на фоне с и нхронного сбора данных с цифровых вх о дов. 39 +Т акж е сущест ву ет ограничение и с пользования асинхронного режима вместе с син- хронным в случае запу ск а синхронного вво да-выво да по внешнему у словию. В момент времени, к ог да мо ду ль о жидает внешний сигнал запу ск а синхронного вво да-выво да (т .е. после того, к ак была вызвана функция X502_StreamsStart() , но до того, к ак возникло внешнее у словие ст арт а), асинхронный вво д или выво д невоз мо ж ен. 3.1.7.1 Асинхронный режим работы При включении пит ания все к аналы нах о дятс я в асинхронном режиме. В асинхрон- ном режимы при вызове функции асинхронного вво да/выво да произво дитс я о днократ- ный вво д или выво д ук азанной информации. При этом задер жк а от вызова ф ункции до непосредственно момент а измерения данных для вво да или выст а вл е ния ук азанно- го зна чения на вых о де для выво да точно не определена. Т акж е точно не м о ж ет быть определена задер жк а между двумя последовательными операциями вво да/выво да. Плюсом асинхронного режима я вляетс я простот а его использования  д о ст аточно о дного вызова требу емой функции: € X502_AsyncInDig() - асинхронный вво д зна чений цифровых линий € X502_AsyncOutDig() - асинхронный выво д зна чений на цифровые линии € X502_AsyncOutDac() - асинхронный выво д зна чения на о дин из к аналов ЦАП Для о днократного вво да данных с АЦП использу етс я функци я X502_AsyncGetA dcF rame() , к оторая выполняет вво д о дного к адра данных АЦП. В от личии от других ф ункций асинхронного вво да-выво да, перед вызовом данной функци и необ х о димо выполнить настройку мо ду ля: необ х о димо задать управ- ляющую т аблицу АЦП (см. Нас тройк а последовательности опроса к аналов АЦП ). Измерение логических к аналов внутри к адра проис х о дит синхронно с заданной частотой сбора АЦП. Асинхронным являетс я вво д самих к адров, то е сть задер жк а между измерением к адров при последовательном вызове X502_AsyncGetA dcF rame() не определена. Например, к о д д ля выполнения о днократного измерения с 7 -го физическ ого к ана- ла в диф ференциальным режиме с диапазоном +/-0.5В мо ж ет выг лядеть следующим образом: 0 /* устанавливае м 1 логи ческий канал в управляющей таблице */ int32_t err = X502_SetL ChannelCount (hnd, 1); if (err == X502_ERR_OK ) { /* логический канал соот ветствует измерению 7 канала в диф. режиме */ err = X502_SetLChann el (hnd,0,6, X502_LCH_MO DE_DIFF ,L502_ADC_RANGE _05,0); } if (err == X502_ERR_OK ) { /* передаем настройк и в мод уль */ err = X502_Configure (hnd,0); 40 +} if (err == X502_ERR_OK ) { /* Считываем кадр дан ных АЦП из одного отсчета */ double val; err = X502_AsyncGe tAdcFrame (hnd, X502_PROC_FL AGS_VOLT , 1000, &val); if (err == X502_ERR_O K ) { /* верно считали значе ние val */ } } 3.1.7.2 Синхронный режим работы В синхронном режиме вво д или выво д данных осуще ствляетс я с заданной частотой, то есть время между соседними измерениями или выво дом соседний отсчетов определе- но. Ч астоты сбора для к аждого к анала з адаютс я относительно общей опорной час тоты синхронизации (по дробнее см. г лаву  Настройк а частоты синхронного вво да/выво да ) и запу ск с ин хронного вво да-выво да для всех к аналов осуществляетс я о дновременно. Для запу ск а синхрон ног о режима , необ х о димо сперва с помощью функции X502_StreamsEnable() разрешить синхронный режим по требу емым к аналам, а затем запу стить синхронный вво д/выво д по всем разрешенным к аналам с помощью X502_StreamsStart() . При синхр о н ном вво де мо ду ль произво дит измерения с заданной частот ой и сам передает данные по интерфейсу в буфер (для L -502 этот буфер нах о дитс я в драйвере и передаетс я мо ду лем с использованием BusMaster D MA, а для E-502  буфер выделяетс я бибилотек ой). Принятые в буфер данные могут быть прочит аны программой с помощью X502_Recv() . Аналогично, для синхронного выво да, мо ду ль сам по мере необ х о димости считывает данные из буфера и выво дит счит анные отсчеты с заданной частотой. Данные в б уф е р драйвера должны быть предварительно записаны с помощью X502_Send() . При этом, если к моме нту выво да очередного отсчет а данные в буф е р драйвера не поступили, то бу дет выведено предыдущее зна чение. В драйвере или библиотек е выделяетс я всего два буфера  о дин на пр ие м и о дин на пе р е да чу . Т о есть зна чения для синхронного вво да с циф ровых линий и отсчеты АЦП передаютс я о дним поток ом, т а к ж е о дним поток ом передаютс я все данные на вы- во д. Каждый отсче т передаетс я в виде 32-битного слова, со де р ж ащего дополнительную информацию, включающую в себ я признак, к к ак ому типу данных относитс я данный отсчет . Р азбор принятых данных на отсчеты АЦП и зна чения цифровых выво дов осущ еств- ляетс я с помощ ью X502_Pro ce ss D ata() . Помимо этого, данная функция т акж е мо ж ет осуществить перево д отс четов АЦП в Воль ты. С ле ду ет учесть, что в от личие от не к ото- рых других из д е ли й  Л Кар д , применение к алибровочных к оэффициентов осуществ- ляетс я аппаратно и зна чения уж е прих о дят в виде 24-битных отсчетов с уж е применен- ными к оэффициент ами. 41 +В 32-битном слове, соответствующем отсчету АЦП, п е редаетс я дополнительно ре- жим измерения и номер физическ ого к а н ала. X502_Pr o cessData() сравнивает эти зна- чения с теми, к оторые были заданы при настройк е управляющей т аблицы, чтобы убе- дитьс я в к орректности принимаемых данных. При этом X502_Pro cessData() о жидает , что с ее помощью бу дут обрабатыватьс я все принятые данные. Данные от АЦП прих о дят в том пор ядк е, в к отором произво дя тс я измерения, т . е. сперва измерения соответствующие всем л о гическим к аналам первого к адра, затем вто- рого и т .д. В этом ж е пор ядк е X502_Pro cessData() возвращает и преобразованные от- счеты АЦП. При этом в X502_Pro cessD ata() мо жно передавать и нецелое к оличество к адров (например, если з апущен синхронный вво д с цифровых линий, то заранее сло ж- но определить, ск ольк о в принятом блок е данных со дер житс я отсчетов с цифровых линий, а ск ольк о отсчетов с АЦП), в этом случае X502_Pro cessD ata( ) обработ ает и выдает все отсчеты, включая отсчеты нецелого к адра, а при следующе м ее вызове про- вер яет , что отсчеты АЦП на чинаютс я с логическ ого к анала, следующего за последним обработ анным до этого к аналом. Как ой логический к анал о жидаетс я следующим для обработки мо жно у з нать с помощью функ ции X502_GetNextExp ectedLc hNum() . Например, пу сть в управляющей т аблице АЦП у ст ановлено 7 логических к аналов. Если был принят блок данных от мо ду ля со дер ж ащий 5 отсчетов АЦП (и произволь- ное к оличество зна чений ци фровых вх о дов, если включен синхронный вво д с цифро- вых линий) и обработ ан с помощью X502_Pro cessData() , то X502_Pro cessData() вернет преобразованные 5 отсчетов АЦП, соответствующие логическим к аналом с индек сами 0,1,2,3,4. Следующий логический к анал, к оторый о жидаетс я для обработки  логиче- ский к анал с индек сом 5, поэтому X502_GetNextExp ectedLc hNum() вернет зна чение 5. Если обработ а ть следующий блок данных, со дер ж ащий 5 следующих отсчетов, то X502_Pro cessData() вернет отсчеты соответствующие к аналам с индек сами 5,6,0,1,2. Т .е . с помощью вызова X502_GetNextExp ectedLc hNum() мо жно узнать, к ак ому логи- ческ ому отсчету бу дет соответствовать первый элемент вых о дного массива при после- дующем вызове X502_Pro cessData() . Следу ет учесть, что по умолчанию буфер в драйвере или библиотек е рассчит ан на к оличество отсче тов, к оторое бу дет введено з а 4с непрерывного сбора. Если вовремя не считывать данные с помощью X502_Recv() , то произойдет пере п о л не н ие буфера в драйвере и часть данных, для к оторых не н аш лось в буфере мест а, бу де т потер яна. При последующем по явлении мест а в буфере, в то место в поток е, г де произошел раз ры в непрерывного поток а данных, бу дет вст авлено слово, предст авляющее собой сообщение о переполнении буфера. Если X502_Pro cessData() во вх о дном массиве об н аружит это слово, то функция вернет ошибку X502_ERR_STREAM_O VERFLO W . При этом, к ак и в случае возникновения других ошибок обработки, все отсчеты, к оторые был и до возникновения ошибки бу дут обработ аны и возвращены в вых о дны х массивах (размеры к оторых бу дут соответственно обновлены). Аналогично, для формирования общего поток а на выво д в треб у емом формате ис- пользу етс я функция X502_PrepareData() , принимающая данные и з трех массивов и со храняющая их во внешний массив. Если к ак ой-либо из источник ов не долж ен исполь- зоватьс я, то в к а честве массива передаетс я ну левой ук азатель. Для к аналов, к оторые не были настроены на синхронный режим с помощью X502_StreamsEnable() , вх о дной массив на анализиру етс я и данные из него не используютс я.. Следу ет отметить, что если для синхронного вво да инициализация поток а переда- чи проис х о дит по X502_StreamsStart() , т ак к ак данные на чнут поступать тольк о после запу ск а синхронного вво да, то с с ин хронным выво дом дело обстоит неск ольк о ина че. Т ак к ак по X502_StreamsStart() уж е должна на чатьс я выда ча синхронных данных, то 42 +часть данных уж е должна быть загруж е н а в мо ду ль. Т аким образ ом, после разреше- ния синхронного выво да по нужным к аналам с помощью X5 02_ Stream s Enable () и до запу ск а синхронного выво да с помощью X502_StreamsStart() необ х о ди мо осуществить предзагрузку части данных синхронного поток а. Для этого следу ет вызвать функцию X502_PreloadStart() , по к оторой в драйвере или библиотек е бу дет выделен буфер на переда чу и инициализирован поток на переда чу , а затем записать ч а сть синхронных данных в буфер драйвера с помощью X502_PrepareD at a ( ) и X502_Send() . Если этого не с делать, то синхронный выво д на чнетс я лишь после того, к ак данные бу дут записаны в мо ду ль и не бу дет привязан к на чалу синхронного сбора/выда чи данных. Кроме того, для синхронной выда чи данных на ЦАП рек оменду етс я предваритель- но у ст ановить н а чальные зна чения на ЦАП с помощью функции асинхронного выво да. В противном случае при на чале с и нхронного выво да мо ж е т быть небольшой перех о д- ный процесс от зна чения на ЦАП, к оторое было до запу ск а синхронного выво да, до выст авления первых нужных зна чений, т .к. ЦАП имеет свой филь тр и ограничения на ск орость изменения сигнала. 3.1.7.3 Циклическ ий выво д Для мо ду ля L-502, на чиная с в ерсии 1.0.4 драйвера и библиотеки, а т акж е для мо- ду ля E-502 (на чиная с версии 1.1.0), введе н а по ддер жк а циклическ ого выво да на ЦАП и цифровые выво ды. Этот режим позволяет загрузить сигнал полностью в буфер внут- ри драйвера ( для L-502) или процессора Cortex-M4 (для E-502), со дер жимое к оторого бу дет циклически выво дитьс я без необ х о димости дальне й ш ей по дк а чки. Данные для загрузки в циклический буф е р по дгот ав л иваютс я т акж е к ак и для пото- к ового выво да с помощью X502_PrepareData() и записываютс я с помощью X502_Send() и могут со дер ж ать к омбинацию данных на оба к анала ЦАП и на цифровые выво ды. Циклический выво д являетс я вариантом синхронного выво да и для его работы нуж- но разрешить нужные потоки на выво д че р е з X502_St re amsEn a b l e() и долж ен быть запущен синхронный вво д-выво д ч е рез X502_StreamsStart() . Т акж е к ак и с обычным поток овым выво дом, часть к аналов мо ж ет использоватьс я для выво да циклическ ого сигнала, а часть  асинхронно. Однак о нельзя часть к аналов выво да использовать в циклическ ом режиме, а часть в поток овом режиме с по дк а чк о й (естественно, цикли че - ский режим на выво д мо жно использовать с поток овым на вв о д). Для выво да циклическ ого сигнала использу етс я двойная буферизация  то есть мо ж ет быть выделено два буфера, пок а из о дного сигнал циклически выво дитс я, в другой м о ж ет по д г руж атьс я следующий сигнал. Смена сигнала проис х о дит по к онц у перио да предыдущего. При этом после записи о дного сиг н ала необ х о димо, чтобы у спела пройти с мена сигналов перед тем к ак мо жно бу дет загруж ать следующий, в противном случае функция X502_OutCycleLoadStart() вернет ошибку (что мо жно использовать к ак признак, что буфер еще не готов для загрузки нового сигнал). Проверку завершения смены сигнала мо жно с делать при соответствующих версиях ПО (см. описание функции X502_OutCycleChec kSetupDone() ) и явно с помощью фун кции X502_OutCycleChec kSetupDone() или использу я флаг X502_OUT_CYCLE_FLA GS_W AIT_DONE во время вызова X502_OutCycleSetup() , чтобы функция верну ла управление тольк о после выполнения смены сигналов. Для загрузки сигнала сперва вызываетс я функ ция X502_OutCycleLoadStart() , в к о- торой задаетс я раз мер циклическ ого буфера, к о торый бу дет использован для хранения отсчетов всех использу емых к аналов выво да. Например, если нужно ис п о л ьз овать два к анала ЦАП, н а к аждый из к оторых вывести сигнал из 1000 точек, то размер дол- 43 +ж ен быть ук азан 2000. Пос ле этого отсчеты загруж аютс я к ак и при поток овом выво де с по дк а чк ой с помощью функций X502_PrepareData() и X502_Send() . При этом сум- марно должно быть записано ровно стольк о ж е отсчетов, ск ольк о было ук азано при вызове X502 _ OutCycleL oadS tart() . После загрузки по вызову X502_OutCycleSetup() проис х о дит переключение на загруж енный буфер, при этом, в зависимости от текуще- го состо яния, это приво дит к сле д ующе му: € если синхронный вво д-выво д не запущен (не было вызова X502_StreamsStart() ) то на чинаетс я предзагрузк а циклическ ого сигнала в мо ду ль, о днак о реально выда ча сигнала на чнетс я тольк о при вызове X502_StreamsStart() (или по внешнему у с л ов и ю запу ск а). Это позволяет при вя зать на чало выво да первого отсчет а циклическ ого сигнала к на чалу вво да. При этом н е об х о димо вызывать X502_OutCycleSetup() с флагом X502_OUT_CYCLE_FLA GS_W AIT_DONE , чтобы г арантировать, что загрузк а сигнала завершитс я до X502_StreamsStart() (акту ально в первую очередь для E-502, г де переда ча данных идет по интерфейсу и мо ж ет занимать зна чительное время). € если синхронны й вво д-выво д запущен, но не было выведено ни о дного циклическ о- го сигнала до этого, то по X502_OutCycleSetup() на чинаетс я выво д циклическ ого сигнала. € если синхронный вво д -в ы в о д запущен и уж е выво дитс я предыдущий циклический сигнал, то после вызова X502_OutCycleSetup() в драйвере (или мо ду ле для E-502) бу дет взведен флаг о необ х о димости переключить сигналы. Пос л е этого собы- тия по достиж ению к онца предыдущего циклическ ого буфера бу дет произведена смена буферов выво да. Т аким образом это позволяет произво дить смену сиг н а- ла всег да в извес тной точк е. При смене сигнала проис х о дит освобо ждение ст аро- го буфера и тольк о после реальной смены мо жно бу дет вызвать следующий раз X502_OutCycleLoadStart() для загрузки следующего сигнала. При использовании флаг а X502_OUT_CYCLE_FLA GS_W AIT_DONE , функция вернет управление тольк о в момент , к ог да сама смена уж е произойдет (если эт а возмо жность по д- дер живаетс я ПО). Ост анов циклическ ого выво да мо жно осуществить о дним из следующий способов: € X502_OutCycleStop() ост анавливает циклический выво д после выво да послед- ней точки на границ е циклическ ог о буфера. Т о есть эт а функция использу етс я, чтобы циклический выво д был завершен точно в известной точк е и на вых о дах ост ались зна чения, соотве тствующие последним отсчет ам в циклическ ом сигнале. При этом сам а функция не д о жидаетс я ост анова выво да, если не ук азан флаг X502_OUT_CYCLE_FLA GS_W AIT_DONE . € X502_StreamsDisable() с ук аз анием всех использу емых к аналов выво да приво дит к не медленному завершению выво да и освобо ждением всех буферов. На вых о дах ост анутс я зна чения, к оторые были в момент вызова. Пос ле этого мо жно бу дет заново разрешить и проинициализировать выво д к ак в цик личес к ом т ак и в пото- к овом режиме с по дк а чк ой. € X502_StreamsStop() приво дит к немедленному ост анову всех поток ов и ост ано- ву генерации опорной частоты синхронизации. На вых о де ост аютс я те зна чения, к оторые были в момент вызова ф ункции. 44 +3.1.7.4 Р азмер буфера и шаг для синхронного режима В данном разделе приво дитс я дополнительная ин формация о том, к ак мо жно настроить д о п олните л ьные параметры, управляющие пере да чей поток а данных в синхронном режиме между мо ду лем и ПК. Эти параметры по умолчани ю настраиваютс я библиотек ой автоматически. Предполаг аетс я, что большинству пользователей должны по дойти автоматически настраиваем ы е параметры и данный раздел не являетс я об язательным. Однак о для случаев, к ог да автоматически определенные параметры не по дх о дят , пользователь мо ж ет задать их самос то ятельно. Для этого в этом разделе приво дитс я описа н ие , к ак выбир а етс я размер буфера и шаг библиотек ой, что озна чают эти параметры и к ак их мо жно настроить вруч ную. Как уж е было ск азано в предыдущем разделе прием и переда ча синхронных данных осуществляетс я через буфера в драйвере или библиотек е  о дин буфер на при е м, о дин на переда чу . Выделение буфера на вво д осуществляетс я по X502_Str e amsStart () , если был раз- решен х от я бы о дин источник для с ин хронного вво да. Выделение буфера на выво д осуществляетс я п о X502_PreloadStart() . При этом размер буфера определяе тс я автоматически библиотек ой в зависимости от у ст ановленной частоты переда чи данных. Р азмер буфера рассчитываетс я т ак, чтобы его хватило на 4 с екунды при синхронном вво де и на 3 секунды при синхронном выво де. Вторым параметром, х арактеризующим переда чу , являетс я шаг переда чи. Для мо- ду ля L-502 этот параметр определяет шаг прерываний. Пе р е да ча данных между бу- фером драйвера и мо ду лем осуществляетс я непосредстве н но самим мо ду лем по DMA. При этом, ч то бы драйвер мог узнать о том, что данные были записаны в буфер или прочит аны из него, при переда че определенного к оличества отсчетов мо ду ль генери- ру ет прерывание. Т о есть реально драйвер  узнае т о том, что были переданы данные тольк о после того к ак бу дет пе р е дано заданное к оличество отсчетов, называемое в дан - ной г лаве шагом пре р ываний (Т очнее ск азать, не позж е, чем бу д е т передано заданное к оличество отсчетов, т ак к ак драйвер мо ж ет прочит ать зна чение счетчик а переданных данных из мо ду ля и по другим у словиям). Т аким образом, малый шаг прерываний позволяет драйверу раньше узнает о при- нятых или переданных данных, но приво дит к большей за грузк е системы. Библиотек а рассчитывает шаг прерываний т ак, чтобы пр е рывани я проис х о дили с частотой 64 раз а в секунду . Для мо ду ля E-502 этот параметр определяет использу емый размер з апр ос а по USB. Кроме того при вво де данные ст авятс я на переда чу в ПК при из размере равным ша- гу , но при этом при отсутствие поступления новых данных могут быть пост авлен на переда чу и ме н ьш ий объем данных. Если пользователя по к аким-либо причинам не у страивают эти зна чения он мо ж ет настроить их вручную с помощью функций X502_SetStreamBufSize() и X502_SetStreamStep() . Эти функции должны быть вызваны до инициализации поток ов переда чи (до X502_StreamsStart( ) или X502_PreloadStart() ). В частности, случаями к ог да зна чения библиотеки мог ут не у строить, могут быть следующие: € Пользователь использу ет с вою прошивку Blac kFin и использу ет к аналы синхрон- ных данных для переда чи пользовательских данных, к оторые сильно изменяют ск орость переда чи данных. В этом случае библиотек а не мо ж ет правильно опре- делить частоту переда чи, т ак к ак не знает ск о р ос ти переда чи пользовательских 45 +данных. € Пользователь изменяет к аналы, к оторые используютс я в синхронном режиме, на лету (после X502_St re amsStar t() ) и при этом ск орости переда чи по этим к ана- лам суще ственно от личаютс я. Т ак к ак расче т размера буфера выполняетс я при инициализации к анала, то он осуществ л я етс я тольк о по тем к аналам, к оторые были разрешены на тот момент . Если, например, был разрешен тольк о синхрон- ный сбор с А ЦП на относительно небольшой частоте, то буфер бу дет выделен т акж е небольшой. При этом, если после запу ск а сбора д а н ных бу дет разрешен синхронный вво д с цифровых линий на частоте 2М Гц, то ве ро ятнее всего этот буфер ок а ж етс я недост аточного размера, и с большой веро ятностью произойдет его переполнение. Если ж е оба этих поток а были разрешены изна чально, а потом синхронный вво д циф ров ы х линий бу дет запрещен, то рассчит анный изна чально шаг прерывания бу дет слишк ом большим и данные от ме дл е нн о го поток а АЦП бу- дут обновлятьс я с большими задер жк ами. Если ж е частоты к аналов соизмеримы, то включение/отключение о дного из н их не приведет к существенному и з мене- нию параметров. Изменение шаг а прерывания и размера буфера при запущенном сборе данных на текущий момент невозмо жно. 3.1.8 Особенности работы по интерфейсу Ethernet и настройк а сетевых параметров Если USB-интерфейс в мо ду ле E-502 всег да работ ает и не треб у ет дополнительной к онфигурации, то для работы по интерфейсу Ethernet необ х о димо выполнить настройку параметров интерфейса и разрешить данный интерфейс. Следу ет отметить, что при разрешенном Ethernet-интерфейсе с мо ду лем мо жно работ ать к ак по USB, т ак и по Ethernet. При этом сбор/генерация данных могут выполнятьс я о дновременно тольк о по о дному интерфейсу (по к оторому пришла к оманда на запу ск сбора/выда чи). Основными параметрами для работы по Ethernet являютс я: € IP-адрес у стройства. Записываетс я к ак 4 цифры от 0 до 255 (мо ду ль по ддер живает тольк о проток ол IPv4), разделенные точк ам и (например, 192.168.0.10). Состоит из адреса по дсет и и адреса у стройства внутри по дсети. Последний долж ен быть уник альным внутри по дсети. € Маск а по дсети. Определяет к ак ая часть адреса относитс я к адресу по дсети, а к ак ая к адресу у стройства. Маск а 255.255.255.0 озна чае т , что первые 3 циф ры (192.168.0) обозна чают адрес по дсети, последняя цифра (10) - адрес у стройства в по дсети. € IP-адрес шлюза. Ис п о л ь зу етс я тольк о к ог да мо ду ль E-502 и х ост , с к оторого вы- полняетс я управление мо ду лем, нах о дятс я в разных по дсет ях. Мо ду ль передает пак еты по адресу шлюза, если адрес назна чения нах о дитс я не в той ж е по дсети, что и мо ду ль. При работе в лок альной се ти не использу етс я. € MA C-адрес мо ду ля (6 цифр от 0 до 255, к оторые записываютс я в 16-рич ном фор- мате). Физический адрес у стройства, к оторый долж ен быть уник ален внутри ло- к альной се ти. В  Л Кар д  для к аждого мо ду ля прописываетс я свой заво дск ой MA C-адрес, к оторый нельзя и з менить. Однак о, при необ х о димости, пользователь 46 +мо ж ет задать свой пользовательский MA C адр е с и разрешить его использова- ние в место заво дск ого. При этом все г да есть возмо жность вернутс я к заво дск ому MA C-адресу , запретив пользовательский. € Имя экземпляра у стройства. Уник альное имя данного экземпляра в виде с тро- ки (до 64 анг лийских символов или 32 ру сских). Использу етс я д ля возмо жно- сти автоматическ ого обнаруж е ни я мо ду лей в лок альной сети (по дробнее в г лаве Обнаруж ение мо ду лей в лок альной сети ). Для работы в первую очередь необ х о димо задать правильные IP-параметры (адрес, маску и, при необ х о димости, адрес шлюза), по дробнее о чем описано в соответствующем разделе FAQ . IP-параметры мо ду ля E-502 м огут быть у ст ановлены 3-мя способами: € Заданы вручную (ст атические параметры). Пользователь сам долж ен позаботить- с я о том, чтобы адрес принадлеж ал нужной по дсети и был уник альный в ней. € Получены автоматически от DHCP-сервера. Если задано авто матическ ое полу- чение адреса и в лок альной сети присутству ет DHCP-сервер, то мо ду ль делает запрос к нему и использу ет выделенные DHCP-сервером IP-адрес а. € Мо ж ет использоватьс я ав томатически получаемый лок альный (link-lo cal) адрес (в соответствии с RFC3927 ). Адрес выбираетс я случайным образом в диапазоне от 169.254.1.0 до 169.254.254.255 и провер яетс я, ч т о в сети нет другого у стройства с т аким адресом (если ес ть, то идет попытк а выбора следующего адреса и т .д.). Это делает возмо жным по дключение к у стройству в лок альной сети без специальной к онфигурации. Сл е ду ет о днак о отметить, что т .к. адрес действителен тольк о в о дной сети, то два разных у стройства в разных сет ях могут иметь о динак овый li n k- lo cal адрес, что приво дит к том у , что если у ПК неск ольк о активных интерфейсов (и на обоих использу етс я link-lo cal адрес или наоборот обычный адрес), то х ост не знает на к ак ом интерфейсе иск ать нужное у стройство. Т .е. для по дключения по link-lo cal адресу на ПК долж ен быть либо о дин активный сетевой интерфейс, либо на нужном интерфейсе долж ен использоватьс я l ink-lo cal адре с, а на другом ст атический или полученный по DHCP адрес. При включении автоматическ ого получения адреса мо ду ль выби рае т себе link-lo cal адрес (и провер яет его уник альность), параллельно выполняя поиск в сети DHCP- сервера. Ес ли DHCP сервер не обнаруж ен, то использу етс я link-lo cal адрес. Как тольк о бу дет обнаруж ен DHCP-сервер, то предпочтение от даетс я полученному от него адресу (в частности при ст арте в сети с DHCP сервером мо ду ль мо ж ет нек оторое время до по- лучения адреса от него использовать link-lo cal адрес). По добный алгоритм использу етс я при автоматическ ом получении адреса в частности в ОС Windo ws, а т акж е и во многих дистрибутивах Lin ux (иног да предост авляя возмо жность от дельного разрешения DH CP и link-lo cal адреса). Следу ет т акж е иметь ввиду , что автоматически получаемый адрес мо ду ль провер яет на уник а л ь н ос ть в сети, поэтому существу ет задер жк а в неск ольк о секунд от по дключения к сети мо ду ля до назна чения адреса. Автоматическ ое полу- чение адреса не требу ет дополнительных настроек, о днак о при этом неиз вестен адрес у стройства со сто р о н ы ПК для у ст ановления соединения. Для решения этой пробле- мы возмо жно использование процедуры поиск а у стройств в лок альной сети, описанной в следующем разделе . Изменить се тевые настройки мо жно с помощью программы X502Studio . 47 +Т акж е изменение сетевых настроек мо ду ля возмо жно программным образом че- рез API библиотеки. Для этого существу ет от дельный тип опи с ателя к онфигурации t_e502_eth_cong_hnd . Для изменения к онфигурации нужно выполнить следующие шаги: 1. Создать описатель к онфигурации с помощью E502_EthCongCreate() . 2. Прочит ать текущую к онфигурацию у стройства с помощью E502_EthCongRead() (соединение с мо ду лем должно быть у ст ановлено) 3. Мо жно получить н уж н ые параметры с помощью функций E502_EthCongGetXXX() и/или у ст ановить н ов ы е з н а чения с помощью функций E502_EthCongSetXXX(). 4. После завершения изменений мо жно записать измененную к онфигурацию в мо- ду ль с помощью E502_EthCongW rite() . Мо ду ль со хранит новую к онфигурацию в энергонезависимой памяти, запрещает Ethernet-интерфейс, после чего снова его переинициализиру ет уж е с новыми параметрами. При этом, ес л и соединение с у стройством было выполнено по Ethernet, то для дальнейшей работы нужно разо- рвать соединение и у ст ановить заново (использу я новые параметры) Для избеж ания не пр е дн а меренного измене н ия к онфигурации по с ети, к онфигура- ция мо ж ет быть защищена простым паролем. Пок а пароль не у ст ановлен в к а честве пароля нужно передавать пу стую строку . У ст ановк а новог о пароля вып олняе тс я аналогично любым др уг им изменениям параметров к онфигурации (с помощью E502_EthCongSetNewP assw ord( ) ). В случае, если пароль забыт , то мо жно у ст ановить соединение по USB и изменить к онфигурацию (включая пароль), введя в к а честве текущего пароля серийный номер мо ду ля. 3.1.9 Обнаруж ение мо ду ле й в лок альной сети В от личие от интерфейсов USB и PCI-Express, для интерфейса Ethernet нет ст ан- дартной возмо жности определения по дключенных у стройств. Однак о есть р яд проток о- лов, реализация к оторых позволяе т обнаружить у стройства заданного типа в лок альной сети. Для этой возмо жности мо ду ль E-502 по ддер живает п рото к олы mDNS (в соответ- ствии с RFC6762 ) и DNS-SD ( RFC6763 ). В соответствии с ними, к аждое у стройство при по дключении объявляет набор сервисов, к оторый оно по ддер живает . Чтобы различать экземпляры у стройст в, по ддер живающие о динак овый тип се р ви- сов, у к аждого экземляра есть с вое уник альное имя. Это имя задаетс я во время к онфи- гурации мо ду ля. Если оно не у ст ановлено, то в к а честве имени экземпляра использу етс я  E502_ < серийный_номер >  , о днак о пользователь мо ж ет задать свое имя, х арактери- зующее назна чение к онкретного мо ду ля для более наг лядной идентифик ации. Кроме имени экземпляра у к аждого сервиса мо ж ет быть набор тек стовых параметров, описы- вающих данный экземпляр (для E-502 это параметры задающие имя типа у с тройства (поле devname, зна чение равно всег да E -5 02) и серийный номер (поле serial). В соответствии с этим проток олом у х ост а в лок альной сети ес ть возмо жность най- ти все экземпляры заданного сервиса в сети. Для обнаруж ения должна быть запущена соответствующая служба (ил и демон), отслеживающая изменения наличия у стройств в сети, а уж е функции e502api работ ают с данной службой. В ОС Lin ux в к а честве р е али- зации данного проток ола использу етс я демон A v ahi, к оторый включен в большинство современных дистрибутивов и вх о дит в ст андартную у ст ановку (или нужно у ст ановить 48 +соответствующий пак ет вручную). В ОС Windo ws использу етс я служба Bonjour, к ото- рая шт а тн о не у ст ановлена, о днак о у ст ановщик вклю че н в L-Card L502/E502 SDK и данная служба бу дет у ст ановлена при выборе соответствующего пункт а (следу ет отметить, что т ак к ак с лу ж ба являетс я от дельным про дуктом, к оторый мо ж ет исполь- зоватьс я и другим ПО, то она не у даляетс я автоматически при у далении L-Card L502/E502 SDK . При не об х о димости следу ет вручную у далить с лужбу через у ст анов- ку и у даление программ в  Панели управления ). Использование данного API позволяет автоматически обнаруживать по дключенные в лок альной сети у стройства, во многом по добно другим интерфейсам. Однак о суще- ствуют следующие особенности: € Обнаруж ение мо ду ля связано с посылк ой пак етов и приемом ответов, к оторые могут быть потер яны при определенных у словиях и потребовать переповторов. Это выполняет с я на уровне проток ола и невидимо для пользователя, о днак о надо иметь ввиду , что обнаруж ение у стройства мо ж ет п о тр е бовать нек оторого времени. € Т ак к ак отключение отслеживаетс я на уровне проток ола, нет опове щения о физи- ческ ом отключении к абеля . Соответственно при выключении пит ания или выдер- гивании к абеля отключение мо ду ля мо ж е т быть не обнаруж ено на пр о т яж ении длительного времени. Для поиск а у стройств следу ет вызвать E502 _ EthSv cBro wseStart() , после чег о использовать полученный к онтек ст поиск а у стройств в сети для последующих вызовов E502_EthSv cBro wseGetEv en t() . Каждый вызов возвращает информацию мак симум об о дном событии и немедленно возвращ ает управление, к ак тольк о оно произошло. Каждому новому обнаруж енному мо ду лю с оответству ет событие E502_ETH_SV C_EVENT_ADD . В случае изменения параметров (например адрес а) прих о дит с обытие E502 _ ETH_SV C_EVENT_CHANGED , а при исчезновении (при у словии описанных выше особенностей)  E502_ETH_SV C_EVENT_REMO VE . Для к аждог о события возвращаетс я описатель сетевого сервиса , по к оторому мо жно определить, к ак ому мо ду лю соответству ет событие (узнать имя экзем- пляра и серийный номе р мо ду ля), а т акж е запросить IP-адрес мо ду ля. Для к аждого события (кроме с луч а я, к ог да событие не обнаруж е н о и в озвращен к о д E502_ETH_SV C_EVENT_NONE ) этот описатель необ х о димо освобо дить с помощью E502_EthSv cRecordF ree() к ак тольк о он ст анет ненужным. В п рос тейшем случае мо жно вызвать E502_EthSv cBro wseGetEv en t() пок а не бу дет обнаруж ено по явление нужного у стройства или не истечет т айма ут на поиск у стройства. При ж елании т акж е мо жно использовать перио дический вызов E502_ EthSv cBro wseGetEv en t() для посто янного мониторинг а у стройств в сети. В любом случае, к ог да поиск у стройств зак ончен, необ х о димо вызвать E502_EthSv cBro wseStop() . У ст ановить с вязь с мо ду лем по описателю сетевого сервиса мо жно к ак вручную по полученному адресу через E502_EthSv c R e cordResolv eIPv4A ddr() , т ак создать запись о у стройстве с помощью E502_Mak e DevRecordByEthS v c() для последующег о открытия через X502_Op enByDevRecord() . 3.1.10 Сигналы в нешней синхронизации мо ду ля Е16 Для внешних сигналов синхронизации в мо ду ле Е16 отведены к онт акты INT и TRIG сигнальных разъемов. При этом эти сигналы к онфигурируютс я на вво д или на выво д 49 +в зависимости от настроек. Сигнал мо ж ет быть с игналом с т арт а сбора данных или сиг- налом на чала перио да преобразования АЦП. Есть выбор срабатывания между фрон- том или спадом сигнала. Выбор сигнала на чала ст арт а сбора данных осуществляетс я через функцию X502_SetSyncStartMo de() . Выбор сигнала на чала перио да преобразо- вания произво дитс я через функцию X5 02_ Se t SyncM o de() . При ис п о л ьз овании внешних сигналов синхронизации необ х о ди м о произвести настройку к онт актов INT и TRIG че- рез функцию X502_SetDigInPullup() . Т акж е внутренний сигнал ст арт а сбора данных мо ж ет быть выработ ан по аналогово му сигналу выбранного логическ ого к анала и по у словиям настроенным через функцию X502_SetSyncStartMo de() . При этом реализо- вано неск ольк о у словий: выше уровня, ниж е уровня, пр и перех о де снизу-ввер х, при перех о де свер ху-вниз. 50 +Г лава 4 Конст анты, типы данных и функции библиотеки 4.1 Конст анты и перечисления 4.1.1 Конст анты и макроопределения Конст ант а Зна чение Описание E502_DEVICE_NAM E E502 L502_DEVICE_NAM E L502 E16_DEVICE_NAME E16 LTA37_DEVICE_NA ME LTA37 LTA11_DEVICE_NA ME LTA11 X502_LTABLE_MAX _CH_CNT 256 Мак симальное к оличество логических к аналов в т аб- лице E16_LTABLE_MAX_ CH_CNT 128 Мак симальное к оличество логических к аналов в т аб- лице для E16 X502_ADC_RANGE_ CNT 6 Количество диапазонов для измерения напр яж е- ний E16_ADC_RANGE_C NT 4 LTA11_ADC_RANGE _CNT 4 X502_ADC_COMM_C H_CNT 32 Количество к аналов АЦП в режиме с общей зе млей X502_ADC_DIFF_C H_CNT 16 Количество к аналов АЦП в дифференциальном ре- жиме X502_LCH_AVG_SI ZE_MAX 128 Мак симальное зна чение для аппаратного у сред- нения по логическ ому к аналу 51 +X502_ADC_FREQ_D IV_MAX (1024*1024) Мак симальное зна чения делителя частоты АЦП E16_ADC_FREQ_DI V_MAX (0x800000) Мак симальное зна чения делителя частоты АЦП для мо ду ля E16 по отно- шению к опорной частоте E16_REF_FREQ_48000KHZ LTA11_ADC_FREQ_ DIV_MAX (0x800000) X502_DIN_FREQ_D IV_MAX (1024*1024) Мак симальное зна чение делителя частоты син- хронного цифрового вво да E16_DIN_FREQ_DI V_MAX (0x800000) Мак симальное зна чение делителя частоты син- хронного цифрового вво да для мо ду ля E16 по отно- шению к опорной частоте E16_REF_FREQ_48000KHZ LTA37_DIN_FREQ_ DIV_MAX 64 E16_ADC_FREQ_DE FAULT 500000 Зна чения частоты АЦП по умолчанию, ис- пользу етс я в функции X502_SetA dcF req и X502_CalcA dcF req2 ес- ли параме тр f_acq = 0 LTA11_ADC_FREQ_ DEFAULT 500000 LTA11_MAX_ADC_F REQ 1000000 E16_DIN_FREQ_DE FAULT 500000 Зна чения частоты цифро- вого вх о да DIN по умол- чанию, использу етс я в функции X502_SetDinF req и X502_CalcDinF req2 если параметр f_din = 0 E16_OUT_FREQ_DE FAULT 500000 Зна чения частоты ЦАП и цифровых вых о дов по умолчанию, ис- пользу етс я в функции X502_SetOutF req и X502_CalcOutF req2 ес- ли параметр f_dout = 0 X502_OUT_FREQ_D IV_MIN 2 Минимальное зна чение де- лителя час тоты синхрон- ного выво да 52 +X502_OUT_FREQ_D IV_MAX 1024 Мак симальное зна че- ние делителя частоты синхронного выво да E16_OUT_FREQ_DI V_MAX 0x8000 Мак симальное зна чение делителя частоты син- хронного выво да для мо ду ля E16 по отноше- нию к опорной частот е E16_REF_FREQ_48000KHZ X502_OUT_FREQ_D IV_DEFAULT 2 Зна чение делителя часто- ты выво да по умолчанию (к оторое т акж е всег да ис- пользу етс я в L-502 с в ерси- ей прошивки ПЛИС ниж е 0.5) X502_OUT_FREQ_D IV_MIN_REF_LF 1 Минимальное зна чение делителя частоты син- хронного выво да при внешней опорной частоте ниж е X502_OUT_FREQ_REF_ LF_VAL X502_OUT_FREQ_R EF_LF_VAL 700000 Зна чение вне шней опор- ной частоты, ниж е к ото- рой разрешено у ст анавли- вать зна чение делите л я ча- стоты генерации до X502_ OUT_FREQ_DIV_MIN_REF_LF X502_ADC_INTERF RAME_DELAY_MAX (0x1FFFFF) Мак симальное зна чение межк адровой задер жки для АЦП E16_ADC_INTERFR AME_DELAY_MAX (0xFFFF) Мак симальное зна чение межк адровой задер жки для АЦП E16 X502_BF_CMD_DEF AULT_TOUT 500 Т айма ут по умолчанию для выполнения к оманды к Blac kFin X502_ADC_SCALE_ CODE_MAX 6000000 Ко д АЦП, соответствую- щий мак с и м альн о му зна- чению шк алы E16_ADC_SCALE_C ODE_MAX (0x80 * 0x7fff) Ко д АЦП, соответствую- щий мак с и м альн о му зна- чению шк алы LTA11_ADC_SCALE _CODE_MAX (0x80 * 0x7fff) Ко д АЦП, соответствую- щий мак с и м альн о му зна- чению шк алы 53 +X502_DAC_SCALE_ CODE_MAX 30000 Ко д ЦАП, соответствую- щий мак с и м альн о му зна- чению шк алы E16_DAC_SCALE_C ODE_MAX 0x7fff LTA37_DAC_SCALE _CODE_MAX 0x650000 X502_DEVNAME_SI ZE 32 Мак симальное к оличество символов в строк е с назва- нием у стройства X502_SERIAL_SIZ E 32 Мак симальное к оличество символов в строк е с серий- ным номером X502_IMPLEMENTA TION_SIZE 16 Мак симальное к оличе- ство символов в с трок е с идентифик атором b oard implemen tation X502_LOCATION_S TR_SIZE 64 Мак симальное к оличество символов в строк е с описа- нием по дключения X502_MAC_ADDR_S IZE 6 Р азмер MA C-адреса для Ethernet интерфейса X502_INSTANCE_N AME_SIZE 64 Р азмер строки с описанием экземпляра у стройства X502_PASSWORD_S IZE 32 Мак симальный размер строки с паролем на настройки X502_EXT_REF_FR EQ_MAX 1500000 Мак симально возмо жное зна чение внешней опорной частоты E502_P1_EXT_REF _FREQ_MAX 2000000 Мак симально возмо жное зна чение внешней опорной частоты для E502-P1 X502_FLASH_USER _SIZE 0x100000 Р азмер пользовательск ой области Flash-памяти X502_BF_REQ_TOU T 500 Ст андартный т айма ут на выполнение з апр ос а к Blac kFin в м с X502_DAC_RANGE 5. Диапазон ЦАП в воль т ах E16_DAC_RANGE 10. LTA37_DAC_RANGE 20V 20. Вых о д 1:1 и 1 :10 LTA37_DAC_RANGE 2V 2. LTA37_DACRANGE_ CNT 2 X502_DAC_CH_CNT 2 Количество к аналов ЦА П LTA37_DAC_CH_CN T 10 X502_DAC_CH_CNT _MAX 20 Мак симальное к оличество к аналов ЦАП по ддер жива- емое библиотек ой 54 +X502_DOUT_LINES _CNT 16 Количество цифровых вы- х о дов у мо ду ля X502_STREAM_IN_ MSG_OVERFLOW 0x01010000 слово в поток е, озна чаю- щее, что произошло пере- полнение X502_DEVREC_SIG N 0x4C524543 Зна чение поля сигнату- ры в записи о у стройстве t_x502_devrec . Признак, что запись действительна (у ст анавливаетс я функци- ями по получению записей о у стройствах) LTA11_ADC_RANGE _10000 0 Диапазоны измерения для к анала АЦП L T A11 Диапа- зон +/-10V LTA11_ADC_RANGE _2500 1 Диапазон +/-2.5V LTA11_ADC_RANGE _625 2 Диапазон +/-0.625V LTA11_ADC_RANGE _156 3 Диапазон +/-0.156V X502_DAC_CH ((ch_cnt * range) + ch) LTA37_DAC_CH X502_DAC_CH(ch, range, LT A37_DAC_ CH_CNT) 4.1.2 События по ис к а сетевых сервисов Тип: t_e502_eth_svc_event Описание: Ко ды событий, возник ающих при поиск е сетевых сервисов , воз- вращаемые функцией E502_EthSvcBrowseGetEvent() Конст ант а Зна чение Описание E502_ETH_SVC_EV ENT_NONE 0 Ни о дного с обытия не произошло E502_ETH_SVC_EV ENT_ADD 1 Обнаруж ено по явление нового с етевого сервиса E502_ETH_SVC_EV ENT_REMOVE 2 Обнаруж ено исчезнове ни е ранее до- ступного се тевого сервиса E502_ETH_SVC_EV ENT_CHANGED 3 Изменение параметров ранее обнару- ж енного сетевого сервиса 55 +4.1.3 Ко ды ошибок библиотеки Тип: t_x502_errs Описание: Ко ды ошибок библиотеки Конст ант а Зна чение Описание X502_ERR_OK 0 Функция выполнена без ошибок X502_ERR_INVALI D_HANDLE -1 В функцию передан недействи- тельный описатель мо д у ля X502_ERR_MEMORY _ALLOC -2 Ошибк а выделения памяти X502_ERR_ALREAD Y_OPENED -3 Попытк а открыть уж е открытое у стройство X502_ERR_DEVICE _NOT_FOUND -4 У стройст во с заданными пара- метрами не найдено в системе X502_ERR_DEVICE _ACCESS_DENIED -5 Доступ к у стройству запрещен (Как правило из-за того, что у стройство уж е открыто в другой программе) X502_ERR_DEVICE _OPEN -6 Ошибк а открытия у стройства X502_ERR_INVALI D_POINTER -7 В функцию передан недействи- тельный ук азатель X502_ERR_STREAM _IS_RUNNING -8 Функция не мо ж ет бы т ь выпол- нена при запущенном поток е сбо- ра данных X502_ERR_RECV -9 Ошибк а чтения данных синхрон- ного вво да, для tcp-соединения тип ошибки со дер житс я в errno X502_ERR_SEND -10 Ошибк а записи данных для син- хронного выво да X502_ERR_STREAM _OVERFLOW -11 Произошло переполнение внут- реннего буфера для поток а син- хронного вво да X502_ERR_UNSUP_ STREAM_MSG -12 Неизвестное сообщение в поток е синхронного вво да X502_ERR_MUTEX_ CREATE -13 Ошибк а с оздания системного мьютек са X502_ERR_MUTEX_ INVALID_HANDLE -14 Неверный описатель мьютек са X502_ERR_MUTEX_ LOCK_TOUT -15 Истекло время о жидания осво- бо ждения мьютек са X502_ERR_MUTEX_ RELEASE -16 Ошибк а о свобо ждения мьютек са X502_ERR_INSUFF ICIENT_SYSTEM_ RESOURCES -17 Недост аточно системных ресур- сов X502_ERR_NOT_IM PLEMENTED -18 Данная возмо жность еще не реа- лизована X502_ERR_INSUFF ICIENT_ARRAY_SIZE -19 Недост аточный размер массива X502_ERR_FPGA_R EG_READ -20 Ошибк а чтения регис тра FPGA X502_ERR_FPGA_R EG_WRITE -21 Ошибк а записи регис тра FPGA X502_ERR_STREAM _IS_NOT_RUNNING -22 Сбор данных уж е ост ановлен 56 +X502_ERR_INTERF ACE_RELEASE -23 Ошибк а освобо ждения интер- фейса X502_ERR_THREAD _START -24 Ошибк а запу ск а поток а X502_ERR_THREAD _STOP -25 Ошибк а ост анова поток а X502_ERR_DEVICE _DISCONNECTED -26 У стройст во было отключено X502_ERR_IOCTL_ INVALID_RESP_SIZE -27 Неверный размер отв ет а на управляющий запрос X502_ERR_INVALI D_DEVICE -28 Неверный тип у стройств а X502_ERR_INVALI D_DEVICE_RECORD -29 Недействительная запись о у стройстве X502_ERR_INVALI D_CONFIG_HANDLE -30 Неверный описатель к онфигура- ции мо ду ля X502_ERR_DEVICE _NOT_OPENED -31 Связь с у стройством закрыт а и ли не была у ст ановлена X502_ERR_INVALI D_OP_FOR_IFACE -32 Данная операция не доступна для текущего интерфейса связи с у стройством X502_ERR_FPGA_N OT_LOADED -33 Не загруж ен ПЛИС мо ду ля X502_ERR_INVALI D_USB_ CONFIGURATION -34 Неверная к о н фигурация USB- у стройства X502_ERR_INVALI D_SVC_BROWSE_ HANDLE -35 Неверный описатель к онтек ст а поиск а у стройств в сети X502_ERR_INVALI D_SVC_RECORD_ HANDLE -36 Неверный описате ль записи о сервисе X502_ERR_DNSSD_ NOT_RUNNING -37 Не за п ущ ена программа обнару - ж ения у стройств в лок альной се- ти X502_ERR_DNSSD_ COMMUNICATION -38 Ошибк а п ри обращении к про- грамме обнаруж ения у стройств в лок альной сети X502_ERR_SVC_RE SOLVE_TIMEOUT -39 Превышен т айма ут запроса пара- метров автообнаруж енного сете- вого у стройства X502_ERR_INSTAN CE_NAME_ENCODING -40 Ошибк а в к о д ировк е имени эк- земпляра у стройства X502_ERR_INSTAN CE_MISMATCH -41 Экземпляры мо ду лей не совпада- ют X502_ERR_NOT_SU P_BY_FIRMWARE -42 Возмо жность не по ддер живает- с я текущей версией прошивки у стройства X502_ERR_NOT_SU P_BY_DRIVER -43 Возмо жность не по ддер живает- с я текущей версией драйвера у стройства X502_ERR_OUT_CY CLE_SETUP_TOUT -44 Превышено время о жидания у ст ановления цикли че ск ого сигнала на выво д 57 +X502_ERR_UNKNOW N_FEATURE_CODE -45 Неизвестный к о д по ддер живае- мой возмо жности X502_ERR_INVALI D_LTABLE_SIZE -102 Задан неверный размер логиче- ск ой т аблицы X502_ERR_INVALI D_LCH_NUMBER -103 Задан неверный номер логиче- ск ого к анала X502_ERR_INVALI D_LCH_RANGE -104 Неверно задано з на чение диапа- зона АЦП X502_ERR_INVALI D_LCH_MODE -105 Неверно задан режим измерения для логическ ого к анала X502_ERR_INVALI D_LCH_PHY_NUMBER -106 Неверно задан номер физическ о- го к анала при настройк е логиче- ск ого X502_ERR_INVALI D_LCH_AVG_SIZE -107 Неверно задан размер у средне- ния для логическ ог о к анала X502_ERR_INVALI D_ADC_FREQ_DIV -108 Неверно задан делитель частоты сбора данных АЦП X502_ERR_INVALI D_DIN_FREQ_DIV -109 Неверно задан делитель частоты синхронного вво да цифровых ли- ний X502_ERR_INVALI D_MODE -110 Неверно задан режим работы мо- ду ля X502_ERR_INVALI D_DAC_CHANNEL -111 Неверный номер к анала ЦАП X502_ERR_INVALI D_REF_FREQ -112 Неверный к о д выбора опорной частоты синхронизации X502_ERR_INVALI D_INTERFRAME_DELAY -113 Неверно задано зна чение меж- к адровой задер жки X502_ERR_INVALI D_SYNC_MODE -114 Неверно з адан режим синхрони- зации X502_ERR_INVALI D_STREAM_CH -115 Неверно задан номер поток а дан- ных X502_ERR_INVALI D_OUT_FREQ_DIV -116 Неверно задан делитель частоты синхронного выво да X502_ERR_REF_FR EQ_NOT_LOCKED -131 Ошибк а захват а опорной часто- ты синхронизации X502_ERR_IOCTL_ FAILD -132 Управляющий запрос к драйверу завершен с ошибк ой X502_ERR_IOCTL_ TIMEOUT -133 Истек т айма ут о жидания завер- шения выполнения управляюще- го запроса к драйверу X502_ERR_GET_IN FO -134 Ошибк а получения информации о у стройстве от драйвера X502_ERR_DIG_IN _NOT_RDY -135 За время о жидания не было счи- т ано новое слово с цифровых ли- ний X502_ERR_RECV_I NSUFFICIENT_WORDS -136 Принято недост аточно слов от мо ду ля 58 +X502_ERR_DAC_NO T_PRESENT -137 Попытк а выполнить операцию, требующую наличие ЦАП, при его отсутс твии X502_ERR_SEND_I NSUFFICIENT_WORDS -138 Передано недост аточно слов в мо ду ль X502_ERR_NO_CMD _RESPONSE -139 Не пришло отв ет а на переданную к оманду X502_ERR_PROC_I NVALID_CH_NUM -140 Неверный номе р к анала в обра- батываемом поток е синхронного вво да X502_ERR_PROC_I NVALID_CH_RANGE -141 Неверный к о д диапазона в обра- батываемом поток е синхронного вво да X502_ERR_FLASH_ INVALID_ADDR -142 Задан неверный адрес во Flash- памяти X502_ERR_FLASH_ INVALID_SIZE -143 Задан неверный размер блок а данных при работе с Flash- памятью X502_ERR_FLASH_ WRITE_TOUT -144 Истек т айма ут о жидания завер- шения записи во Flash-память X502_ERR_FLASH_ ERASE_TOUT -145 Истек т айма ут о жидания завер- шения стирания блок а Flash- памяти X502_ERR_FLASH_ SECTOR_BOUNDARY -146 Заданная область для стирания Flash-памяти нарушает границу блок а в 4 Кбайт X502_ERR_SOCKET _OPEN -147 Не у далось открыть сок ет для со- единения X502_ERR_CONNEC TION_TOUT -148 Превышено время по дключ е ни я X502_ERR_CONNEC TION_CLOSED_BY_DEV -149 Соединение за к рыто другой у стройством X502_ERR_SOCKET _SET_BUF_SIZE -150 Не у далось у ст ановить заданный размер буфера сок ет а X502_ERR_NO_DAT A_CONNECTION -151 Соединение для переда чи дан- ных не у ст ановлено X502_ERR_NO_STR EAM_END_MSG -152 Не у далось до ждатьс я сообщения о завершении поток а X502_ERR_CONNEC TION_RESET -153 Соединение был о сброшено дру- гой стороной X502_ERR_HOST_U NREACHABLE -154 Не у далось найти х ост с ук азан- ным адресом X502_ERR_TCP_CO NNECTION_ERROR -155 Ошибк а у ст ановления TC P- соединения, мо ж ет возник ать к ог да соединение с мо ду лем уж е у ст ановлено (тольк о о дно TCP соединение мо ж ет управлять мо ду лем) 59 +X502_ERR_LDR_FI LE_OPEN -180 Не у далось открыть файл про- шивки Blac kFin X502_ERR_LDR_FI LE_READ -181 Ошибк а чтения из фала прошив- ки Blac kFin X502_ERR_LDR_FI LE_FORMAT -182 Неверный формат файла про- шивки Blac kFin X502_ERR_LDR_FI LE_UNSUP_FEATURE -183 Используютс я возмо жность LDR-файла, недоступные при записи прошивки Blac kFin по HDMA X502_ERR_LDR_FI LE_UNSUP_STARTUP_ ADDR -184 Неверный ст артовый адрес про- граммы в прошивк е Blac kFin X502_ERR_BF_REQ _TIMEOUT -185 Истек т айма ут выполнения за- проса на чтения/з апись памяти Blac kFin X502_ERR_BF_CMD _IN_PROGRESS -186 Команда для Blac kFin все еще нах о дитс я в процессе обработки X502_ERR_BF_CMD _TIMEOUT -187 Истекло время выполнения управляющей к оманды процес- сором Blac kFin X502_ERR_BF_CMD _RETURN_INSUF_DATA -188 Возвращено недост аточно дан- ных в ответ на к оманду к Blac kFin X502_ERR_BF_LOA D_RDY_TOUT -189 Истек т айма ут о жидания готов- ности процессора Blac kFin к за- писи прошивки X502_ERR_BF_NOT _PRESENT -190 Попытк а выполнить операцию для к оторой нуж ен сигнальный процессор при отсутствии сиг- нального процессора в мо ду ле X502_ERR_BF_INV ALID_ADDR -191 Неверный адрес памяти Blac kFin при записи или чтении по HDMA X502_ERR_BF_INV ALID_CMD_DATA_SIZE -192 Неверный размер данных, пере- даваемых с управляющ ей к оман- дой в Blac kFin 4.1.4 Интерфейс соединения с мо ду лем Тип: t_x502_iface Описание: Интерфейс соединения с мо ду лем Конст ант а Зна чение Описание X502_IFACE_UNKN OWN 0 Неизвестный интерфейс X502_IFACE_USB 1 У стройс тво по дключено по USB X502_IFACE_ETH 2 У стройс тво по дключено по Ethernet через TCP/IP 60 +X502_IFACE_PCI 3 У стройс тво по дключено по PCI/PCIe 4.1.5 Флаги, управляющие поиск ом присутствующих мо ду лей Тип: t_x502_getdevs_flags Описание: Флаги, управляющие поиск ом присутствующих мо ду лей Конст ант а Зна чение Описание X502_GETDEVS_FL AGS_ONLY_NOT_ OPENED 1 Признак, что нужно вернуть серийные номера тольк о тех у стройств, к оторые еще не от- крыты 4.1.6 Флаги для управления цифровыми вых о д ами Тип: t_x502_digout_word_flags Описание: Флаги управления цифровыми вых о дами. Могут быть объединены через лог ич е ск ое ИЛИ со зна чениями цифр ов ы х вых о д о в при асинхронном выво де с помощью X502_AsyncOutDig() или переданы в X502_PrepareData() при синхронном выво де. Конст ант а Зна чение Описание X502_DIGOUT_WOR D_DIS_H 0x00020000 Запрещение (пере во д в третье сос то яние) ст аршей половины цифровых вых о дов X502_DIGOUT_WOR D_DIS_L 0x00010000 Запрещение младшей половины цифровых вых о дов E16_DIGOUT_WORD _DIS 0x00030000 Для мо ду ля E16 по ддер живаетс я тольк о полное запрещение цифровых вых о дов 4.1.7 Конст анты для выбора опорной частоты Тип: t_x502_ref_freq Описание: Конст анты для выбора опорной частоты Конст ант а Зна чение Описание E16_REF_FREQ_48 000KHZ 48000000 Частот а 48МГц для E16 X502_REF_FREQ_2 000KHZ 2000000 Частот а 2МГц X502_REF_FREQ_1 500KHZ 1500000 Частот а 1.5МГц 4.1.8 поля i o_mo de в регистре io_hard Тип: t_x502_io_mode Описание: поля io_mo de в регистре io_hard Конст ант а Зна чение Описание X502_MODE_REF_F REQ_2000 0 Частот а 2МГц X502_MODE_REF_F REQ_1500 2 Частот а 1.5МГц E16_MODE_REF_FR EQ_48000 3 Частот а 48МГц для E16 61 +4.1.9 Диапазоны измерения для к анала АЦП Тип: t_x502_adc_range Описание: Диапазоны измерения для к анала АЦП Конст ант а Зна чение Описание X502_ADC_RANGE_ 10 0 Диапазон +/-10V X502_ADC_RANGE_ 5 1 Диапазон +/-5V X502_ADC_RANGE_ 2 2 Диапазон +/-2V X502_ADC_RANGE_ 1 3 Диапазон +/-1V X502_ADC_RANGE_ 05 4 Диапазон +/-0.5V X502_ADC_RANGE_ 02 5 Диапазон +/-0.2V 4.1.10 Диапазоны измерения для к анала АЦП E16 Тип: t_e16_adc_range Описание: Диапазоны измерения для к анала АЦП E16 Конст ант а Зна чение Описание E16_ADC_RANGE_1 0000 0 Диапазон +/-10V E16_ADC_RANGE_2 500 1 Диапазон +/-2.5V E16_ADC_RANGE_6 25 2 Диапазон +/-0.625V E16_ADC_RANGE_1 56 3 Диапазон +/-0.156V 4.1.11 Тип: t_x502devs_dac_range Описание: Конст ант а Зна чение Описание X502_DAC_RANGE_ 5000 0 Вых о д +/-5V для x50 2 E16_DAC_RANGE_1 0000 0 Вых о д +/-10V для E 1 6 4.1.12 Р ежим измерения для логическ ого к анала Тип: t_x502_lch_mode Описание: Р ежим измерения для логическ ого к анала Конст ант а Зна чение Описание X502_LCH_MODE_C OMM 0 Измерение напр яж ения относительно общей зем- ли X502_LCH_MODE_D IFF 1 Дифференциальное измерение напр яж ения X502_LCH_MODE_Z ERO 2 Измерение со бственного ну ля 62 +4.1.13 Р ежимы синхронизации Тип: t_x502_sync_mode Описание: Р ежимы задания источник а частоты синхронизации и признак а на чала синхронного вво да-выво да Конст ант а Зна чение Описание X502_SYNC_INTER NAL 0 Внутренний сигнал X502_SYNC_EXTER NAL_MASTER 1 От внешнего мастера по разъ - ему межмо ду льной синхрониза- ции (ST AR T_IN/CONV_IN для X502_SetSyncStartMo de/X502_SetSyncMo de ) X502_SYNC_DI_SY N1_RISE 2 По фронту сигнала DI_SYN1 X502_SYNC_DI_SY N1_FALL 3 По спаду сигнала DI_SYN1 X502_SYNC_DI_SY N2_RISE 6 По фронту сигнала DI_SYN2 X502_SYNC_DI_SY N2_FALL 7 По спаду сигнала DI_SYN2 E16_SYNC_TRIG_R ISE 2 Т ольк о для E16! Важно правиль- но у ст ановить направление TRIG или INT на вх о д снятием флаг а E16_MODE_TRIG_OUTPUT или E16_MODE_INT_OUTPUT По фронту сигнала TRIG E16_SYNC_TRIG_F ALL 3 По спаду сигнала TRIG E16_SYNC_INT_RI SE 6 По фронту сигнала INT E16_SYNC_INT_FA LL 7 По спаду сигнала INT E16_SYNC_ADC_AB OVE_LEVEL 8 Аналоговая синхронизация ст арт а, толь- к о для E16 Выше уровня E16_SYNC_ADC_BE LOW_LEVEL 9 Ниж е уровня E16_SYNC_ADC_ED GE_RISE 10 По перех о ду сигнала снизу ввер х E16_SYNC_ADC_ED GE_FALL 11 По перех о ду сигнала свер ху вниз 4.1.14 Флаги, управляющие обработк ой принятых данных Тип: t_x502_proc_flags Описание: Флаги, управляющие обработк ой принятых данных Конст ант а Зна чение Описание X502_PROC_FLAGS_ VOLT 0x00000001 Признак, что нужно преобразовать зна чения АЦП в воль ты X502_PROC_FLAGS_ DONT_CHECK_CH 0x00010000 Признак, что не нужно провер ять совпадение номеров к аналов в при- нятых данных с к аналами из логи- ческ ой т аблицы. Мо ж ет использо- ватьс я при нест андартной прошивк е Blac kFin при переда че в ПК не всех данных. 63 +4.1.15 Флаги для обозна чения синхронных поток ов данных Тип: t_x502_streams Описание: Флаги для обозна чения синхронных поток ов данных Конст ант а Зна чение Описание X502_STREAM_ADC 0x01 Поток данных от АЦП X502_STREAM_DIN 0x02 Поток данных с цифровых вх о дов X502_STREAM_DAC 1 0x10 Поток данных первого к анала ЦАП X502_STREAM_DAC 2 0x20 Поток данных второго к анала ЦАП X502_STREAM_DOU T 0x40 Поток данных на цифровые выво ды X502_STREAM_ALL _IN X502_STREAM_AD C | X502_STREAM_DI N Объединение всех флагов, обозна чаю - щих потоки данных на вво д X502_STREAM_ALL _OUT X502_STREAM_DA C1 | X502_STREAM_DA C2 | X502_STREAM_DO UT Объединение всех флагов, обозна чаю - щих потоки данных на выво д 4.1.16 Конст анты, определяющие тип передаваемого отсчет а из ПК в мо ду ль Тип: t_x502_stream_out_wrd_type Описание: Конст анты, определяющие тип передавае мого отсчет а из ПК в мо ду ль Конст ант а Зна чение Описание X502_STREAM_OUT _WORD_TYPE_DOUT 0x0 Цифровой выво д X502_STREAM_OUT _WORD_TYPE_DAC1 0x40000000 Ко д для 1-г о к анала ЦАП X502_STREAM_OUT _WORD_TYPE_DAC2 0x80000000 Ко д для 2-г о к анала ЦАП 4.1.17 Р ежим работы мо ду ля Тип: t_x502_mode Описание: Р ежим работы мо ду ля Конст ант а Зна чение Описание X502_MODE_FPGA 0 Все потоки данных передаютс я через ПЛИС мину я сигнальный процессор Blac kFin X502_MODE_DSP 1 Все потоки данных пере д аютс я через сигнальный процессор, к оторый долж ен быть загруж ен прошив- к ой для обработки этих поток ов X502_MODE_DEBUG 2 От ладочный режим 4.1.18 Номера к аналов ЦАП Тип: t_x502_dac_ch Описание: Номер к аналов ЦАП для ук азания в X502_AsyncOutDac() Конст ант а Зна чение Описание X502_DAC_CH1 0 Первый к анал ЦАП X502_DAC_CH2 1 Второй к анал ЦАП 64 +4.1.19 Флаги, использу емые при выво де данн ы х на ЦАП Тип: t_x502_dacout_flags Описание: Флаги, к омбинацию к оторых мо жно передать в X502_AsyncOutDac() или X502_PrepareData() , чтобы определить действия, к оторые должны выполнить эти функции с переданным зна чением перед выво дом их на ЦАП Конст ант а Зна чение Описание X502_DAC_FLAGS_ VOLT 0x0001 Ук азывает , что зна чение задано в Воль т ах и при выво де е го нужно перевести его в к о ды ЦАП. Если флаг не ук азан, то счит аетс я, ч т о зна чение изна чально в к о дах X502_DAC_FLAGS_ CALIBR 0x0002 Ук азывает , что нужно применить к алибро- вочные к оэффициенты перед выво дом зна че- ния на ЦАП. 4.1.20 Номера к аналов для переда чи поток ов данных Тип: t_x502_stream_ch Описание: Номера к аналов для переда чи поток ов данных Конст ант а Зна чение Описание X502_STREAM_CH_ IN 0 Общий к анал на вво д X502_STREAM_CH_ OUT 1 Общий к анал на выво д X502_STREAM_CH_ CNT 4.1.21 Цифровые линии, на к оторых мо жно включить по дт яги- вающие резисторы Тип: t_x502_pullups Описание: Флаги, определяющие на к аких цифровых вх о дах должны быть включены по дт ягивающие резисторы. Для разных мо ду лей доступны разные наборы флагов. Конст ант а Зна чение Описание X502_PULLUPS_DI _H 0x01 Ст аршая половина цифровых вх о дов (тольк о для L502) X502_PULLUPS_DI _L 0x02 Младшая половина цифровых вх о дов (тольк о для L502) X502_PULLUPS_DI _SYN1 0x04 Линия SYN1 X502_PULLUPS_DI _SYN2 0x08 Линия SYN2 X502_PULLDOWN_C ONV_IN 0x10 По дт яжк а к 0 линии межмо ду льной синхронизации CONV_IN (тольк о для E502) X502_PULLDOWN_S TART_IN 0x20 По дт яжк а к 0 линии межмо ду льной синхронизации ST AR T_IN (тольк о для E502) 65 +E16_MODE_TRIG_O UTPUT 0x04 E16: Переключение TR I G на вых о д, ина че вх о д E16_MODE_INT_OU TPUT 0x08 E16: Переключение INT на вых о д, ина- че вх о д E16_MODE_TRIG_S TART_OUTPUT 0x10 E16: Сигнал ST AR T на вых о де TRIG, ина че CONV (TRIG долж ен быть вклю- чен на вых о д) E16_MODE_INT_ST ART_OUTPUT 0x20 E16: Сигнал ST AR T на вых о де INT, ина че CO N V (INT долж ен быть вклю- чен на вых о д) E16_MODE_RELAY_ ON 0x40 E16: Включить реле, во включенном со- сто янии на к онт акт ах разъема dig ital: +15В, -15В, во выключенном: +3В, GND, вторичное пит ание должно быть включенным E16_MODE_RELAY_ OFF 0x80 E16: Выключить реле E16_MODE_PWM_MA NUAL 0x100 E16: Ручное управление вторичным пи- т анием, по умолчанию вторичное пи- т ание включаетс я при первом обраще- нии к у стройств у из API и выключа- етс я если было закрыто соединение по Ethernet или отключ е ние USB к абеля E16_MODE_PWM_ON 0x200 E16: Вклю че н ие вторичного пит ания. Если включен флаг E16_MODE_PWM_MANUAL, то состо яние вторичного пит ания бу дет зависеть от состо яния этого флаг а, ина че работ а по умолчанию 4.1.22 Флаги, опреде ляющ и е наличие опций в мо д у ле и наличие необ х о димы х параметров Тип: t_x502_dev_flags Описание: Флаги, определяющие наличие опций в мо д у ле и наличие необ х о- димых параметров Конст ант а Зна чение Описание X502_DEVFLAGS_D AC_PRESENT 0x00000001 Признак наличия двухк анально- го к анального ЦАП X502_DEVFLAGS_G AL_PRESENT 0x00000002 Признак наличия г альванораз- вязки X502_DEVFLAGS_B F_PRESENT 0x00000004 Признак наличия сигнального процессора Blac kFin X502_DEVFLAGS_P ROC_TYPE 0x00000038 3 бит а, отвечающие за тип использумого процессо- ра/к онтроллера (0  ADSP- BF523) 66 +X502_DEVFLAGS_D AC_TYPE 0x000000C0 2 бит а, отвечающие з а тип использу емого ЦАП (0  AD5542AAR UZ, 1  D A C8581IPW) X502_DEVFLAGS_I FACE_SUPPORT_USB 0x00000100 Признак, что у стройство по ддер- живает интерфейс USB X502_DEVFLAGS_I FACE_SUPPORT_ETH 0x00000200 Признак, что у стройство по ддер- живает Ethernet X502_DEVFLAGS_I FACE_SUPPORT_PCI 0x00000400 Признак, что у стройство по д- дер живает интерфейс PCI/PCI- Express X502_DEVFLAGS_I NDUSTRIAL 0x00008000 Признак, что у стройство выпол- нено в инду стриалном исполне- нии X502_DEVFLAGS_F LASH_DATA_VALID 0x00010000 Признак, что во Flash-памя ти присутству ет информация о мо- ду ле X502_DEVFLAGS_F LASH_ADC_CALIBR_ VALID 0x00020000 Признак, что во Flash-памя ти присутствуют действительные к алибровочные к оэффициенты АЦП X502_DEVFLAGS_F LASH_DAC_CALIBR_ VALID 0x00040000 Признак, что во Flash-памя ти присутствуют действительные к алибровочные к оэффициенты ЦАП X502_DEVFLAGS_F LASH_AFC_CALIBR_ VALID 0x00080000 X502_DEVFLAGS_F PGA_LOADED 0x00800000 Признак, что присутс тву ет про- шивк а ПЛИ С и она у спешно бы- ла загруж ена X502_DEVFLAGS_D EVREC_OPENED 0x01000000 Признак, что у стройство уж е открыто (действителен тольк о внутри t_x502_devrec ) X502_DEVFLAGS_F PGA_AWAITING_GD32 0x02000000 Признак, что присутс тву ет про- шивк а ПЛИ С и она у спешно бы- ла загруж ена о жидаем GD32 для того чтобы ост альные ре гистры работ али X502_DEVFLAGS_G D_PRESENT 0x02000000 Признак, что присутству е т GD32 и это E502-P1 67 +4.1.23 Тип с о дер ж имого строки с располо ж ением у стройства Тип: t_x502_location_type Описание: Данное поле определяет со дер жимое поля l o cation в структуре t_x502_devrec Конст ант а Зна чение Описание X502_LOCATION_T YPE_NONE 0 В поле располо ж ения у стройства не со дер житс я информации X502_LOCATION_T YPE_ADDR 1 В поле располо ж ения у строй- ства со дер житс я строк а с адре- сом у стройства X502_LOCATION_T YPE_INSTANCE_NAME 2 В поле располо ж ения у стройства со дер житс я строк а с именем эк- земпляра 68 +4.1.24 Флаги для режима циклическ ого выво да Тип: t_x502_out_cycle_flags Описание: Данные флаги могут быть переданы в X502_OutCycleSetup() и X502_OutCycleStop() Конст ант а Зна чение Описание X502_OUT_CYCLE_ FLAGS_FORCE 0x01 Флаг ук азывает , что ост анов или смена сигнала могут произойти без о жидания к онца цикла предыдуще- го сигнала. Это позволяет выпол- нить переключение быстрее (о дна- к о все равно мо ж ет быть пост авле- но на переда чу до 256 К Семплов, к оторые должны бу дут быть пере- даны), но точк а см ены или ост ано- ва мо ж ет быть в любом месте пери- о да X502_OUT_CYCLE_ FLAGS_WAIT_DONE 0x02 Флаг ук азывает , что функция должна до ж д а тьс я полной загруз- ки сигнала и у ст ановки сигнала на выво д (для X502_OutCycleSetup() ) или завершения генерации циклическ ого с игнала (для X502_OutCycleStop() ). Без нег о функции тольк о посылают к о- манду мо ду лю, во звращая с разу управление. Данное о жидание мо ж ет занимать зна чительное время в зависимо- сти от размера сигнала (а т акж е размера предыдущего сигнала в случае смены или ост анова г ене- рации без X502_OUT_CYCLE_FLAGS_ FORCE ). Данну ю проверку мо жно с делать и от дельной функций X502_OutCycleCheckSetupDone() . Данный флаг имеет зна чения тольк о в тех случаях, к ог да по ддер живаетс я функция X502_ OutCycleCheckSetupDone() , в про- тивном случае он игнориру етс я. 69 +4.1.25 Дополнительные возмо жности мо ду ля Тип: t_x502_features Описание: Ко ды возмо жностей мо ду ля, к оторые могут по ддер живатьс я или нет в зависимости от типа мо ду ля, версий прошивок и т .п. Конст ант а Зна чение Описание X502_FEATURE_OU T_FREQ_DIV 1 По ддер жк а у ст ановки делителя ча- стоты выво да, от ли чног о от X502_ OUT_FREQ_DIV_DEFAULT X502_FEATURE_OU T_STATUS_FLAGS 2 Возмо жность чтения флагов со- сто яния выво да с помощью X502_ OutGetStatusFlags() 4.1.26 Флаги состо яния для синхронного выво да Тип: t_x502_out_status_flags Описание: Флаги состо яния для синхронного выво да Конст ант а Зна чение Описание X502_OUT_STATUS _FLAG_BUF_IS_EMPTY 0x01 Флаг ук аз ы ва ет , что в насто ящее время буфер в мо ду ле на переда- чу пу ст X502_OUT_STATUS _FLAG_BUF_WAS_ EMPTY 0x02 Флаг ук азывает , что было опу- стошение буфера на выво д с на- чала ст арт а синхронного вво да- выво да или с момент а последнего чтения ст ату с а с помощью X502_ OutGetStatusFlags() (в зависи- мости от того, что было послед- ним) 4.1.27 Параметры мо ду лей Тип: t_x502_params Описание: Параметры мо ду лей Конст ант а Зна чение Описание X502_PARAM_UNKN OWN 0 Неизвестный параме тр LTA37_WRITE_CTR L2_REG 1 запись к онтрольного регистра для тестов 70 +4.2 Типы данных 4.2.1 Запись о у стройстве Тип: t_x502_devrec Описание: Структура, описывающая у стройство, по к оторой с ни м мо жно у ст а- новить соединение Поле Тип Описание поля sign uint32_t Признак действительной струк- туры. Если запись действительна (соответству ет к ак ому-либо у строй- ству), то долж ен быть раве н X502_DEVREC_SIGN ) devname char [X5 02_DEVNAME_SIZE] Название у стройства serial char [X5 02_SERIAL_SIZE] Серийный номер location char [X5 02_LOCATION_STR_ SIZE] Описание по дключения (если есть) flags uint32_t Флаги из t_x502_dev_flags , описы- вающие у стройство iface uint8_t Интерфейс, по к оторому по дклю че - но у стройство location_type uint8_t Определяет , что именно со хранено в поле lo cation (о дно зна чение из t_x502_location_type ) res char [12 2] Р езерв internal t_x502_devrec_inptr * Непрозра чный ук азатель на с трук - туру с дополнительной информа- цией, необ х о димой для открытия у стройства 4.2.2 Калибровочные к оэффициенты диапазона. Тип: t_x502_cbr_coef Описание: Структура со дер ж и т к алибровочные зна чения смещения ну ля и к оэф- фициент а шк алы для о дного диапазона АЦП или ЦАП.Р езу ль тирующее зна чение АЦП вычисляетс я к ак (v al - os) * k, г де v al - неотк алиброванное зна чение Поле Тип Описание поля offs double смещение ну ля k double к оэффициент шк алы 71 +4.2.3 Коэффициенты для к алибровки ф ильра к оррекции А ЧХ Тип: t_x502_afc_coef Описание: Структура описыва ет к оэффициенты и параметры, использу емые для к оррекции А ЧХ ЦАП Поле Тип Описание поля Fd double Частот а генерации ЦАП, на к оторой из- мерено отноше ни е амплиту д. SigFreq double Частот а сигнала, для к оторой измерено отношение амплиту д. K double [X502_DAC_CH_CNT _MAX] Набор отношений реально вы- ст авленной амплиту ды сину- соидального сигнала частоты @eldrefTL TR35_AF C_COEF,SigF req к задаваемой амплиту де при частоте гене- рации @eldrefTL TR35_AF C_COEF,F d для к аждого к анала ЦАП. 4.2.4 Калибровочные к оэффициенты мо ду ля Тип: t_x502_cbr Описание: Структура, со дер ж а щая в се к алибровочные к оэффициенты, к оторые используютс я мо ду лем L-502/E-502 Поле Тип Описание поля adc t_x502_cbr_coef [X502_ADC_RANGE_ CNT] Калибровочные к оэффициенты АЦП dac t_x502_cbr_coef [X502_DAC_CH_CNT _MAX] Калибровочные к оэффициенты ЦАП afc_coef t_x502_afc_coef Калибровочные к оэффициенты филь тра к оррекции А ЧХ для ЦАП L T A37 4.2.5 Информация о мо ду ле L-502/E-502. Тип: t_x502_info Описание: Структура, со дер ж ащая посто янную ин формация о мо ду ле L-502/E- 502, к оторая к ак правило не изменяетс я после открытия Вн имание ! Бинарная сов- местимось между версиями библиотек н е г арантиру етс я! Использу ете тольк о те версии библиотек с к оторыми была ск омпилирован программа! Поле Тип Описание поля name char [X502_DEVNAME_S IZE] Название у стройства (L502 и ли E502 или E16) serial char [X5 02_SERIAL_SIZE] Серийный номер devflags uint32_t Флаги из t_x502_dev_flags , описы- вающие наличие в мо ду ле опреде - ленных опций 72 +fpga_ver uint16_t Версия ПЛИС (ст арший байт - ма- ж орная, младший - минорная) plda_ver uint8_t Версия ПЛИС, управляющего ана- логовой частью board_rev uint8_t Р евизия платы mcu_firmware_ver uint32_t Версия прошивки к онтроллера Cortex-M4. Действительна тольк о для мо ду ля E-502 flash_size uint32_t Р азмер внешней ash-памяти в бай- т ах factory_mac uint8_t [X502_MAC_ADDR_ SIZE] Заво дск ой MA C-адрес  действи- телен тольк о для у с тройств с Ethernet-интерфейсом cbr t_x502_cbr Заво дские к алибровочные к оэффи- циенты (из Flash-памяти) 4.2.6 Описатель к онфигурации сетевого ин т е рфейса Тип: t_e502_eth_config_hnd Описание: Непрозра чный ук азатель на структуру , со дер ж ащ ую параметры к он- фигурации сетевого интерфейса мо ду ля E-502. Пользовательск ой программе не до- ступны поля структуры напр ямую, а тольк о через функции библиотеки. Описатель к онфигурации создаетс я с помощ ью E502_EthConfigCreate() и в к онце раб оты освобо ждаетс я с помощью E502_EthConfigFree() . Как правило все настройки не должны заполнятьс я пользователем вручную, обычно с п е рва они считываютс я из у стройства с помощью E502_EthConfigRead() , после чего часть настроек мо жно изменить и со храни ть в мо ду ль через E502_EthConfigWrite() 4.2.7 Описатель к онтек ст а поиск а у стройств в сети Тип: t_e502_eth_svc_browse_hnd Описание: Ук азатель на непрозра чную структуру с информацией о состо янии текущего сеанса поиск а у стройств в сети. Создаетс я при на чале поиск а вызовом E502_EthSvcBrowseStart() и уничто ж ае тс я с помощью E502_EthSvcBrowseStop() 4.2.8 Описатель сетевого сервиса Тип: t_e502_eth_svc_record_hnd Описание: Ук азатель на непрозра чную структуру с информацией о сервисе в сети, соответствующем о дному мо ду лю E-502. Использу етс я при автоматиче- ск ом обнаруж ении у стройств в лок альной сети. Создаетс я при вызове E502_ EthSvcBrowseGetEvent() и уничто ж аетс я с помощью E502_EthSvcRecordFree() 73 +4.2.9 Внутренняя информация записи о у стройстве Тип: t_x502_devrec_inptr Описание: Непрозра чная структура с информацией, дос т аточной для у ст а- новления с ним с вязи. Зависит от типа у с трой с тва, интерфейса по дключе- ния и не доступна пользователю напр ямую, а ис п ольз у етс я библиотек ой в X502_OpenByDevRecord() 4.2.10 Описатель мо ду ля Тип: t_x502_hnd Описание: Непрозра чный ук азатель на структуру , с о дер ж ащую инф ормацию о настройк ах мо ду ля и текущем соединении с ним. Пользовательск ой программе не доступны поля структуры н а п р ямую, а тольк о через функции библиотеки. Функ- ции управления мо ду лем принимают описатель мо ду ля своим первым параметром. Описатель мо ду ля создаетс я с помощью X502_Create() и в к онце работы освобо ж- даетс я с помощью X502_Free() . 4.2.11 Список сер ийный номеров Тип: t_x502_serial_list Описание: Тип определяет массив се р ийных номе ров для к о л ичес тва мо ду лей, определяемого н а эт апе работы программы. 4.3 Функции 4.3.1 Функции для создания и освобо ждения описателя мо ду ля 4.3.1.1 Создание оп исателя мо ду ля Формат: t_x502_hnd X 502_Create (void) Описание: Создание описателя мо ду ля, для последующей работы с мо ду лем E-502 или L-502. В случае у спешного выделения памяти инициализиру ет поля опи с ателя зна чениями по умолчанию. Возвращаемое зна чени е : NULL в случае ошибки, ина че - описатель мо ду ля 74 +4.3.1.2 Освобо ждение оп исателя мо ду ля Формат: int32_t X502 _Free (t_x502_hnd hnd) Описание: Освобо ждение памяти, выделенной по д описатель мо ду ля с помощью X502_Create() . По сле этого описатель уж е использовать нельз я, независимо от возвращенного з на чения! Параметры: hnd  Описатель у стройства Возвращаемое зна чени е : Ко д ошибки 4.3.2 Функции для открытия и получения информации о мо ду ле 4.3.2.1 Г лобавльные переменные Переменная Тип Описание info t_x502_info * 4.3.2.2 Получение спи ск а серийных номеров мо ду лей L-502. Формат: int32_t L502 _GetSerialList (char serials[] [X502_SERIAL_SIZE], uint32_t size, uint32_t flags, uint32_t *devcnt) Описание: Функция возвращ ает список номе ров всех найденных мо ду лей L-502, независимо от того, открыты они сейчас или нет . Если нуж ен список тольк о тех мо ду лей, к оторые не открыты (то е сть тольк о тех, с к оторыми мо жно у ст ановить соединение), то для это го мо жно передать в функцию флаг X502_GETDEVS_FLAGS_ONLY_NOT_OPENED . Параметры: serials  Массив размером size * X502_SERIAL_SIZE байт , в к оторый бу дут со хране- ны серийные номера найденных мо ду лей. Мо ж ет быть NULL, если siz e=0, а dev cn t!=NULL, в случае, если нужно тольк о получить к оличество мо ду лей в системе. size  О преде л я ет , ск ольк о мак симально серийных номеров мо ж ет быть со хранено в мас сив serial. Бу дут со хранены тольк о первые size серийных номеров. Мо ж ет быть 0, если serials=NULL ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. dev cn t  Если dev cn t!=NULL, то в данную переменную со храняетс я общее число найденных мо ду лей L502 (мо ж ет быть больше size). Возвращаемое зна чени е : Если <0 - к о д ошибки, ина че к оличество со храненных серийных номеров в массиве serials (всег да <= size) 75 +4.3.2.3 Открытие м о ду ля L-502 по его се р ийному номеру Формат: int32_t L502 _Open (t_x502_hnd hnd, const char *serial) Описание: Функция у ст анавливает связь с мо ду лем L-502 по его серийному номеру . По- сле у спешного выполнения этой функции, пользователь получает эк склюзив- ный доступ к мо ду лю через описате л ь мо ду ля. До закрытия связи с помощью X502_Close() никто другой у ст ановить связь с мо ду лем не смо ж е т (бу дет возвра- щена ошибк а X502_ERR_DEVICE_ACCESS_DENIED ). Если в к а честве серийного номера передан NULL или пу ст ая строк а, то бу дет у ст ановлена связь с первым найд е нны м мо ду лем, с к оторым получитс я у спешно ее у ст ановить. Если в системе нет ни о дного мо ду ля, то бу дет возвращена ошибк а X502_ERR_DEVICE_NOT_FOUND . Если в системе присутствуют мо ду ли L-502, но со- единение ни с о дним из них у ст ановить не у далось, то бу дет во звращена ошибк а, полученная при попытк е у ст ановить сое д инение с последним найденным м о ду лем. После з авершения работы с у стройством соединение должно быть закрыто с по- мощью X502_Close() . Параметры: hnd  Описатель у стройства. serial  Ук азатель на строку с серийным номером открываемого мо ду ля или NULL. Возвращаемое зна чени е : Ко д ошибки. 4.3.2.4 Получение списк а серийных номеров мо ду лей E-502, по дключенных по USB. Формат: int32_t E502 _UsbGetSerialList (char serials[] [X502_SERIAL_SIZE], uint32_t size, uint32_t flags, uint32_t *devcnt) Описание: Функция возвращает список номеров всех найденных мо ду лей E-502, независимо от того, открыты они сейчас или нет . Функция на данный момент не по ддер живает флаг X502_GETDEVS_FLAGS_ONLY_ NOT_OPENED . Параметры: serials  Массив размером size * X502_SERIAL_SIZE байт , в к оторый бу дут со хране- ны серийные номера найденных мо ду лей. Мо ж ет быть NULL, если siz e=0, а dev cn t!=NULL, в случае, если нужно тольк о получить к оличество мо ду лей в системе. size  О преде л я ет , ск ольк о мак симально серийных номеров мо ж ет быть со хранено в мас сив serial. Бу дут со хранены тольк о первые size серийных номеров. Мо ж ет быть 0, если serials=NULL ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. dev cn t  Если dev cn t!=NULL, то в данную переменную со храняетс я общее число найденных мо ду лей E502 (мо ж ет быть больше size). Возвращаемое зна чени е : Если <0 - к о д ошибки, ина че к оличество со храненных серийных номеров в массиве serials (всег да <= size) 76 +4.3.2.5 Р абот ает ан алогично E502_UsbGetSerialList, тольк о д ля мо ду лей E16. Формат: int32_t E16_ UsbGetSerialList (char serials[] [X502_SERIAL_SIZE], uint32_t size, uint32_t flags, uint32_t *devcnt) Описание: 4.3.2.6 Открытие мо ду ля E-502, по дключенного по USB, по его серийному номеру Формат: int32_t E502 _OpenUsb (t_x502_hnd hnd, const char *serial) Описание: Функция у ст анавливает связь с мо ду лем E-502, по дключенным по интерфейсу USB, по его серийному номеру . После у спешног о выполнения этой функции, пользовате ль получает эк склюзив- ный доступ к мо ду лю через описате л ь мо ду ля. До закрытия связи с помощью X502_Close() никто другой у ст ановить связь с мо ду лем не смо ж е т (бу дет возвра- щена ошибк а X502_ERR_DEVICE_ACCESS_DENIED ). Если в к а честве серийного номера передан NULL или пу ст ая строк а, то бу дет у ст ановлена связь с первым найд е нны м мо ду лем, с к оторым получитс я у спешно ее у ст ановить. Если в системе нет ни о дного мо ду ля, то бу дет возвращена ошибк а X502_ERR_DEVICE_NOT_FOUND . Если в систе ме присутствуют мо ду ли E-502, но с о- единение ни с о дним из них у ст ановить не у далось, то бу дет во звращена ошибк а, полученная при попытк е у ст ановить сое д инение с последним найденным м о ду лем. После з авершения работы с у стройством соединение должно быть закрыто с по- мощью X502_Close() . Параметры: hnd  Описатель у стройства. serial  Ук азатель на строку с серийным номером открываемого мо ду ля или NULL. Возвращаемое зна чени е : Ко д ошибки. 4.3.2.7 Р абот ает аналогично E502_Op enUsb, тольк о для мо ду лей E16 . Формат: int32_t E16_ OpenUsb (t_x502_hnd hnd, const char *serial) Описание: 77 +4.3.2.8 Открытие м о ду ля E-502 по IP-ад ресу Формат: int32_t E502 _OpenByIpAddr (t_x502_hnd hnd, uint32_t ip_addr, uint32_t flags, uint32_t tout) Описание: Функция у ст анавливает связь с мо ду лем E-502, по дключенным по интерфейсу Ethernet, для к оторого у ст ановле н ук азанный адрес IPv4. После з авершения работы с у стройством соединение должно быть закрыто с по- мощью X502_Close() . Параметры: hnd  Описатель у стройства. ip_addr  IPv4 адрес мо ду ля в виде 32-битного слова. Для адреса a .b.c.d ip_addr = (a << 24)|(b << 16)|(c << 8)|d. ags  Флаги, управляющие работой функции. Р ез ерв, должны быть всег да 0. tout  Время на у ст ановления по дключения в мс. Если по дключение не у д а стс я завершить за заданное время, то функция вернет ошибку . Возвращаемое зна чени е : Ко д ошибки. 4.3.2.9 Открытие м о ду ля E-16 по IP-а дресу Формат: int32_t E16_ OpenByIpAddr (t_x502_hnd hnd, uint32_t ip_addr, uint32_t flags, uint32_t tout) Описание: Функция у ст анавливает связь с мо ду лем E-16, по дключенным по инте р фейс у Ethernet, для к оторого у ст ановле н ук азанный адрес IPv4. После з авершения работы с у стройством соединение должно быть закрыто с по- мощью X502_Close() . Параметры: hnd  Описатель у стройства. ip_addr  IPv4 адрес мо ду ля в виде 32-битного слова. Для адреса a .b.c.d ip_addr = (a << 24)|(b << 16)|(c << 8)|d. ags  Флаги, управляющие работой функции. Р ез ерв, должны быть всег да 0. tout  Время на у ст ановления по дключения в мс. Если по дключение не у д а стс я завершить за заданное время, то функция вернет ошибку . Возвращаемое зна чени е : Ко д ошибки. 78 +4.3.2.10 Закрытие сое д инения с мо ду лем Формат: int32_t X502 _Close (t_x502_hnd hnd) Описание: Функция разрывает соединение с мо ду лем E-502/L-502, если оно было ранее у ст а- новлено (в противном случае ничего не делает). Описатель мо ду ля не освобо ждает- с я. Память по д описатель мо ду ля должна быть ос вобо ждена вызовом X502_Free() . Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.2.11 Проверк а, открыто ли соединение с мо ду лем Формат: int32_t X502 _IsOpened (t_x502_hnd hnd) Описание: Функция провер яет , открыто ли в данный момент соединение с мо ду лем. Если соединение открыто, то функция возвращает X502_ERR_OK . Если ж е закрыто, то функция возвращает ошибку X502_ERR_DEVICE_NOT_OPENED . Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.2.12 Получение информа ции о мо ду л е Формат: __attribute__ ((__deprecated__)) int32_t X502_GetDevInfo(t_x502_hnd hnd Описание: Получение информации о мо ду ле L-502/E-502, с к оторым у ст ановлена связь. Вни- мание! При использовании этой функции (к ак и любой другой из этого api) важно убедитьс я что при сборк е исполняем ого файла, использу етс я заг оловочный файл той ж е ве р с ии что и бинарный ф айл самой библиотеки ( x502api.h == x502api. dll)! Параметры: hnd  Описатель мо ду ля. info  Информация о мо ду ле (смотри описание типа t_x502_info ). Возвращаемое зна чени е : Ко д ошибки. 79 +4.3.2.13 Получение информа ции о мо ду л е Формат: int32_t X502 _GetDevInfo2 (t_x502_hnd hnd, t_x502_info *info, uint32_t size) Описание: Получение информации о мо ду ле L-502/E-502, с к оторым у ст ановлена связь. Вни- мание! При использовании этой функции (к ак и любой другой из этого api) важно убедитьс я что при сборк е исполняем ого файла, использу етс я заг оловочный файл той ж е ве р с ии что и бинарный ф айл самой библиотеки ( x502api.h == x502api. dll)! Параметры: hnd  Описатель мо ду ля. info  Информация о мо ду ле (смотри описание типа t_x502_info ). size  Р азмер sizeof(t_x502_info). Возвращаемое зна чени е : Ко д ошибки. 4.3.3 Функции для работы с запис ями об у стройстве 4.3.3.1 Получить список запи се й , соответствующих по дключенным мо ду- лям L502. Формат: int32_t L502 _GetDevRecordsList (t_x502_devrec *list, uint32_t size, uin t32_t flags, uint32_t *devcnt) Описание: Функция нах о дит все по дк люченные мо ду ли L-502 и инициализиру ет записи о к аждом найденном у стройстве и со храняет их в переданный список (если не ну ле- вой). Возвращенные в списк е запис и должны быть очищены после использования с помощью X502_FreeDevRecordList() (т акж е в случае повторного вызов L502_ GetDevRecordsList() с тем ж е массивом записей, записи, полученные п ри преды- дущем вызове, должны быть спе р в а очищены). Параметры: list  Массив для с о хранения з аписей о найденных у стройствах. Долж ен со дер- ж ать место для со хранения не менее size записей. Мо ж ет быть NULL, если size=0, а d e v cn t!=NULL, в случае, ес ли нужно тольк о получить к оличество мо ду лей в системе. size  Определяет , ск ольк о мак симально записей мо ж ет быть со хранено в м ассив list. Бу дут со хранены тольк о первые size записей, если у стройств найденно больше. ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. dev cn t  Если не ну левой ук азатель, то в данную переменную со храняетс я общее число найденных мо ду лей L-502 (мо ж ет быть больше siz e). Возвращаемое зна чени е : Если <0  к о д ошибки, ина че к оличество со храненных записей о найденных у строй- ствах (всег да <= siz e). Именно на этот размер нужно с делать в дальнейшем X502_ FreeDevRecordList() для освобо ждения памяти, выделенной по д информацию, на к оторую ссылаетс я запись. 80 +4.3.3.2 Получить список запи се й , соответствующих по дключенным мо ду- лям E502. Формат: int32_t E502 _UsbGetDevRecordsList (t_x502_devrec *list, uint32_t size, uint32_t flags, uint32_t *devcnt) Описание: Функция нах о дит все по дключенные по интерфейсу USB мо ду ли E-502 и иници- ализиру ет записи о к аждом найденном у стройстве и со храняет их в переданный список (если не ну левой). Возвращенные в списк е записи должны быть очищены после использования с помощью X502_FreeDevRecordList() (т акж е в случае по- вторного вызов E502_UsbGetDevRecordsList() с тем ж е мас сивом записе й , записи, полученные при предыд ущ ем вызове, должны быть сперва очищены). Параметры: list  Массив для с о хранения з аписей о найденных у стройствах. Долж ен со дер- ж ать место для со хранения не менее size записей. Мо ж ет быть NULL, если size=0, а d e v cn t!=NULL, в случае, ес ли нужно тольк о получить к оличество мо ду лей в системе. size  Определяет , ск ольк о мак симально записей мо ж ет быть со хранено в м ассив list. Бу дут со хранены тольк о первые size записей, ес ли у стройств найдено больше. ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. dev cn t  Если не ну левой ук азатель, то в данную переменную со храняетс я общее число найденных мо ду лей E-502, по дключенных по ин те рф е йсу USB (мо ж ет быть больше size). Возвращаемое зна чени е : Если <0  к о д ошибки, ина че к оличество со храненных записей о найденных у строй- ствах (всег да <= siz e). Именно на этот размер нужно с делать в дальнейшем X502_ FreeDevRecordList() для освобо ждения памяти, выделенной по д информацию, на к оторую ссылаетс я запись. 4.3.3.3 Аналогично E5 02_UsbGetDevRecordsList, получит ь список записей, соответствующих по дклю ченным мо ду лям E16. Формат: int32_t E16_ UsbGetDevRecordsList (t_x502_devrec *list, uint32_t size, uin t32_t flags, uint32_t *devcnt) Описание: 4.3.3.4 Аналогично E5 02_UsbGetDevRecordsList, получит ь список записей, соответствующих по дклю ченным мо ду лям E14-440. Формат: int32_t E440 _UsbGetDevRecordsList (t_x502_devrec *list, uint32_t size, uint32_t flags, uint32_t *devcnt) Описание: 81 +4.3.3.5 Получить список запи се й , соответствующих по дключенным мо ду- лям E502. Формат: int32_t E502 _UsbGetDevRecordsList2 (t_x502_devrec *list, uint32_t size, uint32_t flags, uint32_t *devcnt, uint16_t idVendor, uint16_t idProduct) Описание: Делает то ж е самое что и E502_UsbGetDevRecordsList, от личие в том что мо жно ук азать idV endor и idPro duct USB у стройства. Параметры: idV endor  idV endor idPro duct  idPro d uc t Возвращаемое зна чени е : Если <0  к о д ошибки, ина че к оличество со храненных записей о найденных у строй- ствах (всег да <= siz e). Именно на этот размер нужно с делать в дальнейшем X502_ FreeDevRecordList() для освобо ждения памяти, выделенной по д информацию, на к оторую ссылаетс я запись. 4.3.3.6 Создание з аписи о у стройстве с ук азанным IP-адресом Формат: int32_t E502 _MakeDevRecordByIpAddr (t_x502_devrec *devrec, uint32_t ip_addr, uint32_t flags, uint32_t tout) Описание: Данная функция инициализиру ет запись о у стройстве, по дключенном по интер- фейсу Ethernet, с ук азанным IPv4 адресом. Данная функция тольк о создает запись, но не провер яет наличие соответствующего у стройства. По дключение к мо ду лю вы- полняетс я аналогично другим запис ям через X502_OpenByDevRecord() . Параметры: devrec  Ук азатель на запись у стройства, к оторая должна быть создана и запол- нена нужными параметрами. ip_addr  IPv4 адрес мо ду ля в виде 32-битного слова (аналогично параметру ip_addr функции E502_OpenByIpAddr() ). ags  Флаги. Р езерв, должны быть всег да 0. tout  Время для у ст ановления по дключения в мс. Данное время со храняетс я в записи и использу етс я при последующем вызове X502_OpenByDevRecord() . Если по дключение не у дастс я завершить за это время, то функция X502_OpenByDevRecord() вернет ошибку . Возвращаемое зна чени е : Ко д ошибки 82 +4.3.3.7 Создание з аписи о у стройстве с ук азанным IP-адресом Формат: int32_t E502 _MakeDevRecordByIpAddr2 (t_x502_devrec *devrec, uint32_t ip_addr, uint32_t flags, uint32_t tout, char const *devname) Описание: Р абот ает аналогично функции E502_Mak eDevRecordByIpA ddr. Для по ддер жки E16 добавлен параметр *devname. Параметры: devrec  Ук азатель на запись у стройства, к оторая должна быть создана и запол- нена нужными параметрами. ip_addr  IPv4 адрес мо ду ля в виде 32-битного слова (аналогично параметру ip_addr функции E502_OpenByIpAddr() ). ags  Флаги. Р езерв, должны быть всег да 0. tout  Время для у ст ановления по дключения в мс. Данное время со храняетс я в записи и использу етс я при последующем вызове X502_OpenByDevRecord() . Если по дключение не у дастс я завершить за это время, то функция X502_OpenByDevRecord() вернет ошибку . devname  Имя у стройства E16 или E502. Возвращаемое зна чени е : Ко д ошибки 4.3.3.8 У ст ановк а TCP-порт а управляющего соединения д ля записи о у стройстве Формат: int32_t E502 _EthDevRecordSetCmdPort (t_x502_devrec *devrec, uint16_t cmd_port) Описание: Данная функция позволяет изменить TCP-порт управляющего соединения мо- ду ля E-502. Это мо ж ет быть необ х о димо, если мо ду ль E-502 и х ост , с к оторого необ х о димо у ст ановить соединение, нах о дятс я в разных сет ях и адрес мо ду ля E- 502 не доступен из сети х ост а. В этом случае требу етс я настройк а проброса портов на маршрутизаторе и при наличие более о дного т ак ого мо ду ля E-502, т .к все соеди- нения ид ут с маршрутизитором, то различить эти мо ду ли мо жно тольк о по TCP- порту , если настроить разные порты при пробросе. В этом случае помимо п о р т а управляющего соединения, необ х о димо изм енить и порт соединения для п е реда чи данных, вызвав E502_EthDevRecordSetDataPort() . Данная функция должна быть вызвана для записи, созданной до этого с по- мощью E502_MakeDevRecordByIpAddr() и до открытия соединения с помощью X502_OpenByDevRecord() . Параметры: devrec  Ук азатель на запись у стройства, в к оторой нужно изменить упр ав л я ю- щий TCP-порт . cmd_p ort  Новое зна чение TCP-порт а для управляющего соединения Возвращаемое зна чени е : Ко д ошибки 83 +4.3.3.9 У ст ановк а TC P-порт а соединения переда чи данных для записи о у стройстве Формат: int32_t E502 _EthDevRecordSetDataPort (t_x502_devrec *devrec, uint16_t data_port) Описание: Функция аналогична E502_EthDevRecordSetCmdPort() , но изменяет TCP-порт для соединения, по к оторому идет обмен данных поток ов вво да-выво да. Параметры: devrec  Ук азатель на запись у стройства, в к оторой нужно изменить упр ав л я ю- щий TCP-порт . data_p ort  Новое зна чение TCP-порт а для соединения переда чи данных Возвращаемое зна чени е : Ко д ошибки 4.3.3.10 Создание за писи о у стройстве по описат е л ю сетевого сервиса Формат: int32_t E502 _MakeDevRecordByEthSvc (t_x502_devrec *devrec, t_e502_eth_svc_record_hnd svc, uint32_t flags, uint32_t tout) Описание: Данная функция инициализиру ет запись о у стройстве, по дключенном по интер- фейсу Ethernet, соответствующему сетевому сервису , на к оторый ук азывает пере- данный описатель сетевого с ервиса. Этот описатель мо ж ет быть получен с помо- щью функций поиск а сетевых сервисов, соответствующих мо ду лям E-502, в лок аль- ной сети. Данная функция тольк о создает запись, но не провер яет наличие соот- ветствующего у стройства. По дк лючение к мо ду лю выполняетс я аналогично другим запис ям через X502_OpenByDevRecord() . Вс я необ х о димая информация из описа- теля сетевого се рвиса со хр а н я етс я в записи о у стройстве, т .е. после вызова данной фунции при ж елании описатель сетевого сервиса мо жно сразу освобо ждать с по- мощью E502_EthSvcRecordFree() . Параметры: devrec  Ук азатель на запись у стройства, к оторая должна быть создана и запол- нена нужными параметрами. sv c  Описатель сетевого сервиса, полученный с помощью E502_ EthSvcBrowseGetEvent() . ags  Флаги. Р езерв, должны быть всег да 0. tout  Время для у ст ановления по дключения в мс. Данное время со храняетс я в записи и использу етс я при последующем вызове X502_OpenByDevRecord() . Если по дключение не у дастс я завершить за это время, то функция X502_OpenByDevRecord() вернет ошибку . Возвращаемое зна чени е : Ко д ошибки 84 +4.3.3.11 Открыть соеди нение с мо ду лем по записи о у стройстве Формат: int32_t X502 _OpenByDevRecord (t_x502_hnd hnd, const t_x502_devrec *devrec) Описание: Функция у ст анавливает соединение с мо ду лем E-502 или L-502 по записи об этом у стройстве. Необ х о димые действия завис ят от того, н а к ак ое у стройство по дклю- ченное по к ак ому интерфейсу ссылаетс я запись. Сами з апи с и создаютс я с пециаль- ными функциями (свои для к аждого типа мо ду ля и интерфейса по дключения) и не должны изменятьс я пользователем вручную. Параметры: hnd  Описатель мо ду ля. devrec  Запись о у стройстве, со дер ж ащая нео б х о димую информацию для у ст а- новления с ним связи Возвращаемое зна чени е : Ко д ошибки. 4.3.3.12 Освобо ждение за писей об у стройствах Формат: int32_t X502 _FreeDevRecordList (t_x502_devrec *list, uint32_t size) Описание: Функция очища ет ресурсы, выделенные при инициализации записи о у стройстве по д информацию, необ х о димую для открытия у стройства. Данная функция долж- на вызыватьс я после инициализации записи о у стройстве о дн о й из соответствую- щих функций после того, к ог да запись уж е не нужна. После у ст ановки свя зи с у стройством через X502_OpenByDevRecord() запись не использу етс я в дальнейшем и ее мо жно при ж елании сразу освобо дить, не закрывая соединения с у стройством. Функция мо ж ет очистить сразу неск ольк о записей из м ассива (если очищаетс я о д- на, то в к а честве размера допу стимо ук азывать 1). Параметры: list  Массив з аписей о у стройстве или ук азатель на единственную запись, ресурсы к оторой (к оторых) нужно ос вобо дить. size  Количество записей в ма ссиве Возвращаемое зна чени е : Ко д ошибки. 85 +4.3.4 Функции для изменения настроек мо ду ля 4.3.4.1 Переда ча у ст ановленных н астроек в мо ду л ь Формат: int32_t X502 _Configure (t_x502_hnd hnd, uint32_t flags) Описание: Функция выполняет запись текущих настроек (к оторые были у ст ановлены с по- мощью функций X502_SetXXX) в мо ду ль. Должна вызыватьс я перед запу ск ом поток а данных. Параметры: hnd  Описатель мо ду ля. ags  Флаги (резерв - должно быть равно 0). Возвращаемое зна чени е : Ко д ошибки. 4.3.4.2 У ст ановк а параметров логическ ого к анала Формат: int32_t X502 _SetLChannel (t_x502_hnd hnd, uint32_t lch, uint32_t phy_ch, uint32_t mode, uint32_t range, uint32_t avg) Описание: Функция у ст анавливает параметры заданного логическ ого к анала в логическ ой т аблице АЦП. Параметры: hnd  Описатель мо ду ля. lc h  Номер логическ ого к анала. (от 0 до X502_LTABLE_MAX_CH_CNT -1 или до E16_ LTABLE_MAX_CH_CNT -1 для E16) ph y_c h  Номер физическ ого к анала АЦП, на чиная с 0 (0-15 для дифференци- ального режима, 0-31 для режима с общей землей) mo de  Р ежим измерения к анал АЦП (зна чение типа t_x502_lch_mode ) range  Диапазон измерения к анала (зна чение типа t_x502_adc_range ) a vg  Коэффициент у средне н ия по к аналу (не реализовано в E16). Ну левое зна че- ние соот ветству ет зна чению к оэффициент а, определенного библиотек ой. Для явного задания к оэффициент а у среднения нужно перед зна чение от 1 (отсут - ствие у среднения) до X502_LCH_AVG_SIZE_MAX . В случае если зна чение у сред- нения превышает делитель частоты, то это зна чение бу дет ск орректировано Возвращаемое зна чени е : Ко д ошибки. 4.3.4.3 Получение массива диапазонов мо ду ля E16. Формат: double const * E16_GetAdcR anges (uint32_t *ranges_len) Описание: Возвращаем ук азатель на массив: double ranges[] = 10, 2.5, 0.625, 0.15625; Параметры: ranges_len  Ук азатель ку да з аписывает размер возвращаем ого массива Возвращаемое зна чени е : Ук азатель на массив double размером ranges_len или NULL в случае ошибки. 86 +4.3.4.4 Получение массива диапазонов мо ду ля E502. Формат: double const * E502_GetAdc Ranges (uint32_t *ranges_len) Описание: Возвращаем ук азатель на массив: double ranges[] = 10. , 5., 2., 1., 0.5, 0 .2; Параметры: ranges_len  Ук азатель ку да з аписывает размер возвращаем ого массива Возвращаемое зна чени е : Ук азатель на массив double размером ranges_len или NULL в случае ошибки. 4.3.4.5 Получение массива диапазонов мо ду ля Формат: double const * X502_GetAdc Ranges (t_x502_hnd hnd, uint32_t *ranges_len) Описание: Для мо ду ля E16: double ranges[] = 10, 2.5, 0.62 5, 0.15625; Для мо ду ля E502: double ranges[] = 10., 5., 2. , 1., 0.5, 0.2; Параметры: hnd  Описатель мо ду ля. ranges_len  Ук азатель ку да з аписывает размер возвращаем ого массива Возвращаемое зна чени е : Ук азатель на массив double размером ranges_len или NULL в случае ошибки. 4.3.4.6 У ст ановк а к оличества логических к аналов Формат: int32_t X502 _SetLChannelCount (t_x502_hnd hnd, uint32_t lch_cnt) Описание: Функция у ст анавливает к оли че ство логических к аналов в лог ич е ск ой т аблице АЦП. Параметры: hnd  Описатель мо ду ля lc h_cn t  Количество логических к аналов (от 1 до X502_LTABLE_MAX_CH_CNT или до E16_LTABLE_MAX_CH_CNT для E16) Возвращаемое зна чени е : Ко д ошибки 87 +4.3.4.7 Получение к оличества логических к ан алов Формат: int32_t X502 _GetLChannelCount (t_x502_hnd hnd, uint32_t *lch_cnt) Описание: Функция возвращает у ст ановленное ранее с помощью X502_SetLChannelCount() к оличество логических к аналов в управляющей т аблице АЦП. Параметры: hnd  Описатель мо ду ля lc h_cn t  Количество логических к аналов Возвращаемое зна чени е : Ко д ошибки 4.3.4.8 У ст ановк а делителя частоты сбора для АЦП Формат: int32_t X502 _SetAdcFreqDivider (t_x502_hnd hnd, uint32_t adc_freq_div) Описание: Частот а сбора АЦП получаетс я к ак резу ль т ат деления опорной час тоты синхро- низации (к ак в случае внешней, т ак и внутренней) на делитель, у ст анавливаемый этой функцией. Аль тернативой этой функции служит X502_SetAdcFreq() , к оторая рассчитывае т этот делитель на основании переданной требу емой частоты сбора АЦП. Параметры: hnd  Описатель мо ду ля. adc_freq_div  Делитель частоты АЦП (от 1 до X502_ADC_FREQ_DIV_MAX ). Возвращаемое зна чени е : Ко д ошибки. 4.3.4.9 У ст ановк а зна чения межк адровой задер жки для АЦП Формат: int32_t X502 _SetAdcInterframeDelay (t_x502_hnd hnd, uint32_t delay) Описание: Функция у с т анавливает межк адровую задер жку для АЦП, то ест ь к оличество перио дов опорной частоты синхронизации, к оторое бу дет пропущено после п рове - дения изме р е ния последнего к анала логическ ой т аблицы до пр о ведения измерения, соответствующего первому логическ ому к аналу следующего к адра. Аль тернативой мо ж ет являтьс я функция X502_SetAdcFreq() , к оторая р ас считы- вает зна чение межк адровой задер жки по заданным параметрам частоты сбора и частоты следования к адров (частоты сбора на логический к анал). Параметры: hnd  Описатель мо ду ля. dela y  Зна чение межк адр о вой задер жки (от 0 до X502_ADC_INTERFRAME_DELAY_ MAX ) Возвращаемое зна чени е : Ко д ошибки. 88 +4.3.4.10 У ст ановк а делителя частоты синхронного вво да с цифровых линий . Формат: int32_t X502 _SetDinFreqDivider (t_x502_hnd hnd, uint32_t din_freq_div) Описание: Частот а синхр о н ног о вво да данны х с цифровых вх о дов получаетс я к ак резу ль- т ат де ления опорной частоты синхронизации на делитель, у с т анавливаемый этой функцией. Аль тернативой этой функции служит X502_SetDinFreq() , к оторая рассчитывае т этот делитель на основании переданной требу емой частоты синхронного вво да с цифровых линий. Параметры: hnd  Описатель мо ду ля. din_freq_div  Делитель частоты синхронного вво да с цифровых линий (от 1 до X502_DIN_FREQ_DIV_MAX ). Возвращаемое зна чени е : Ко д ошибки. 4.3.4.11 У ст ановк а делителя частоты синхронного выво да Формат: int32_t X502 _SetOutFreqDivider (t_x502_hnd hnd, uint32_t out_freq_div) Описание: Частот а синхронного выво да данных получаетс я к ак резу ль т ат деления опорной частоты с ин хронизации на делитель, у ст анавливаемый этой фу нкцией. Использу ет- с я общая часто т а выво да для к аждого к анала ЦАП и для цифровых линий (выво д осуществляетс я параллельно). Час тот а выво да не мо ж ет быть больше половины опорной частоты. Аль тернативой этой функции служит X502_SetOutFreq() , к оторая рассчитывае т этот делитель на основании переданной требу емой частоты синхронного выво да. Для мо ду ля L-502, чтобы была возмо жность у с т ановить делитель, от личный от X502_OUT_FREQ_DIV_DEFAULT , необ х о ди мо об н о вить п рош и в к у ПЛИС до вер- сии 0. 5 или выше. Для мо ду ля E-502 в озмо жность всег да по ддер живаетс я. Про- верить программно наличие данной возмо жности мо жно с помощью функции X502_CheckFeature() . Параметры: hnd  Описатель мо ду ля. out_freq_div  Делитель частоты синхронного выво да (от X502_OUT_FREQ_DIV_ MIN до X502_OUT_FREQ_DIV_MAX ). Возвращаемое зна чени е : Ко д ошибки. 89 +4.3.4.12 У ст ановк а частоты сбора АЦП Формат: int32_t X502 _SetAdcFreq (t_x502_hnd hnd, double *f_acq, double *f_frame) Описание: Функция по дбирает делитель частоты АЦП т ак, чтобы полученная частот а сбора была наиболее близк а к ук азанной в параметре f_acq. Функция возвращает в этом ж е параметре реальную частоту , к о торая была у ст ановлена. Т ак ж е функция мо ж ет по добрать зна чение межк адровой задер жки т ак, чтобы частот а следования к адров (частот а сбора на логический к ан а л ) была наиболее близк а к ук аз анному з на чению. Для этого следу ет передать требу емое зна чение в переменной f_frame (в ней т акж е по завершению бу дет возвращено зна чение у ст ановленной частоты). Если в к а честве f_frame пере д а н ну левой ук азатель, то бу дет у ст ановлена ну левая межк адровая задер жк а. Если необ х о димо изменить зна чение опорной частоты, то д анная функция должна быть выз вана после X502_SetSyncMode() и X502_SetRefFreq() / X502_ SetExtRefFreqValue() , в противном случае полученные делители бу дут давать неверное зна чение частоты. Если у ст анавливаетс я частот а к адров, то функция должна вызыватьс я после того, к ак было заданно нужное к оличество логичес ких к аналов в управляющей т аблице с помо щью X502_SetLChannelCount() . При использовании внешней опорной частоты синхронизации эт а функц ия бу дет давать верный резу ль т ат , тольк о если эт а внешняя частот а соответству ет зна чению, у ст ановленному с помощью X502_SetRefFreq() . Параметры: hnd  Описатель мо ду ля. f_acq  На вх о де принимает требу емое зна чения частоты сбора АЦП в Г ерцах. На вых о де возвращает реально у ст ановленное зна чение частоты. f_frame  На вх о де принимает требу емое зна чение часто ты сбора к адров (часто- ты сбора на лог и че ский к анал) АЦП в Г ерцах. На вых о де воз вращает реально у ст ановленное зна чение. Если передан ну левой ук аз атель, то у ст анавливает мак симальную частоту с бора к адров (ну левую межк адровую задер жку). Возвращаемое зна чени е : Ко д ошибки. 90 +4.3.4.13 У ст ановк а частоты синхронного вво да с цифровых вх о дов Формат: int32_t X502 _SetDinFreq (t_x502_hnd hnd, double *f_din) Описание: Функция по дбир ае т делитель частоты вво да зна чений с цифровых вх о дов т ак, чтобы полученная час тот а вво да была наиболее близк а к ук азанной. Функция воз- вращает в этом ж е параметре реальную частоту , к оторая была у ст ановлена. Если необ х о димо изменить зна чение опорной час тоты синхронизации, то данная функция должна быть вызвана после X502_SetSyncMode() и X502_SetRefFreq() / X502_SetExtRefFreqValue() , в противном случае полученный д е ли т ель бу дет да- вать неверное зна чение частоты. При использовании внешней опорной частоты синхронизации эт а функц ия бу дет давать верный резу ль т ат , тольк о если эт а внешняя частот а соответству ет зна чению, у ст ановленному с помощью X502_SetRefFreq() . Параметры: hnd  Описатель мо ду ля. f_din  На вх о де принимает требу емое зна чения час тоты вво да с цифровых вх о- дов в Г ерцах. На вых о де возвращает ре альн о у ст ановленное зна чение частоты. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.14 У ст ановк а частоты синхронного выво да Формат: int32_t X502 _SetOutFreq (t_x502_hnd hnd, double *f_dout) Описание: Функция по дбирает делитель частоты синхронного выво да т ак, чтобы получен- ная частот а была наиболее близк а к ук азанной. Функция возвращает в этом ж е параметре реальную частоту , к оторая была у ст ановлена. Если необ х о димо изменить зна чение опорной час тоты синхронизации, то данная функция должна быть вызвана после X502_SetSyncMode() и X502_SetRefFreq() / X502_SetExtRefFreqValue() , в противном случае полученный д е ли т ель бу дет да- вать неверное зна чение частоты. При использовании внешней опорной частоты синхронизации эт а функц ия бу дет давать верный резу ль т ат , тольк о если эт а внешняя частот а соответству ет зна чению, у ст ановленному с помощью X502_SetRefFreq() . Для мо ду ля L-502, чтобы была возмо жность у ст ановить частоту , от личную от опорной частоты, деленной на X502_OUT_FREQ_DIV_DEFAULT , необ х о димо обновить прошивку ПЛИС до версии 0.5 или выше. Для мо ду ля E-502 возмо жность все - г да по дд е р живаетс я. Проверить программно наличие данной возмо жности мо жно с помощью функции X502_CheckFeature() . Параметры: hnd  Описатель мо ду ля. f_dout  На вх о де принимает требу емое зна чения частоты синхронного выво да в Г ерцах. На вых о де возвращ ает реально у ст ановленное зна чение част оты. Возвращаемое зна чени е : Ко д ошибки. 91 +4.3.4.15 Получить текущие зна чения частот сбора АЦП Формат: int32_t X502 _GetAdcFreq (t_x502_hnd hnd, double *f_acq, double *f_frame) Описание: Функция возвращает ткущие у ст ановленные для мо ду ля з н а чения частоты сбо- ра и частоты к адров АЦ П (частоты на логический к анал) в Г ерцах, к оторые бы- ли у ст ановлены до этого с помощью X502_SetAdcFreq() или с помощью функций X502_SetAdcFreqDivider() / X502_SetAdcInterframeDelay() . Параметры: hnd  Описатель мо ду ля. f_acq  Если не NU LL, то на вых о де возвращаетс я текущее зна чение частоты сбора АЦП. f_frame  Если не N ULL, то на вых о де возвращаетс я текущее зна чение частоты к адров АЦП. 4.3.4.16 У ст ановк а зна чения внутренней опорной частоты синхронизации Формат: int32_t X502 _SetRefFreq (t_x502_hnd hnd, uint32_t freq) Описание: Функция задает зна чение внутренней опорной частоты синхрони з ации , от к ото- рой пол учаютс я все частоты синхронного вво да/выво да посредством деления на определенный делитель. Данная функция при внутренней опорной частете выбирает о дну из двух до- ступных частот в 2МГц или 1.5 МГц(2МГц являетс я зна чением по умолчанию), для задания к оторых мо жно введены к онст анты из t_x502_ref_freq . При использовании внешней опорной частоты следу ет использовать X502_ SetExtRefFreqValue() . Для мо ду ля E-502 выво д на ЦАП при опорной частоте 1.5 МГц работ ае т тольк о для версии прошивки PLD A 1 или выше. Параметры: hnd  Описатель мо ду ля. freq  Зна чение из t_x502_ref_freq , к оторое задает выбранную опорную частоту . Возвращаемое зна чени е : Ко д ошибки. 92 +4.3.4.17 У ст ановк а зна чения внешней опорной ч астоты синхронизации Формат: int32_t X502 _SetExtRefFreqValue (t_x502_hnd hnd, double freq) Описание: При у ст ановк е внешней опорной частоты (вызов X502_SetSyncMode() со з ан че ни - ем, от личным от X502_SYNC_INTERNAL ) данная функция позволяет задать частоту внешней опорной частоты, к оторо я мо ж ет быть любая, но не превышать 1.5 МГц. Данная функция не влияет н а настройки самого мо ду ля, о днак о у ст ановк а к ор- ректного зна чения позволяет правильно у ст ановить нужную частоту сбора функ- циями X502_SetAdcFreq() , X502_SetDinFreq() и X502_SetOutFreq() , а т акж е к ор- ректно рассчит ать зна чения по умолчанию для размера буфера и шаг а переда чи данных между мо ду лем и ПК. Данная функция доступна в библиотек е версии 1.1.4 или выше . Параметры: hnd  Описатель мо ду ля. freq  Зна чение внешней опорной частоты в Гц. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.18 У ст ановк а зна чения для аналоговой синхронизации (тольк о для E16) Формат: int32_t X502 _SetAdcSyncStartValue (t_x502_hnd hnd, uint32_t phy_ch, u int32_t mode, uint32_t range, double value) Описание: Параметры: hnd  Описатель мо ду ля. ph y_c h  Номер физическ ого к анала АЦП, на чиная с 0 (0-15 для дифференци- ального режима, 0-31 для режима с общей землей) mo de  Р ежим измерения к анал АЦП (зна чение типа t_x502_lch_mode ) range  Диапазон измерения к анала (зна чение типа t_x502_adc_range ) v al ue  Зна чение в Воль т а х . Возвращаемое зна чени е : Ко д ошибки. 93 +4.3.4.19 Получение зна чения опорной частоты синхрон изации Формат: int32_t X502 _GetRefFreqValue (t_x502_hnd hnd, double *freq) Описание: Данная функция возвращает текущее зна чение опорной частоты синхро- низации, к оторое использу етс я библиотек ой в фун кциях X502_SetAdcFreq() , X502_SetDinFreq() и X502_SetOutFreq() , а т акж е при рассчете параметров пе- реда чи данных между мо ду лем и ПК. При внутренней опорной частоте использу етс я зна чение, у ст ановленное X502_SetRefFreq() (1.5 или 2 Мгц), при внешней  частот а, у ст ановленная с по- мощью функции X502_SetExtRefFreqValue() . Данная функция доступна в библиотек е версии 1.1.4 или выше . Параметры: hnd  Описатель мо ду ля. freq  Зна чение внешней опорной частоты в Гц. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.20 У ст ановк а режима генерации частоты синхрони зации Формат: int32_t X502 _SetSyncMode (t_x502_hnd hnd, uint32_t sync_mode) Описание: Функция у ст анавливает кто бу дет генератором опорной частоты синхронизации - сам мо ду ль или бу дет использоватьс я внешний сигнал. В режиме X502_SYNC_INTERNAL мо ду ль сам бу дет генерировать для себ я частоту синхронизации с частотой, заданной X502_SetRefFreq() . При этом запу ск генера- ции бу дет осуществлен по вызову X502_StreamsStart() или по у словию, заданому в X502_SetSyncStartMode() , а ост анов по X502_StreamsStop() . В ост альных режимах сбор бу дет осуществлятьс я по внешнему сигналу синхро- низации. Параметры: hnd  Описатель мо ду ля. sync_mo de  Зна чение из t_x502_sync_mode , определяющее кто бу дет источни- к ом частоты с ин хронизации. Возвращаемое зна чени е : Ко д ошибки. 94 +4.3.4.21 У ст ановк а режима запу ск а частоты синхронизации Формат: int32_t X502 _SetSyncStartMode (t_x502_hnd hnd, uint32_t sync_start_mode) Описание: Функция у ст анавливает у словие запу ск а синхронн ог о вво да/выво да данных. Если с помощью X502_SetSyncMode() у ст ановлен режим с и нхронизации X502_SYNC_INTERNAL , то по заданному данной ф ункцией у словию мо ду ль на чнет генерировать частоту синхронизации, в противном случае по заданному у словию мо ду ль на чнет использовать внешне за д а н ную частоту синхронизации (т .е. до вы- полнения у словия сигнал синхронизации на заданном вх о де бу дет игнорироватьс я). Р ежимы задания у словия запу ск а синхронизации имеют те ж е зна че- ния, что и режимы з адани я самой частоты (см. тип t_x502_sync_mode ). В случае X502_SYNC_INTERNAL запу ск осуществляетс я при выполнении функции X502_StreamsStart() , в противном случае - после выполн е ния X502_StreamsStart() мо ду ль на чинает о жидать заданного данной функцией у словия. Т .е . даж е при задании внешних источник ов синхронизации, все равно необ х о димо вызывать X502_StreamsStart() . Параметры: hnd  Описатель мо ду ля. sync_start_mo de  Зна чение из t_x502_sync_mode , определяющее у словие за - пу ск а частоты синхронизации. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.22 У ст ановить режим р аботы мо ду ля Формат: int32_t X502 _SetMode (t_x502_hnd hnd, uint32_t mode) Описание: Функция у ст анавливает режим работы мо ду ля, к оторый определяет бу дет ли по- токи данных обрабатывать ПЛИС и ли сигнальный процессор Blac kFin. При вклю- чении пит ания мо ду лем всег да управляет ПЛИС. После з агрузки прошивки с помо- щью X502_BfLoadFirmware() мо ду ль перех о дит в режим управления сигнальным процессором. Данная функция мо ж ет использоватьс я д ля ручной у ст ановки режима, напри- мер, для возврат а в режим управления ПЛИС или для переключения в режим управления сигнальным процессором, если прошивк а уж е была загруж ена (напри- мер, через JT A G интерфейс при от ладк е). Параметры: hnd  Описатель мо ду ля. mo de  Р ежим работы мо ду ля из t_x502_mode . Возвращаемое зна чени е : Ко д ошибки. 95 +4.3.4.23 Получение текущего режима работы мо ду ля Формат: int32_t X502 _GetMode (t_x502_hnd hnd, uint32_t *mode) Описание: Функция возвращает текущий режим рабо ты мо ду ля. Параметры: hnd  Описатель мо ду ля. mo de  В данном п арам етре возвращаетс я текущий режим работы мо ду ля (из t_x502_mode ). Возвращаемое зна чени е : Ко д ошибки. 4.3.4.24 У ст ановить к оэффициенты для к ал ибровки зна чений АЦП Формат: int32_t X502 _SetAdcCoef (t_x502_hnd hnd, uint32_t range, double k, double offs) Описание: Функция записывает в ПЛИС к оэффициенты для к алибровки зна чений АЦП. При открытии мо ду ля, библиотек а считывает к алибровочные к оэффициенты из защищенной области Flash-памяти мо ду ля и записывает их в ПЛИС для выполне- ния к алибровки на лету . Р езу л ь тирующее зна чение АЦП вычисляетс я по форму ле (v al - os) * k, г де v al  нек алиброванное з на чение. Данная функция позволяет изменить использу емые к оэффициенты в то время, пок а не запущен синхронный сбор данных. При это м изменяютс я тольк о текущие к оэффициенты, а заво дские к алибровочные к оэффициенты из Flash-памяти со хра- няют свое зна чение и при сле дую щ ем открытии бу дут восст ановлены. Параметры: hnd  Описатель мо ду ля. range  Диапазон АЦП (из t_x502_adc_range ). k  У ст анавливаемое зна чение к оэффициент а шк алы. os  У ст анавливаемое зна чение смеще ни я ну ля. Возвращаемое зна чени е : Ко д ошибки. 96 +4.3.4.25 Получение текущих к алибровочных к оэффициентов А Ц П Формат: int32_t X502 _GetAdcCoef (t_x502_hnd hnd, uint32_t range, double *k, doubl e *offs) Описание: Функция возвращает текущие к алибровочные к оэффициенты для заданного диа- пазона измерения АЦП. Эти к оэ ф фициенты могут от ли чать с я от заво дских зна че- ний, со храненных во Flash-памяти мо ду ля, например, ес ли пользователь использо- вал X502_SetAdcCoef() для у ст ановки своих к оэффициентов. Параметры: hnd  Описатель мо ду ля. range  Диапазон АЦП (из t_x502_adc_range ). k  В данной переменной возвращаетс я текущий к оэффициент шк алы. os  В данной переменной возвращаетс я текущее смещение ну ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.26 У ст ановить к оэффициенты для к ал ибровки зна чений ЦАП Формат: int32_t X502 _SetDacCoef (t_x502_hnd hnd, uint32_t ch, double k, double of fs) Описание: Функция у ст анавливает к алибровочные к оэффициенты для заданного к анала АЦП, к оторые бу дут использ оватьс я функциями x502api для к алибровки выво- димых зна чений ЦАП, если ук азан фалаг X502_DAC_FLAGS_CALIBR . Отк алиброванное зна чение ЦАП в к о дах получаетс я к ак (v al + os) * k, г де v al  нек алиброванное з на чение (в к о дах). При открытии мо ду ля, библиотек а считывает к али б р о вочн ые к оэффициенты из защищенной области Flash-памяти мо ду ля и использу ет их. Данная функция нужна тольк о если пользователь х очет использовать свои к оэф- фициенты. При этом она не изменяет зна чения во Flash-памяти, т .е. при следующем открытии мо ду ля к оэффициенты бу дут снова восст ановлены из Flash-памяти. Параметры: hnd  Описатель мо ду ля. c h  Канал ЦАП (из t_x502_dac_ch ). k  У ст анавливаемое зна чение к оэффициент а шк алы. os  У ст анавливаемое зна чение смеще ни я ну ля. Возвращаемое зна чени е : Ко д ошибки. 97 +4.3.4.27 Получение текущих к алибровочных к оэффициентов ЦАП Формат: int32_t X502 _GetDacCoef (t_x502_hnd hnd, uint32_t ch, double *k, doubl e *offs) Описание: Функция возвращает текущие к алибровочные к оэффициенты для заданного к анала ЦАП. Эти к оэффициенты мог ут от личатьс я от заво дских зна чений, со- храненных во Flash-памя ти мо ду ля, например, если пользова тель использовал X502_SetDacCoef() для у ст ановки своих к оэффициентов. Параметры: hnd  Описатель мо ду ля. c h  Канал ЦАП (из t_x502_dac_ch ). k  В данной переменной возвращаетс я текущий к оэффициент шк алы. os  В данной переменной возвращаетс я текущее смещение ну ля. Возвращаемое зна чени е : Ко д ошибки. 98 +4.3.4.28 Р а ссчет частоты сбора АЦП Формат: int32_t X502 _CalcAdcFreq (double ref_freq, uint32_t lch_cnt, double *f _acq, double *f_frame, uint32_t *result_freq_div, uint32_t *result_frame_delay) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты АЦП и зна чение межк адровой за д е р жки т ак, чтобы полученные частоты были наиболее близки к заданным, и возвращает полученные зна чения частот . В от личие от X502_SetAdcFreq() , данная функция предназна чена получения ск орректированной частот ы без использования описателя мо ду ля и тольк о рас- считывает резу ль тирующие параметры, не изменяя настройки. Для мо ду ля E16 в параметре ref_freq следу ет передавать E16_REF_FREQ_48000KHZ, либо использ овать функцию X502_CalcA dcF req2! Параметры: ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) lc h_cn t  Количество логических к аналов, к оторое бу дет использов ано. Необ х о- димо для расчет а межк адровой з адер жки. Если в к а честве f_frame передан ну левой ук азатель, то мо ж ет быть равно 0. f_acq  На вх о де принимает требу емое зна чения частоты сбора АЦП в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к оторая мо ж ет быть у ст ановлена. f_frame  На вх о де принимает требу емое зна чение часто ты сбора к адров (часто- ты сбора на логический к анал) АЦП в Г ерцах. На вых о де возвращает рассчи- т анное зна чение. Е с ли передан ну левой ук азатель, то задер жк а рассчит ана не бу дет . Если пе редано зна чение меньше или равное ну ля, то бу дет расс ч ит ана мак симальная частот а к адров (с ну левой межк адровой задер жк ой). result_freq_div  В данном п а р а метре воз вращаетс я рассчит анное зна чения де- лителя частоты АЦП. Мо ж ет быть передан ну левой ук азатель, ес ли это зна- чение явно знать не требу етс я. result_frame_dela y  В данном параметре возвращаетс я рассчит анное зна чение межк адровой за д е р жки. Мо ж е т быть передан ну левой ук азате л ь , если это зна чение явно знать не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 99 +4.3.4.29 Р а ссчет частоты сбора АЦП Формат: 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) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты АЦП и зна чение межк адровой за д е р жки т ак, чтобы полученные частоты были наиболее близки к заданным, и возвращает полученные зна чения частот . В от личие от X502_SetAdcFreq() , данная функция предназна чена получения ск орректированной частоты и тольк о рассчитывает резу ль тирую щ и е параметры, не изменяя настройки. Описатель мо ду ля в этой функции нуж ен для того чтобы различать мо ду ли E16 и X502. Параметры: hnd  Описатель мо ду ля. ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) lc h_cn t  Количество логических к аналов, к оторое бу дет использов ано. Необ х о- димо для расчет а межк адровой з адер жки. Если в к а честве f_frame передан ну левой ук азатель, то мо ж ет быть равно 0. f_acq  На вх о де принимает требу емое зна чения частоты сбора АЦП в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к оторая мо ж ет быть у ст ановлена. f_frame  На вх о де принимает требу емое зна чение часто ты сбора к адров (часто- ты сбора на логический к анал) АЦП в Г ерцах. На вых о де возвращает рассчи- т анное зна чение. Е с ли передан ну левой ук азатель, то задер жк а рассчит ана не бу дет . Если пе редано зна чение меньше или равное ну ля, то бу дет расс ч ит ана мак симальная частот а к адров (с ну левой межк адровой задер жк ой). result_freq_div  В данном п а р а метре воз вращаетс я рассчит анное зна чения де- лителя частоты АЦП. Мо ж ет быть передан ну левой ук азатель, ес ли это зна- чение явно знать не требу етс я. result_frame_dela y  В данном параметре возвращаетс я рассчит анное зна чение межк адровой за д е р жки. Мо ж е т быть передан ну левой ук азате л ь , если это зна чение явно знать не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 100 +4.3.4.30 Р а ссчет частоты синхронного вво да с цифровых вх о дов Формат: int32_t X502 _CalcDinFreq (double ref_freq, double *f_din, uint32_t *result_freq_div) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты вво да зна чений с цифровых вх о дов т ак, чтобы полученная частот а вво да была наиболее близк а к ук азанной, и возвращает полученное зна чение частоты. В от личие от X502_SetDinFreq() , данная функция предназна чена получения ск орректированной частот ы без использования описателя мо ду ля и тольк о рас- считывает резу ль тирующие параметры, не изменяя настройки. Для мо ду ля E16 в параметре ref_freq следу ет передавать E16_REF_FREQ_48000KHZ, либо использ овать функцию X502_CalcDinF req2! Параметры: ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) f_din  На вх о де принимает требу емое зна чения час тоты вво да с цифровых вх о- дов в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к оторое мо ж ет быть у ст ановлено. result_freq_div  В данном п а р ам етре воз вращаетс я рассчит анное зна чения де- лителя частоты синхронного вво да ц ифровых лин ий. Мо ж ет быть передан ну левой ук азатель, если это зна чение явно з н ат ь не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 4.3.4.31 Р а ссчет частоты синхронного вво да с цифровых вх о дов Формат: int32_t X502 _CalcDinFreq2 (t_x502_hnd hnd, double ref_freq, double *f _din, uint32_t *result_freq_div) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты вво да зна чений с цифровых вх о дов т ак, чтобы полученная частот а вво да была наиболее близк а к ук азанной, и возвращает полученное зна чение частоты. В от личие от X502_SetDinFreq() , данная функция тольк о рассчитывает резу ль- тирующие параметры, не изменяя нас тройк и. Параметры: hnd  Описатель мо ду ля. ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) f_din  На вх о де принимает требу емое зна чения час тоты вво да с цифровых вх о- дов в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к оторое мо ж ет быть у ст ановлено. result_freq_div  В данном п а р ам етре воз вращаетс я рассчит анное зна чения де- лителя частоты синхронного вво да ц ифровых лин ий. Мо ж ет быть передан ну левой ук азатель, если это зна чение явно з н ат ь не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 101 +4.3.4.32 Р а ссчет частоты синхронного выво да Формат: int32_t X502 _CalcOutFreq (double ref_freq, double *f_dout, uint32_t *result_freq_div) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты с и нхрон- ного выво да т ак, чтобы полученная частот а была наиболее близк а к ук азанной, и возвращает полученное зна чение частоты. В от личие от X502_SetOutFreq() , данная функция предназна чена получения ск орректированной частот ы без использования описателя мо ду ля и тольк о рас- считывает резу ль тирующие параметры, не изменяя настройки. Функция пре д полаг ает , что мо ду ль по ддер ж и ва ет изменение частоты выво да (см. требования к мо д у лю для этого в описании функции X502_SetOutFreq() ). Для мо ду ля E16 в параметре ref_freq следу ет передавать E16_REF_FREQ_48000KHZ, либо использ овать функцию X502_CalcOutF re q2! Параметры: ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) f_dout  На вх о де принимает требу емое зна чения ч ас тоты синхронного выво да в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к от ор о е мо ж ет быть у ст ановлено. result_freq_div  В данном п а р ам етре воз вращаетс я рассчит анное зна чения де- лителя частоты синхронного выво да. Мо ж ет быть передан ну левой ук азатель, если это зна чение явно знать не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 102 +4.3.4.33 Р а ссчет частоты синхронного выво да Формат: int32_t X502 _CalcOutFreq2 (t_x502_hnd hnd, double ref_freq, double *f _dout, uint32_t *result_freq_div) Описание: Ис х о дя из заданных параметров, функция по дбирает делитель частоты с и нхрон- ного выво да т ак, чтобы полученная частот а была наиболее близк а к ук азанной, и возвращает полученное зна чение частоты. В от личие от X502_SetOutFreq() , данная функция предназна чена получения ск орректированной частот ы без использования описателя мо ду ля и тольк о рас- считывает резу ль тирующие параметры, не изменяя настройки. Функция пре д полаг ает , что мо ду ль по ддер ж и ва ет изменение частоты выво да (см. требования к мо д у лю для этого в описании функции X502_SetOutFreq() ). Параметры: hnd  Описатель мо ду ля. ref_freq  Зна чение опорной частоты в Гц (внешней или внутренней) f_dout  На вх о де принимает требу емое зна чения ч ас тоты синхронного выво да в Г ерцах. На вых о де возвращает рассчит анное зна чение частоты, к от ор о е мо ж ет быть у ст ановлено. result_freq_div  В данном п а р ам етре воз вращаетс я рассчит анное зна чения де- лителя частоты синхронного выво да. Мо ж ет быть передан ну левой ук азатель, если это зна чение явно знать не требу етс я. Возвращаемое зна чени е : Ко д ошибки. 4.3.5 Функции асинхронного вво да-выво да 4.3.5.1 Асинхронный выво д данных на к анал ЦАП Формат: int32_t X502 _AsyncOutDac (t_x502_hnd hnd, uint32_t ch, double data, uin t32_t flags) Описание: Функция выво дит ук азанное зна чение на ук азанный к анал ЦАП. Зна чение мо- ж ет быть задано к ак в к о дах, т ак и в Воль т ах, и к нему могут быть применены к алибровочные к оэффициенты (определяетс я флаг ами). Функция мо ж ет вызыватьс я либо к ог да синхронный с бор не запущен, либо п ри запущенном сборе данных, если синхронный выво д по этому к аналу ЦАП не раз- решен. Функция не работ ает в случае, если мо ду ль нах о дитс я в о жидании внешнего у словия для з апу ск а синхронного вво да (была вызвана X502_StreamsStart() при внешней синхронизации ст арт а, но сам сигнал запу ск а еще не возник) . Параметры: hnd  Описатель мо ду ля. c h  Номер к анала ЦАП (из t_x502_dac_ch ). data  Выво димое з н а чение на ЦАП (в к о дах и ли воль т ах) ags  Флаги из t_x502_dacout_flags . Возвращаемое зна чени е : Ко д ошибки. 103 +4.3.5.2 Асинхронный выво д данных на к анал ЦАП Формат: int32_t X502 _AsyncOutDac2 (t_x502_hnd hnd, uint32_t range, uint32_t ch, double da ta, uint32_t f lags) Описание: Функция выво дит ук азанное зна чение на ук азанный к анал ЦАП. Зна чение мо- ж ет быть задано к ак в к о дах, т ак и в Воль т ах, и к нему могут быть применены к алибровочные к оэффициенты (определяетс я флаг ами). Функция мо ж ет вызыватьс я либо к ог да синхронный с бор не запущен, либо п ри запущенном сборе данных, если синхронный выво д по этому к аналу ЦАП не раз- решен. Функция не работ ает в случае, если мо ду ль нах о дитс я в о жидании внешнего у словия для з апу ск а синхронного вво да (была вызвана X502_StreamsStart() при внешней синхронизации ст арт а, но сам сигнал запу ск а еще не возник) . Параметры: hnd  Описатель мо ду ля. range  Диапазон или вых о ды о дного к анала (для L T A37 1:1 или 1: 10) (из t_x502devs_dac_range ) c h  Номер к анала ЦАП (из t_x502_dac_ch ). data  Выво димое з н а чение на ЦАП (в к о дах и ли воль т ах) ags  Флаги из t_x502_dacout_flags . Возвращаемое зна чени е : Ко д ошибки. 104 +4.3.5.3 Асинхронный выво д данных на цифровые вы х о ды Формат: int32_t X502 _AsyncOutDig (t_x502_hnd hnd, uint32_t val, uint32_t msk) Описание: Функция выво дит ук азанное зна чение на цифровые вых о ды мо ду ля. Формат зна- чения аналогичен X502_PrepareData() - в младших 16 бит ах ук азываетс я выво ди- мое зна чение, а в ст аршие - флаги (с помощ ью к оторых мо жно перевести о дну из половин в третье состо яние). Функция мо ж ет вызыватьс я либо к ог да синхронный с бор не запущен, либо п ри запущенном сборе данных, если синхронный выво д по цифровым линиям не раз- решен. Мо жно использ овать маску , чтобы вывести тольк о на часть выво дов, ост авив ост альные неизме нн ыми, о днак о следу ет учесть, что после откр ытия связи с мо ду- лем необ х о димо сперва с делать выво д на все линии, после чего уж е мо жно исполь- зовать маску при последующих вызовах. Функция не работ ает в случае, если мо ду ль нах о дитс я в о жидании внешнего у словия для з апу ск а синхронного вво да (была вызвана X502_StreamsStart() при внешней синхронизации ст арт а, но сам сигнал запу ск а еще не возник) . Параметры: hnd  Описатель мо ду ля. v al  Младшая половина - выво димое зна чение, ст арш ая - флаги из t_x502_ digout_word_flags . Б иты 0..15 соответствуют вых о дам OUT1..OUT16 (E16) DO1..DO16 (x502) на сигнальном разъјм е msk  Маск а - ук азанные в маск е биты не бу дут изменятьс я с предыдущего вы- веденного сос то яния (распространяетс я и на ст арш ую половину v al). Возвращаемое зна чени е : Ко д ошибки. 105 +4.3.5.4 Асинхронный вв о д зна чений с цифровых вх о дов Формат: int32_t X502 _AsyncInDig (t_x502_hnd hnd, uint32_t *din) Описание: Функция считывает текущее зна чение цифровых вх о дов. При этом синхрон- ный сбор цифровых вх о дов не долж ен быть запущен (не разре шен поток X502_STREAM_DIN ). Т ак к ак мо ду ли E-502/L-502 не по ддер живают аппаратно асинхронный вво д, то если на момент вызова этой функции не запущен синхронный вво д/выво д с по- мощью X502_StreamsStart() , то данная функция на время выполнения запу ск ает синхронный сбор и ост а н а вл ива ет его к ак тольк о бу дет получено о дно новое зна- чение цифровых вх о дов, дл я мо ду лей E16 этого не требу етс я. Для мо ду ля E16 17 бит - состо яние вх о да INT, 18 бит - TRIG Функция не работ ает в случае, если мо ду ль нах о дитс я в о жидании внешнего у словия для з апу ск а синхронного вво да (была вызвана X502_StreamsStart() при внешней синхронизации ст арт а, но сам сигнал запу ск а еще не возник) . Параметры: hnd  Описатель мо ду ля. din  При у спешном выполнении в этой переменной возвращаетс я текущее сос то- яние цифровых вх о дов. Действительны младшие 18 бит , ст аршие 14 - резерв. Часть битов при этом объединены с линиями синхронизации, при этом это объединение зависит от типа мо ду ля. По др о бнее описано в разделе с разли- чиями мо ду лей E-502 и L-502. Р езервные биты могут быть использованы в последующих версиях, не следу ет счит ать, что они всег да бу дут равны ну лю! Возвращаемое зна чени е : Ко д ошибки. 106 +4.3.5.5 Асинхронный вв о д о дного к а дра АЦП Формат: int32_t X502 _AsyncGetAdcFrame (t_x502_hnd hnd, uint32_t flags, uint32_t tout, double *data) Описание: Функия произво дит о днократный вво д к адра в соответствии с заранее у ст а- новленной лог ич е ск ой т аблицей. Частот а сбора АЦП соответству ет частоте, у ст а- новленной с помощью X502_SetAdcFreq() . Частот а следования к адров зна чения не имеет . Сам к адр вво дитс я синхронно, но при последовательном вызове X502_ AsyncGetAdcFrame() для измерения неск ольких к адров задер жк а между этими к ад- рами не определена. Функция т ак ж е выполняет обработку принятых данных АЦП, ана- логично X502_ProcessAdcData() , и принимает набор флагов, аналогичный X502_ProcessAdcData() . Для работы этой функции не долж ен быть разрешен синхронный вв о д АЦП и цифровых линий. Т ак к ак аппаратно асинхронный вво д в плате отсутству ет , то эт а функция в случае не запущенного поток а з ап у ск ает его внутри себ я, принимает о дин к адр данных и после этого ост анавливает синхронный сбор. Параметры: hnd  Описатель мо ду ля. ags  Флаги из t_x502_pro c_ags tout  Т айма ут на выполнение фун кции в мс data  Массив, в к отором в случае у спе х а бу дут возв р а щены отсчеты к адра АЦП. Долж ен быть размером, дост аточным для хранения отсчетов типа double в к оличестве, равном к оличеству у ст ановленных логических к аналов в управ- ляющей т аблице А ЦП. Возвращаемое зна чени е : Ко д ошибки. 107 +4.3.6 Функции для работы с синхронным поток овым вв о дом- выво дом 4.3.6.1 Р азрешение синхронных поток ов на вво д/выво д Формат: int32_t X502 _StreamsEnable (t_x502_hnd hnd, uint32_t streams) Описание: Функция разрешает прием/переда чу для ук азанных поток ов Не ук азанные по- токи со храняют свое разрешенное или запрещенное сос то яние. Мо ж ет вызыватьс я к ак до X502_Configure() , т ак и после. Р азреш енные потоки у ст а н а вл ива ю тс я к ак правило до вызова X502_StreamsStart() . При ж елании в нек оторых ситу ациях мо жно изменять сост ав разрешенных пото- к ов во время запущенного сбора данных, о днак о если эти потоки сильно различа- ютс я в частоте, то рассчит анные библиотек ой зна че ни я буфера и шаг а прерывания могут не по дх о дить для изменивших с я зна че ни й (см. Размер буфера и ша г для синхронного режима ) Параметры: hnd  Описатель мо ду ля. streams  Набор флагов t_x502_streams , ук азывающих, к акие потоки должны быть разрешены. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.2 Запрещение син х р онных поток ов на вво д/выво д Формат: int32_t X502 _StreamsDisable (t_x502_hnd hnd, uint32_t streams) Описание: Функция запрещает переда чу синхронных данных дл я ук аза н ных поток ов. Не ук азанные потоки со храняют свое разрешенное или запрещенное состо яние. Функ- ция, противополо жная по смыслу X502_StreamsEnable() . Параметры: hnd  Описатель мо ду ля. streams  Набор флагов t_x502_streams , ук азывающих, к акие потоки должны быть запрещены. Возвращаемое зна чени е : Ко д ошибки. 108 +4.3.6.3 Получить зн а чение, к акие син х р онные потоки разрешены Формат: int32_t X502 _GetEnabledStreams (t_x502_hnd hnd, uint32_t *streams) Описание: Функция позволяет п о л учить набор флагов, к оторые ук азывают , к акие синхрон- ные потоки сейчас разрешены. Параметры: hnd  Описатель мо ду ля. streams  Набор флагов t_x502_streams , ук азывающих, к акие потоки сейчас раз- решены. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.4 Запу ск синхронных поток ов вво д а/выво да Формат: int32_t X502 _StreamsStart (t_x502_hnd hnd) Описание: Функция запу ск а синхронных поток ов данных. Все синхронные потоки т актиру- ютс я от общей опорной частоты. Если был у ст ановлен внутренний ст арт синхро- низации, то синхронизация поток ов на чнетс я при выполнении данн о й функци и, в противном случае по данной функции мо ду ль перейдет в состо яние о жидания внешнего признак а на чальной синхронизации. Т акж е функция ос уществляет инициализацию к анала DMA на вво д данных из платы, если был разрешен поток АЦП или синхронного вво да цифровых линий, и инициализацию к анала DM A на выво д, если был разрешен х от я бы о дин поток на выво д, но не была вызвана функция X502_PreloadStart() (о днак о в этом случае на чало выво да не совпадет с на чалом вво да). Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.5 Ост анов синхронных поток ов вво да /в ы во да Формат: int32_t X502 _StreamsStop (t_x502_hnd hnd) Описание: Функция ост анова синхронных поток ов вво да/выво да данных. После выполне- нию этой функции мо ду ль завершает генерацию опорной частоты синхрони з ации (или использовать внешнюю частоту синхронизации) и ос т анавливает синхронную переда чу данных. Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 109 +4.3.6.6 Проверк а, запущен ли синхронный вво д/выво д Формат: int32_t X502 _IsRunning (t_x502_hnd hnd) Описание: Функция провер яет запущен ли синхронный вво д выво д с помощью X502_StreamsStart() или к ак ой-либо внутренней логик ой в прошивки Blac kFin. Если сбор данных не запущен, то функция возвращает ошибку X502_ERR_STREAM_ IS_NOT_RUNNING , если запущен, то ну левой к о д ошибки Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.7 Чтение да нных АЦП и цифровых вх о дов из мо ду ля Формат: int32_t X502 _Recv (t_x502_hnd hnd, uint32_t *buf, uint32_t size, uin t32_t tout) Описание: Функция считывает данные от мо ду ля, к оторые были приняты в промежуточ- ный буфер в драйвере или библиотек е. Функция принимает отсчеты в специальном индек сном формате, в к отором со дер житс я информация, что это за данные (зна ч е - ния цифровых вх о дов или отсчеты АЦП) и дополнительная информация для АЦП (номер к анала, реж им) . Для разбора полученных отсчетов использу етс я функция X502_ProcessData() . Если в буфере сейчас нах о дитс я меньше отсчетов, чем было запрошено, то функ- ция бу дет о жидать пок а придет заданное к оличество данных или пок а не исте- чет ук азанный т айма ут . В последнем случае функ ция возвратит стольк о отсчетов, ск ольк о было в буфере при истечении т айма ут а. Количество готовых для чтения от счетов в буфере драйвера мо жно при ж елании узнать с помощью функции X502_GetRecvReadyCount() . До вызовов X502_Recv() синхронный поток с бора данных долж ен быть уж е за- пущен с помощью X502_StreamsStart() . Параметры: hnd  Описатель мо ду ля. buf  Буфер, в к оторые бу дут со хранены отсчеты. size  Количество считываемых отсчетов (32-битных слов). tout  Т айма ут на прием данны х в мс. Возвращаемое зна чени е : Если < 0 - к о д ошибки. Если >= 0 - к оличество счит анных слов. 110 +4.3.6.8 Переда ча поток овых данных ЦАП и цифровых вых о дов в мо ду ль Формат: int32_t X502 _Send (t_x502_hnd hnd, const uint32_t *buf, uint32_t size, uint32_t tout) Описание: Функция записывает данные на переда чу в промежуточный буфер, после чего эти данные бу дут переданы в мо ду ль. Данные должны быть в спе ц иальном фор- мате, к оторый определяет , что это за данные (цифровые вых о ды, к анал ЦАП1 или к анал ЦАП2). По дготовить данные в нужном формате мо жно с помощью X502_PrepareData() . Если промежуточный буфер на переда чу заполнен, то функция бу дет ждать пок а он не освобо ди т с я или пок а не истечет ук азанный т айма ут . Количество сво- бо дного мест а в буфере мо жно при ж елании узнать с помощью функции X502_ GetSendReadyCount() . Возвращение озна чает , что данные записаны в промежуточный буфер, а не то что они уж е дошли до мо ду ля и выведе н ы. Перед вызовом этой функции должна быть запущена предзагрузк а данных на выво д с помощ ью X502_PreloadStart() . Параметры: hnd  Описатель мо ду ля. buf  Буфер со словами, к оторые н е об х о димо передать мо д у лю size  Количество передаваемых отсчетов (32-битных слов). tout  Т айма ут на переда чу (в буфер драйвера) данных в мс. Возвращаемое зна чени е : Если < 0 - к о д ошибки. Если >= 0 - к оличество записанных слов. 111 +4.3.6.9 Обработк а принятых отсчетов АЦП от мо ду ля Формат: int32_t X502 _ProcessAdcData (t_x502_hnd hnd, const uint32_t *src, dou ble *dest, ui nt32_t *size, uint32_t flags) Описание: Функция выполняет обработку отсчетов АЦП, прочит а н ных с помощью X502_Recv() . Функция провер яет служ ебную информацию из вх о дного масс и- ва и перево дит отсчеты АЦП либо в к о ды, ли б о в воль ты (если ук азан флаг X502_PROC_FLAGS_VOLT ). Функция использу етс я, к ог да не запущен с инх ронный вво д с цифровых линий и отсчеты АЦП являютс я единственными прих о дящими от мо ду ля данными (е сли в принятом поток е бу дут другие данные - то они бу дут отброшены). Если запущ ен синхронный вво д с цифровых линий, то с л е ду ет использовать X502_ProcessData() , к оторая выделяет данные с циф ровых линий в от дельный массив. Параметры: hnd  Описатель мо ду ля. src  Вх о дной массив отсчетов, принятых с помощью X502_Recv() . dest  Массив, в к оторый бу дут со хранены преобразованные данные от АЦП. size  На вх о де - к оличество слов в массиве src, на вых о де - к оли че ство со хранен- ных преобразованных зна чений в массиве dest ags  Набор флагов из t_x502_proc_flags Возвращаемое зна чени е : Ко д ошибки. 112 +4.3.6.10 Обработк а принятых от мо ду ля данных Формат: 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) Описание: Функция выполняет обработку данных, прочит анных с помощью X502_Recv() . Функция провер яет служ ебную информацию из вх о дного массива, разбивает дан- ные на два массива - данные от АЦП, к оторые перево дятс я в тип double, и данные от синхронного цифрового вво да. Данные от АЦП т ак ж е могут быть переведены в воль ты. При этом данные АЦП прих о дят от мо ду ля уж е отк алиброванными с помощью к алибровочных к оэффи- циентов, т ак к ак к алибровк а выполняетс я аппаратно. Если данные АЦП не пере- во дятс я в Воль ты и при этом не были изменены з аво дские к алибровочные к оэффи- циенты, то возвращенное зна чение равное X502_ADC_SCALE_CODE_MAX соответству ет напр яж ению равному мак симальному для использу емого диапазона. Кроме того, функц ия разбирает сообщения, передаваемые в поток е данных (на- пример, сообщение о переполнении буфера). Параметры: hnd  Описатель мо ду ля. src  Вх о дной массив отсчетов, принятый с помощью X502_Recv() . size  Количество отсчетов (32-битных с лов) в массиве src. ags  Набор флагов из t_x502_proc_flags , управляющих поведением функции. Мо ж ет быть ук азано неск ольк о флагов через логическ ое ИЛИ . adc_data  Массив, в к оторый бу дут со хранены данные от АЦП, преобразован- ные в соответствии с ук азанными флаг ами. Мо ж ет быть NULL, если не нуж- но с о хранять данные от АЦП (тог да adc_data_size долж ен быть то ж е NULL, или в переменной передан размер 0). adc_data_size  На вх о де в данном параметре передаетс я резмер буфе- ра adc_data. Если данных от АЦП во вх о дном массиве бу дет больш е adc_data_size, то в adc_data б у дет с о хранено тольк о первые adc_data_size отсчетов. На вых о де при у спешном завершении функции в данную перемен- ную записываетс я к оличество со хранных отсчетов АЦП. Ук азатель мо ж ет быть равен NULL, если adc_data = NULL din_data  Массив, в к оторый бу дут со хранены отчеты с синхронного цифро- вого вво да. Каждое слово соответствуют сос то янию всех цифровых вх о дов в формате, описанном в функции X502_AsyncInDig() . din_data_size  Аналогично параметру a d c _ data_size в этом параметре переда- етс я размер буф е ра din_data в отсчет ах, а на вых о де со храняетс я к оличество реально со храненных о тсчетов цифрового вво да. Мо ж ет б ы т ь NULL, если din_data = N ULL. Возвращаемое зна чени е : Ко д ошибки. 113 +4.3.6.11 Обработк а при нятых от мо ду ля данных с пользовательскими дан- ными Формат: 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) Описание: Функция аналогична X502_ProcessData() , но позволяет т акж е выделить пользо- вательские данные из поток а. Пользовательскими данными счит аютс я все отсчеты, к оторые не являютс я данными АЦП, данными цифрового вво да или сообщениями. Пользовательские данные складываютс я без изменений в массив usr_data (если он не равен ну лю). Данная функция предназна чена в первую очередь для програм- мистов, к оторые бу дут использовать мо дифицированную прошивку сигнального процессора Blac kFin. Параметры: hnd  Описатель мо ду ля. src  Вх о дной массив отсчетов, принятый с помощью X502_Recv() . size  Количество отсчетов (32-битных с лов) в массиве src. ags  Набор флагов из t_x502_proc_flags . adc_data  Массив, в к оторый бу дут со хранены данные от АЦП (с м. X502_ProcessData() ). adc_data_size  см. X502_ProcessData() din_data  Массив, в к оторый бу дут со хранены отчеты с синхронного цифрового вво да. См. X502_ProcessData() . din_data_size  см. X502_ProcessData() . usr_data  Мас сив, в к оторый бу дут со хранены пользовательские данные без изменения их формат а. usr_data_size  В эт ом параметре передаетс я размер буфера usr_data а на вы- х о де со хран я етс я к оличество реально со храненных отсчетов пользоват ельских данных. Мо ж ет быть NULL тольк о если usr _data = NULL. Возвращаемое зна чени е : Ко д ошибки. 114 +4.3.6.12 По д го т ов к а данных для выво да в мо ду л ь Формат: int32_t X502 _PrepareData (t_x502_hnd hnd, const double *dac1, const dou ble *dac2, co nst uint32_t * digout, uint32_t size, int32_t flags, ui nt32_t *out_buf) Описание: Функция принимает данные из трех массивов - данные на цифровые вых о ды, отсчеты первого и второго к анала ЦАП. В к а честве массива мо ж ет быть передан ну левой ук азатель, если данные из этого источник а не требуютс я. Все использу е мые массивы должны б ы ть о дин а к ового размера и функция их равноме рн о перемеши- вает в общий поток, преобразу я в нужный для м о ду ля формат . Вых о дной массив долж ен бу дет со дер ж ать n*size отс четов, г де n - к оличество использу емых вх о дных массивов (от 1 до 3). Зна чения цифровых вых о дов предст авляют собой 32-битные слова, младшие 16- бит к оторых определяют зна чения выво дов, а ст аршие - флаги из t_x502_digout_ word_flags , к оторые могут использоватьс я в частности для перево да о дной (или обеих) из половин выво дов в третье состо яние. В к а честве зна чений ЦАП могут использоватьс я к ак к о ды, т ак и Воль ты, в за- висимости от переданных флагов, и к выво димым зна чениям могут быть приме- нены к алибровочные к оэффициенты. Если используютс я к о ды ЦАП с в к люченной к алибровк ой, то к о д X502_DAC_SCALE_CODE_MAX определяет к о д, соотв етствующий +5V. Параметры: hnd  Описатель мо ду ля. dac1  Вх о дной массив отсчетов первого к анала ЦАП или NULL, если не исполь- зу етс я. dac2  Вх о дной массив отсчетов второго к анала ЦАП или NULL, если не исполь- зу етс я. digout  Вх о дной массив со зна чениями цифровых выво дов или NULL, если не использу етс я. size  Р азмер к аждого из использу емых вх о дных массивов. ags  Флаги, управляющие работой функции, из t_x502_dacout_flags . out_buf  Вых о дной мас сив, в к оторый бу дут со хранены сформир ов анн ые от- счеты. Долж ен быть размера n*size (n - к олич е ство использу емых вх о дных массивов) Возвращаемое зна чени е : Ко д ошибки. 115 +4.3.6.13 По д го т ов к а данных для переда чи в мо ду ль Формат: int32_t X502 _PrepareData2 (t_x502_hnd hnd, const double *dac_data, uint32_t *dac_size, const uint32_t *dout_data, uint32_t *dout_size, uint32_t flags, uint32_t *result, uint32_t *snd_size, uint32_t ch_enabled) Описание: Функция принимает отсчеты ЦАП и цифровых линий и на основе этих данных формиру ет слова специального формат а для дальнейшей переда чи в мо ду ль с по- мощью X502_Send() . Данные от ЦАП принимаютс я в следующем пор ядк е: 1-ый отсчет первого разре- шенного к анала, зате м 1-ый отсчет второго т ак ого к анала и т .д., затем по второму отсчету к аждого к анала и т .д. В к а честве зна чений ЦАП могут использоватьс я к ак к о ды, т ак и Воль ты, в зависимости от переданных флагов, и к выво димым зна чениям могут быть применены к алибровочные к оэффициенты. Зна чения цифровых вых о дов предст авляют собой 32-битные слова, младшие 16- бит к оторых определяют зна чения выво дов, а ст аршие - флаги из t_x502_digout_ word_flags , к оторые могут использоватьс я в частности для перево да о дной (или обеих) из половин выво дов в третье состо яние. Формат вых о дных слов и к оличество слов н а отсчет определяетс я заданным фор- матом передаваемых данных. Функция завершает работу к ак тольк о з ак ончитс я место в вых о дном буфере. Параметры: hnd  Описатель мо ду ля. dac_data  Массив отсчетов ЦАП. Мо ж ет быть передан ну л е вой ук азатель, если используютс я тольк о выво д на цифровые линии. dac_size  На вх о де задает к оличество отсчетов в массиве dac_data, на вых о де возвращает , ск ольк о отсчетов было реально записано в вых о дной массив. dout_data  Массив зна чений для выво да на цифровые линии. Мо ж ет быть пе- редан ну левой ук азатель, е сли используютс я тольк о данные ЦАП. dout_size  На вх о де задает к оличество зна чений в массиве dout_ data, на вых о де возвращает , ск ольк о зна чений было реально записано в вых о дной массив. ags  Флаги, управляющие работой функции, из t_x502_dacout_flags . result  Р е зу ль тирующий массив в специальном ф орма те для переда чи в мо ду ль. snd_size  На вх о де задает разме р массива result, на вых о де возвращает , ск оль- к о всего 32-битных слов было записано в массив result в х о де выполнения функции. c h_enabled  Битовая маск а определяющая разрешенные к аналы, 1й бит - 1й к анал, 2й бит - 2й к анал, и т .д. Возвращаемое зна чени е : Ко д ошибки. 116 +4.3.6.14 По д го т ов к а о дного слова для выво да в ЦАП Формат: int32_t X502 _PrepareDacWrd (t_x502_hnd hnd, uint32_t dac_ch, double da c_val, int32_t flags, uint32_t *out_wrd) Описание: Функция принимает о дин отсчет для о дного к анала ЦАП. В к а честве зна чения отсчет а ЦАП могут использоватьс я к ак к о ды, т ак и Воль ты, в зависимости от пере- данных флагов, и к выво димым зна чениям могут быть применены к алибровочные к оэффициенты. Если и с пользуютс я к о ды ЦАП с вклю че н ной к алибровк ой, то к о д X502_DAC_SCALE_CODE_MAX определяет к о д, соответ ствующий +5V. Параметры: hnd  Описатель мо ду ля. range  Диапазон или вых о ды о дного к анала (для L T A37 1:1 или 1: 10) (из t_x502devs_dac_range ) dac_c h  Номер к анала ЦАП. dac_v al  Отсчет к анала dac_c h ЦАП. ags  Флаги, управляющие работой функции, из t_x502_dacout_flags . out_buf  Ук азатель на резу ль тирующее слово данных для к анал а dac_c h. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.15 Получить к оличество отсчетов в буфере поток а на вво д Формат: int32_t X502 _GetRecvReadyCount (t_x502_hnd hnd, uint32_t *rdy_cnt) Описание: Функция возвращает к оличество отс четов, к оторые были приняты из мо ду ля во внутренний б уф е р и готовы для считывания с помощью X502_Recv() . Т о есть если в X502_Recv() передать зна чение, к оторое верну ла данная функция, то X502_Recv() вернет это к оличество данных без о жидания (т ак к ак они уж е в буфере). При работе по Ethernet данная функция возвращает к орректное зна чение тольк о для ОС Windo ws. Параметры: hnd  Описатель мо ду ля. rdy_cn t  Количество готовых к приему отсчетов. Возвращаемое зна чени е : Ко д ошибки. 117 +4.3.6.16 Получить ра зме р свобо дного мест а в буфере поток а на выво д Формат: int32_t X502 _GetSendReadyCount (t_x502_hnd hnd, uint32_t *rdy_cnt) Описание: Функция возвращает к оличество отсчет ов, соответствующее свобо дному месту в буфере на переда чу в мо ду ль. Это к оличество отсчето в г арантированно мо ж ет быть передано с помощью X502_Send() без о жидания. Данная функция не реализована при работе по интерфейсу Ethernet (TC P). Параметры: hnd  Описатель мо ду ля. rdy_cn t  Количество слов, к оторому соответству ет свобо дное место в буфере на переда чу . Возвращаемое зна чени е : Ко д ошибки. 4.3.6.17 Получить номер следующего о жидаемого логическ ого к ан ала АЦП для обработки Формат: int32_t X502 _GetNextExpectedLchNum (t_x502_hnd hnd, uint32_t *lch) Описание: Функция возвращает номер логическ ого к анала АЦП, к оторый дол- ж ен быть обработ ан первым при следующем вызове X502_ProcessData() / X502_ProcessAdcData() в случае, если поток данных непрерывен. По сути, это номер логическ ог о к анала, следующий за логическим к аналом по- следнего обработ анного до этого отсчет а АЦП. Мо ж ет быть использовано при обработк е блок ов д анных не кратных целому к оличеству к адров. Если перед X502_ProcessData() вызывать данную функцию, то она вернет номер логическ о- го к анала, соответствующий первому отсчету АЦП, обработ анному последующим вызовом X502_ProcessData() . Например, если у ст ановлено 7 логических к аналов, а в X502_ProcessData() пе- редано для обработки кратное 7 к оличество отсчетов, т о последующий вызов X502_ GetNextExpectedLchNum() вернет ном ер к анала равный 0 (т ак к ак обработ ано це- лое число к адров и о жидаетс я снова на чало к адра). Если в X502_ProcessData() передан массив с 7*n + 5 отсчет ами АЦП, то следующим о жидаемым к аналом бу дет логический к анал с номером 5 (обработ аны к аналы 0,1,2,3,4 из неполного к адра). Параметры: hnd  Описатель мо ду ля. lc h  Номер логическ ого к анала (на чиная с ну ля). Возвращаемое зна чени е : Ко д ошибки. 118 +4.3.6.18 На чало по дготовки выво да синхронных данных Формат: int32_t X502 _PreloadStart (t_x502_hnd hnd) Описание: Функция должна вызыватьс я перед на чалом предзагрузки поток овых синхрон- ных данных на выво д. Для на чала выда чи синхронных данных о дновременно с на чалом синхронного вво да, к моменту на чала сбора часть данных должна быть уж е загруж ена в мо ду ль до вызова X502_StreamsStart() . Данная функция инициализиру ет к анал обмена на переда чу данных на выво д. После вызова этой функции мо жно загрузить часть данных на выво д с помощью X502_Send() . Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.19 На чало загрузки циклическ о го сигнала на выво д Формат: int32_t X502 _OutCycleLoadStart (t_x502_hnd hnd, uint32_t size) Описание: По вызову этой функции в д райве ре (для L502) или в памяти к онтроллера мо ду ля (для E502) выделяетс я место по д циклический буфер на выво д. Должна вызывать- с я перед загрузк ой циклических данных с помощью X502_Send() . Для у спешного выполнения долж ен быть с вобо дный буфер (использу етс я двой- ная буферизация) - т .е. функция не мо ж ет быть вызвана сразу после предыдущего X502_OutCycleSetup() . Кроме того не долж ен был быть использован поток овый выво д. Для L-502 размер мак симальный размер буфера определяетс я тольк о размером, к оторый позволяет выделить система на уровне драйвера. Для E-502 размер огра- ничен памятью встроенного к онтроллера. По дробнее смотри в описании различий E-502 и L-502. Параметры: hnd  Описатель мо ду ля. size  Количество отс четов в выво димом циклическ ом сигнале суммарно для всех использу емых к аналов выво да. Возвращаемое зна чени е : Ко д ошибки. 119 +4.3.6.20 У ст ановк а ранее загруж енного циклическ ого сигнала на выво д Формат: int32_t X502 _OutCycleSetup (t_x502_hnd hnd, uint32_t flags) Описание: По вызову этой функции ранее загруж енный циклический буфер ст ановитс я ак- тивным. Если синхронный вво д-выво д запущен (через X502_StreamsStart() ), то по этой функции сигнал бу дет выдаватьс я на вых о д , ина че выд а ча на чнетс я при запу ск е синхронного вво да-выво да. Если до этого уж е выво дилс я циклический сигнал, то смена на новый произойдет в к онце цикла предыдущего сигнала, если не ук азан флаг X502_OUT_CYCLE_FLAGS_ FORCE . Если не ук азан флаг X502_OUT_CYCLE_FLAGS_WAIT_DONE , то функция тольк о да- ет к оманду н а у ст ановку сигнала, не о ж и дая непосредственной смены сигнала или загрузки сигнала. В частности для о дновременного запу с к а с ин хронног о вво да и выво да необ х о димо с делать загрузку первого циклическ ого сиг н а л а с данным фла- гом, чтобы г арантировать, что сигнал полностью загруж ен к моменту запу с к а син- хронного вво да-выво да через X502_StreamsStart() . Данная функция должна быть вызвана тольк о после вызова X502_ OutCycleLoadStart() и загрузки ук азанного в не й к оличества отсчетов в бу- фер! Параметры: hnd  Описатель мо ду ля. ags  Флаги из t_x502_out_cycle_flags . Возвращаемое зна чени е : Ко д ошибки. 4.3.6.21 Ожидание у ст ановки ранее загруж енного циклическ ого сигнала на выво д Формат: int32_t X502 _OutCycleSetupWaitDone (t_x502_hnd hnd, uint32_t tout) Описание: Р еализу ет тот ж е функционал что и X502_OutCycleSetup с флагом X502_OUT_ CYCLE_FLAGS_WAIT_DONE Добавлен т айма ут о жидания у ст ановки циклическ ого сиг- нала. Данная функция должна быть вызвана тольк о после вызова X502_ OutCycleLoadStart() и X502_OutCycleSetup() и загрузки ук азанного в ней к оличества отсчетов в буфер! Параметры: hnd  Описатель мо ду ля. ags  Флаги из t_x502_out_cycle_flags . tout  Т айма ут в течении к оторого бу дет о жидатьс я, к ог да процессор заверш и т выполнение к оманды. Функция возвратит управление л ибо по завершению к оманды, либо по т айма уту . Возвращаемое зна чени е : Ко д ошибки. 120 +4.3.6.22 Ост а нов выво да циклическ ого сигнала Формат: int32_t X502 _OutCycleStop (t_x502_hnd hnd, uint32_t flags) Описание: По вызову этой функции прекращаетс я выда ча ранее у ст ановленного цикличе- ск ого сигнала с помощью X502_OutCycleSetup() . Ост ановк а осуществляетс я после выда чи последнего отсчет а в перио де, что позволяет знать к акие зна чения ос т а- нутс я на вых о дах. При вызове ж е X502_StreamsStop() (или при запрещении всех поток ов на выво д через X502_StreamsDisable() ) ост анов всех поток ов проис х о дит сразу и точная точк а ост анова неизвестна. При этом необ х о димо учитывать, что сама функция по умолчанию тольк о делает запрос на ост анов, а реально ост анов произойдет позж е. Если вызвать X502_StreamsStop() до завершения ост анова, то последний отсчет бу дет неизве- стен, т .е. необ х о димо до ждатьс я завершения ост анова, для чег о мо ж ет например быть использован флаг X502_OUT_CYCLE_FLAGS_WAIT_DONE . Параметры: hnd  Описатель мо ду ля. ags  Флаги из t_x502_out_cycle_flags . Возвращаемое зна чени е : Ко д ошибки. 121 +4.3.6.23 Проверк а, завершена ли у ст ановк а или ост анов цикл ическ ого сиг- нала Формат: int32_t X502 _OutCycleCheckSetupDone (t_x502_hnd hnd, uint32_t *done) Описание: Функция провер яет , завершена ли у ст ановк а циклическ ого сигнала после вызова X502_OutCycleSetup() или завершена ли ост ановк а генерации циклическ ого сиг- нала после вызова X502_OutCycleStop() . По своему назна чению аналогична флагу X502_OUT_CYCLE_FLAGS_WAIT_DONE в описанных выше функциях, но позволяет вы- полнить о жидание вручную (с проверк ой других у словий). Функция доступна в библиотеки, на чиная с версии 1.1.2, при этом для работы функции н е об х о дима версия прошивки ARM не ниж е 1.0.2 для мо ду ля E - 502 или версия драйвера не ниж е 1. 0.9 для L-502. В от личие от флаг а, если данные у словия не выполняютс я, то функция явно вернет ошибку X502_ERR_NOT_SUP_BY_FIRMWARE или X502_ERR_NOT_SUP_BY_DRIVER . Ожидание завершения мо ж е т быть необ х о димо при вызове X502_OutCycleSetup() при загрузк е первого сигнала до вызов а X502_StreamsStart() , если требу етс я, чтобы выда ча первых отсчетов на ЦАП совпала по времени с моментом запу ск а вво да, т .к. ина че загрузк а сигнала в мо ду ль мо ж ет не завершитьс я к моменту запу ск а и выда ча сиг н а л а на чнетс я с задер жк ой (акту ально для E502). При пос л е дую щ их вызовах X502_OutCycleSetup() для с мены уж е у ст ановленно- го сигнала у ст ановк а счит аетс я завершенной после заве ршения загрузки сигнала и непосредственной смены выдаваемого сигнала. Эту проверку мо жно использо- вать, чтобы явно узнать, что смена с игнала заве р ш ил ас ь и мо жно уж е загруж ать следующий циклический сигнал. При вызове X502_OutCycleStop() о жидание з авершения мо ж ет использоватьс я перед вызовом X502_StreamsStop() , чтобы убедитс я (если это необ х о димо), что генерация была завершена именно на последней точк е загруж енного цик личес к ого сигнала. Параметры: hnd  Описатель мо ду ля. done  0, е сли есть незавершенный запрос на у ст ановку или ост анов циклическ ого сигнала, 1  в противном случае (включая случай, к ог да выда ча циклическ о- го сигнала вообще не в едетс я) Возвращаемое зна чени е : Ко д ошибки. 122 +4.3.6.24 Чтение флагов ст ату са выво д а Формат: int32_t X502 _OutGetStatusFlags (t_x502_hnd hnd, uint32_t *status) Описание: Функция чит ает зна чения флагов ст ату са синхронного выво да из регистра ст ату- са. В частности по флагу X502_OUT_STATUS_FLAG_BUF_WAS_EMPTY мо жно проверить, не было ли опу стошения буфера с момент а запу ск а синхронного выво да, чтобы убе- дитьс я, что не было разрыва сигнала из-за непо дк а ченных вовремя данных. Параметры: hnd  Описатель мо ду ля. status  Флаги ст ату са  набор битов из t_x502_out_status_flags , объе ди не н - ных через логическ ое ИЛИ. Возвращаемое зна чени е : Ко д ошибки. 4.3.6.25 У ст ановк а размера буфера для синхронного вво д а или выво да Формат: int32_t X502 _SetStreamBufSize (t_x502_hnd hnd, uint32_t ch, uint32_t size) Описание: Функция у ст анавливает размер буфера, к оторый использу етс я для вре менного хранения данных на прием или на переда чу . Предназна чена для случаев, к ог да пользователя по к аким-либо причинам не у довлетвор яет рассчитываемое би б л ио- тек ой зна чение по умолчанию. Если функцией X502_SetStreamBufSize был у ст ановлен не ну левой раз- мер буфера, то э тот размер бу дет использоватьс я на чиная с первого вы- зова X502_Str e amsStart или X502_StreamsEnable и пересчитыватьс я далее не бу дет , чтобы библиотек а сама рассчит ала размер буфера надо вызвать X502_SetStreamBufSize с ну левым размером и он р а ссчит аетс я при первом X502_StreamsStart или X 502_S trea msEn abl e. Параметры: hnd  Описатель мо ду ля. c h  Определяет , у ст анавливаетс я размер буфера на вво д или на выво д (зна чение из t_x502_stream_ch ). size  Р азмер буфера в 32-битных отсчет ах, 0 - библиотек а бу дет сама рассчиты- вать зна чение по умолчанию Возвращаемое зна чени е : Ко д ошибки. 123 +4.3.6.26 У ст ановк а шаг а при переда че поток а на вво д или выво д Формат: int32_t X502 _SetStreamStep (t_x502_hnd hnd, uint32_t dma_ch, uint32_t step) Описание: Функция у ст анавливает шаг переда чи данн ых (шаг г енерации п ре ры в ан ий для PCI-Express или размер запроса для USB) при переда че синхронного поток а дан- ных на вво д или на выво д. Данная функция предназна чена для пользователей, к оторых не у строит автоматически рассчитываемое б и б л иоте к ой зна че н ие . Параметры: hnd  Описатель мо ду ля. dma_c h  О пределя ет , шаг переда чи у ст анавливаетс я на вво д или на выво д (зна- чение из t_x502_stream_ch ). step  Шаг прерывания в 32-битных отсчет ах Возвращаемое зна чени е : Ко д ошибки. 4.3.7 Функции для настройки сетевых параметров мо ду ля E502 4.3.7.1 Получение текущего IP-ад реса у стройства Формат: int32_t E502 _GetIpAddr (t_x502_hnd hnd, uint32_t *ip_addr) Описание: Функция возвращает IP-адрес у стройства по к оторому было у ст ановлено соеди- нение. Т о есть связ ь с у стройством должна быть уж е у ст ановлена и кроме того, у ст ановлена именно по интерфейсу Ethernet. Параметры: hnd  Описатель у стройства ip_addr  Т екущий IPv4 адрес мо ду ля в виде 32-битного слова (аналогично па- раметру ip_addr функ ции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 4.3.7.2 Создание оп исателя к онфигурации сетевого интерфейс а Формат: t_e502_eth_config_hnd E502_EthConfigCreate (void) Описание: Создание описателя к онф игурации сетевого интерфейса. В случае у спешного вы- деления памяти инициализиру ет поля описателя зна чениями по-умолчанию. Возвращаемое зна чени е : NULL в случае ошибки, ина че - описатель мо ду ля 124 +4.3.7.3 Освобо ждение оп исателя к онфигурации сетевого интерфейс а. Формат: int32_t E502 _EthConfigFree (t_e502_eth_config_hnd cfg) Описание: Освобо ждение памяти, выделенной по д описате ль к онфигурации сетевого интер- фейса с помощью E502_EthConfigCreate() . После этого описатель уж е использо- вать нельзя, независимо от возвращенного зна чения! Параметры: cfg  Описатель к онфигурации сетевого интерфейса Возвращаемое зна чени е : Ко д ошибки 4.3.7.4 Чтение текущей сетев ой к онфигурации интерфейса Формат: int32_t E502 _EthConfigRead (t_x502_hnd hnd, t_e502_eth_config_hnd cfg) Описание: Функция чит ает текущие параме тр ы интерфейса и со храняет их в структуру , на к оторую ук азывает созданный с помощью E502_EthConfigCreate() описатель к онфигурации сетевого ин т ерф е йса. Соединение с у стройством при этом должно быть у ст ановлено, но мо ж ет быть у ст ановлено по любому по ддер живаемому интерфейсу . Параметры: hnd  Описатель у стройства из к оторого нужно счит ать к онфигурацию cfg  Описатель к онфигурации сетевого интерфейса Возвращаемое зна чени е : Ко д ошибки 125 +4.3.7.5 Запись сетевой к онфигурации интерфейса Формат: int32_t E502 _EthConfigWrite (t_x502_hnd hnd, t_e502_eth_config_hnd cfg, const char *passwd) Описание: Функция пере д ае т мо ду лю к онфигурацию сетевого интерфейса, к оторую мо ду ль долж ен со хранить в своей энергонезависимой памяти. При у спешном выполнении данной функции мо ду ль отключает Ethernet- интерфейс, настраивает его на новые параметры и снова его инициализиру ет , по- этому если соединение с у стройством у ст ановлено по сети, то дал ь н е йшая работ а с у стройством бу дет уж е не возмо ж н а  необ х о димо закрыть связь с у стройством и у ст ановить ее заново. Для изменения к онфигурации необ х о димо передать пароль для к онфигурации (пу ст ая строк а, если пароль не был у ст ановле н) . При работе по USB интерфейсу в к а честве пароля мо жно пере дать текущий серийный номер у стройства (для случая, если забыт у ст ановленный пароль). Параметры: hnd  Описатель у стройства из к оторого нужно счит ать к онфигурацию cfg  Описатель к онфигурации сетевого интерфейса passwd  Строк а с паролем для из менения к онфигурации Возвращаемое зна чени е : Ко д ошибки 4.3.7.6 Копирование со дер жимого сетевой к онфигура ции интерфейса Формат: int32_t E502 _EthConfigCopy (t_e502_eth_config_hnd src_cfg, t_e502_eth_config_hnd dst_cfg) Описание: Функция выполняет к опирование всех параметров о дной созданной к онфигура- ции в другую к онфирураци ю, создавая полную к опию. Параметры: src_cfg  Описатель ис х о дной сетевой к онфигурации интерфейса, со дер жимое к оторой нужно ск опировать. dst_cfg  Описатель се тевой к онфигурации интерфейса, в к оторую нужно ск о- пировать со дер жимое ис х о дной к онфигурации Возвращаемое зна чени е : Ко д ошибки 126 +4.3.7.7 Определение, ра зреше н ли интерфейс Ethernet. Формат: int32_t E502 _EthConfigGetEnabled (t_e502_eth_config_hnd cfg, uint32_t *en) Описание: Функция возвращ ает , разре шен ли интерфейс Ethernet в ук азанной к онфи г ура- ции. Если интерфейс не разрешен, то Ethernet к онтроллер полностью отключен. Параметры: cfg  Описатель к онфигурации сетевого интерфейса en  Если интерфейс разрешен, то в данной переменной возвращаетс я 1, ина че  0 Возвращаемое зна чени е : Ко д ошибки 4.3.7.8 Р азрешение интерфейса Ethernet. Формат: int32_t E502 _EthConfigSetEnabled (t_e502_eth_config_hnd cfg, uint32_t en) Описание: Функция у ст анавливает , разрешена ли работ а по интерфейсу Ethernet. Если ин- терфейс не разрешен, то E the r ne t к онтроллер полностью отключен. Параметры: cfg  Описатель к онфигурации сетевого интерфейса en  0 озна чает запрет интерфейса Ethernet, 1  разрешение Возвращаемое зна чени е : Ко д ошибки 4.3.7.9 Определение, разрешено ли автоматическ ое получение параметров IP . Формат: int32_t E502 _EthConfigGetAutoIPEnabled (t_e502_eth_config_hnd cfg, uint 32_t *en) Описание: Функция возвраща ет , разрешено ли автома тич е ск ое получение параметров IP (IP-адрес, маск а по дсети, адрес шлюза) с использованием DHCP/linklo cal или ис- пользуютс я ст атически заданные параметры. Параметры: cfg  Описатель к онфигурации сетевого интерфейса en  Если разрешено автом атич е ск ое п о л уче н ие параметров, то возвращаетс я 1, ина че  0 Возвращаемое зна чени е : Ко д ошибки 127 +4.3.7.10 Р а зрешение автоматическ ого получения параметр ов IP . Формат: int32_t E502 _EthConfigSetAutoIPEnabled (t_e502_eth_config_hnd cfg, uint 32_t en) Описание: Функция у с т анавливает , разрешено ли автоматическ ое получение параметров IP (IP-адрес, маск а по дсети, адрес шлюза) с использованием DHCP/linklo cal или ис- пользуютс я ст атически заданные параметры. Параметры: cfg  Описатель к онфигурации сетевого интерфейса en  Если разрешено автом атич е ск ое п о л уче н ие параметров, то возвращаетс я 1, ина че  0 Возвращаемое зна чени е : Ко д ошибки 4.3.7.11 Получить состо яние автоматическ ого получения параметров IP . Формат: int32_t E502 _EthConfigGetAutoIPState (t_e502_eth_config_hnd cfg, uint 32_t *state) Описание: Функция возвращает , получил ли мо ду ль параме тры IP (IP-адрес, маск а по дсети, адрес шлюза) с использованием D HCP/linklo cal Параметры: cfg  Описатель к онфигурации сетевого интерфейса state  Состо яние автоматическ ого получения параметров IP Возвращаемое зна чени е : Ко д ошибки 4.3.7.12 Определение, разр еше н ли пользовательский MA C-адрес Формат: int32_t E502 _EthConfigGetUserMACEnabled (t_e502_eth_config_hnd cfg, uint 32_t *en) Описание: Функция возвращает , разрешен ли MA C-адрес, заданный пользователем, или ис- пользу етс я заво дск ой MA C-адрес. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. en  Если разре шен пользовательский MA C-адрес, то возвращаетс я 1, ина че (если использу етс я заво дск ой)  0 Возвращаемое зна чени е : Ко д ошибки 128 +4.3.7.13 Определение, разр еше н ли пользовательский MA C-адрес Формат: int32_t E502 _EthConfigSetUserMACEnabled (t_e502_eth_config_hnd cfg, uint 32_t en) Описание: Функция возвращает , разрешен ли MA C-адрес, заданный пользователем, или ис- пользу етс я заво дск ой MA C-адрес. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. en  Если разре шен пользовательский MA C-адрес, то возвращаетс я 1, ина че (если использу етс я заво дск ой)  0 Возвращаемое зна чени е : Ко д ошибки 4.3.7.14 Получение у ст ановленного ст атич е с к ого IP-адреса Формат: int32_t E502 _EthConfigGetIPv4Addr (t_e502_eth_config_hnd cfg, uint32_t *ip_addr) Описание: Функция возвращает заданный в к онфигурации ст атический IP-адрес, к ото- рый использу е тс я у стройством, если запрещено автоматическ ое получение IP- параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. ip_addr  Заданный IP-адрес в виде 32-битного слова (аналогично параметру ip_addr функции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 4.3.7.15 У ст ановк а ст атическ ого IP-ад реса Формат: int32_t E502 _EthConfigSetIPv4Addr (t_e502_eth_config_hnd cfg, uint32_t ip_addr) Описание: Функция у ст анавливает в к онфигурации заданный ст атический IP-адрес, к ото- рый бу дет использоватьс я у стройством, если запрещено автоматическ ое получение IP-параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. ip_addr  У ст анавливаемый IP-адрес в виде 32-битного слова (аналогично пара- метру ip_addr функ ции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 129 +4.3.7.16 Получение у ст ановленной ст ат ическ ой маски по дс е т и Формат: int32_t E502 _EthConfigGetIPv4Mask (t_e502_eth_config_hnd cfg, uint32_t *mask) Описание: Функция возвращает заданное в к онфигурации зна чение маски по дсети, к о- торая использу етс я у стройство м, если запрещено автоматическ ое получение IP- параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. mask  Маск а по дсети в виде 32-битного слова ( а н алог ич но параметру ip_addr функции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 4.3.7.17 У ст ановк а ст атическ ой м а ски по дсети Формат: int32_t E502 _EthConfigSetIPv4Mask (t_e502_eth_config_hnd cfg, uint32_t mask) Описание: Функция у ст анавливает в к онфигурации зна чение маски по дсети, к оторая бу- дет использоватьс я у стройством, если запрещено автоматическ ое п о л уче н ие IP- параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. mask  У ст анавливаемое зна чение маски по д с ети в виде 32-битного слова (анало- гично параметру ip_addr функции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 4.3.7.18 Получение у ст ановленного ст атич е с к ого адреса шлюза Формат: int32_t E502 _EthConfigGetIPv4Gate (t_e502_eth_config_hnd cfg, uint32_t *gate) Описание: Функция возвраща ет заданное в к онфигурации зна чение адреса шлюза, к о- торый использу етс я у стройством, ес л и запрещено автоматическ ое получение IP- параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. gate  Адрес шлюза в виде 32-битного слова (аналогично параметру ip_addr функции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 130 +4.3.7.19 У ст ановк а ст атическ ого ад реса шлюза Формат: int32_t E502 _EthConfigSetIPv4Gate (t_e502_eth_config_hnd cfg, uint32_t gate) Описание: Функция у ст а н а вл ива ет в к онфигурации зна чение адр е са шлюза, к оторый бу- дет использоватьс я у стройством, если запрещено автоматическ ое п о л уче н ие IP- параметров. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. gate  У ст анавливаемое зна чение адреса ш л юз а в виде 32-битного слова (анал о - гично параметру ip_addr функции E502_OpenByIpAddr() ). Возвращаемое зна чени е : Ко д ошибки 4.3.7.20 Получение у ст ановленного пользовательск ого MA C-адреса Формат: int32_t E502 _EthConfigGetUserMac (t_e502_eth_config_hnd cfg, uint8_t * mac) Описание: Функция возвращает заданное в к онфигурации зна чение пользовательск ого MA C-адреса, к от оры й использу етс я у стройством при явном его разрешении (см. E502_EthConfigSetUserMACEnabled() ). Параметры: cfg  Описатель к онфигурации сетевого интерфейса. mac  Пользовательский MA C-адрес у стройства в виде массива из X502_MAC_ADDR_SIZE байт в пор ядк е записи адреса Возвращаемое зна чени е : Ко д ошибки 4.3.7.21 У ст ановк а пользовательск ого MA C-адреса Формат: int32_t E502 _EthConfigSetUserMac (t_e502_eth_config_hnd cfg, const uin t8_t *mac) Описание: Функция у ст анавливает в к онфигурации зна чение п о л ьз овательск ог о MA C- адреса, к оторый бу дет использоватьс я у стройством при явном его разрешении (см. E502_EthConfigSetUserMACEnabled() ). Параметры: cfg  Описатель к онфигурации сетевого интерфейса. mac  У ст анавливаемое зна чение пользовательск ого MA C-адрес у стройства в в и де массива из X502_MAC_ADDR_SIZE байт в пор ядк е записи адреса Возвращаемое зна чени е : Ко д ошибки 131 +4.3.7.22 Получение заво дск ого MA C-адреса у стройства Формат: int32_t E502 _EthConfigGetFactoryMac (t_e502_eth_config_hnd cfg, uint8_t * mac) Описание: Функция возвращает зна чение заво дск ого MA C-адреса у стройства, к оторому соответству ет переданная первым параметром к онфигурация. Заво дск ой MA C- адрес, использу емый у стройством по-умолчанию, записывае тс я произво дителем (в Л Кар д) при произво дстве у стройства вместе с его серийным номером и не мо ж ет быть изменен пользователем. Ес ли пользователю нужно и з менить MA C- адрес у стройства , то он долж ен задать пользовате льский MA C-адрес с помо- щью E502_EthConfigGetUserMac() и разрешить его использование через E502_ EthConfigSetUserMACEnabled() . При этом всег да есть возмо жность снова вернуть- с я к ис п ольз ованию оригинального заво дск ого MA C-адреса. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. mac  Заво дск о й MA C-адрес у стройства в виде массива из X502_MAC_ADDR_SIZE байт в пор ядк е записи адреса Возвращаемое зна чени е : Ко д ошибки 4.3.7.23 Получение у ст ановленного имени экземпляра у стройства Формат: int32_t E502 _EthConfigGetInstanceName (t_e502_eth_config_hnd cfg, char *name) Описание: Функция возвращает заданное пользователем имя экземпляра у стройства. Дан- ное имя мо ж е т использоватьс я для обнаруж ения у стройства в сети. Если не задано, то использу етс я и м я, образованное назва н ие м у стройства и е го серийным номером. Данное имя должно быть уник ально в пределах сети. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. name  Ок анчивающаяс я ну лем строк а с заданным именем экзем п ля р а у строй- ства в формате UTF-8. Массив долж ен быть рассчит ан на X502_INSTANCE_ NAME_SIZE байт данных. Возвращаемое зна чени е : Ко д ошибки. 132 +4.3.7.24 У ст ановк а имени экземпляра у стройства Формат: int32_t E502 _EthConfigSetInstanceName (t_e502_eth_config_hnd cfg, cons t char *name) Описание: Функция у ст а н ав л ивае т имя экземпляра у стройства, к оторое мо ж ет использо- ватьс я для обнаруж ения у стройства лок альной в сети. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. name  Ок анчивающаяс я ну лем строк а с заданным именем экзем п ля р а у строй- ства в формате UTF-8. Мак симальный размер массива (включая завершаю- щий ноль) сост а вл я ет X502_INSTANCE_NAME_SIZE байт данных. Возвращаемое зна чени е : Ко д ошибки. 4.3.7.25 У ст ановк а нового пароля для смены к он фигурации Формат: int32_t E502 _EthConfigSetNewPassword (t_e502_eth_config_hnd cfg, cons t char *new_p asswd) Описание: Функция у ст анавливает новое зна чение пароля, к оторое должно бу дет использо- ватьс я для смены к онфигурации через E502_EthConfigWrite() . При этом зна че н ие при со хранении к онфигурации с у ст ановленным новым па- ролем необ х о димо для у спеш ной смены к онфигурации в E502_EthConfigWrite() передать зна чение пароля, к оторое было у ст ановлено до этого. Если функ- ция завершитс я у спешно, то для п о следующего изменения к онфигурации в E502_EthConfigWrite() нужно бу дет передавать уж е новое у ст ановленное зна че- ние пароля. Параметры: cfg  Описатель к онфигурации сетевого интерфейса. new_passwd  Ок анчивающаяс я ну лем строк а, со дер ж ащая новое зна чение па- роля для смены к онфигурации сетевого интерфейса. Мак симальный размер массива (включая завершающий ноль) сост авляет X502_PASSWORD_SIZE байт данных. Возвращаемое зна чени е : Ко д ошибки. 4.3.8 Функции для поиск а мо ду лей в лок альн ой сети 4.3.8.1 Тип: t_x502_search_eth_cb Описание: 133 +4.3.8.2 На чало сеанса поиск а мо ду лей в лок альной сети Формат: int32_t E502 _EthSvcBrowseStart (t_e502_eth_svc_browse_hnd *pcontext, uint32_t flags) Описание: При вызове данной функции запу ск ае тс я процесс поиск а сервисов, соответ- ствующих мо ду лям E-502, в лок альной сети и создаетс я к онтек ст текуще- го сеанс а поиск а. Этот к онтек ст использу етс я для дальнейших вызовов E502_ EthSvcBrowseGetEvent() . После завершения поиск а должна быть вызвана функ- ция E502_EthSvcBrowseStop() . Для запу с к а сеанса нео б х о дима з ап ущ енная служба (демон) обнаруж ения  по ддер живаютс я Bonjour для О С Windo ws и A v ahi для ОС Lin ux. Параметры: p con text  Ук азатель, в к оторый при у спешном выполнении со храня етс я к он- тек ст сеанса поиск а у стройств. ags  Флаги (резерв). Долж ен всег да передаватьс я 0. Возвращаемое зна чени е : Ко д ошибки. 134 +4.3.8.3 Получение информации о изменении присутствия мо ду лей в лок аль- ной сети Формат: int32_t E502 _EthSvcBrowseGetEvent (t_e502_eth_svc_browse_hnd context, t_e502_eth_svc_record_hnd *svc, uint32_t *event, uint32_t *flags, u int32_t tout) Описание: Данная функция позволяет к ак получить списо к присутствующих мо ду лей (се- тевых сервисов) в лок альной сети, т ак и отслеживать в дальнейшем измене н ие их состо яния. Функция ждет первого изменения состо яния и возвращ ает информацию о нем. Информация состоит из события ( по явление сетевого сервиса, исчезновение, изме- нение параметров) и из описателя сетевого сервиса, к оторому соответству ет собы- тие. После на чал а поиск а с помощью E502_EthSvcBrowseStart() к онтек ст не со дер- жит информации о наличие сетевых сервисов. Если уж е есть по дключенные в ло- к альной сети мо ду ли E-502, то инфор м аци я о них бу дет возвраще н а в следующих E502_EthSvcBrowseGetEvent() с событием E502_ETH_SVC_EVENT_ADD , за к аждый вызов по о дному у стройству . Если за заданный т айма ут не произошло ни о дного изменения, то функция за- вершитс я у спешно по ок ончанию т айма ут а и вернет событие E502_ETH_SVC_EVENT_ NONE . При ж елании мо жно про долж ать вызвать данную функцию д ля непрерывного отслеживания сос то яния по д ключения мо ду лей. Параметры: con text  Описатель к онтек ст а поиск а, созданный при вызове E502_ EthSvcBrowseStart() . sv c  Если возвращенное событие не равно E502_ETH_SVC_EVENT_NONE , то в данной переменной со храняетс я созданный описатель сетевого сервиса, соответству- ющего ук азанному событию. Этот описатель долж ен быть всег да уничто ж ен вручную с помощью E502_EthSvcRecordFree() . ev en t  В данную переменную со храняетс я к о д события (о дин из t_e502_eth_ svc_event ). Если за ук азанное вре мя не произошло ни о дного события, то возвращаетс я к о д E502_ETH_SVC_EVENT_NONE . ags  В данной переменной со храняютс я дополнительные к о ды флагов (резе рв). Мо ж ет быть передан ну левой ук азатель, ес л и зна чение флагов не интересу ет . tout  Т айма ут (в мс) на время о жидания события Возвращаемое зна чени е : Ко д ошибки. 135 +4.3.8.4 Ост анов сеанса поиск а мо ду лей в лок альной сети Формат: int32_t E502 _EthSvcBrowseStop (t_e502_eth_svc_browse_hnd context) Описание: При вызове данной функции процес с поиск а сетевых се рвисов, соответс твую щ ий ук азанному к онтек сту , ос т анавливаетс я. Все ресурсы, выделенные на эт апе E502_ EthSvcBrowseStart() освобо ждаютс я. Конте к ст с этого моме нт а ст а н о витс я недей- ствительным. Вызову E502_EthSvcBrowseStart() всег да долж ен соответ ствовать последующий вызов E502_EthSvcBrowseStop() для к орректног о освобо ждения ре- сурсов. Параметры: con text  Описатель к онтек ст а поиск а, созданный при вызове E502_ EthSvcBrowseStart() . Возвращаемое зна чени е : Ко д ошибки. 4.3.8.5 Освобо ждение оп исателя сетевого сервиса Формат: int32_t E502 _EthSvcRecordFree (t_e502_eth_svc_record_hnd svc) Описание: Освобо ждение памяти, выделенной по д оп ис атель сетевого сервиса при вызове E502_EthSvcBrowseGetEvent() . Параметры: sv c  Описатель сетевого сервиса Возвращаемое зна чени е : Ко д ошибки 4.3.8.6 Получить и м я экземпляра по описателю сервиса Формат: int32_t E502 _EthSvcRecordGetInstanceName (t_e502_eth_svc_record_hnd svc, char *name) Описание: Функция возвращает имя экземпляра се р вис а. Это имя соответству ет имени, к оторое у ст ановлено в сетевых настройк ах мо ду ля, соответствующего ук азанно- му се рвису , с помощью E502_EthConfigSetInstanceName() . Следу е т отметить, что данное имя, в от личие от ост ал ь н ых строк, предст авлено в к о дировк е UTF-8, к о- торая совпадает с обычной ASCI I с тр о к ой тольк о дл я символов анг лийск ого алфа- вит а. Функция не выполняет запросов к самому мо ду лю. Параметры: sv c  Описатель сетевого сервиса name  Массив на X502_INSTANCE_NAME_SIZE байт , в к оторый бу дет со хранено название экземпляра Возвращаемое зна чени е : Ко д ошибки 136 +4.3.8.7 Получить сери йный номер мо ду ля по описателю сетевого сервиса Формат: int32_t E502 _EthSvcRecordGetDevSerial (t_e502_eth_svc_record_hnd svc, char *serial) Описание: Функция возвращает серийный номер мо ду ля E-502, соответствующег о се тево- му сервису , на к оторый ук азывает пе р е данн ый описатель. Функция не выполняет запросов к самому мо ду лю . Параметры: sv c  Описатель сетевого сервиса serial  Массив на X502_SERIAL_SIZE байт , в к оторый бу дет со хранен серийный номер Возвращаемое зна чени е : Ко д ошибки 4.3.8.8 Получить и м я у сройства мо ду ля по описателю сетевого сервиса Формат: int32_t E502 _EthSvcRecordGetDevName (t_e502_eth_svc_record_hnd rec, char *devname) Описание: Функция возвращает имя у стройства мо ду ля (E502 или E16), соответствую- щего сете вому сервису , на к оторый ук азывает переданный описатель. Функция не выполняет запросов к самому мо ду лю. Параметры: sv c  Описатель сетевого сервиса devname  Масс и в на X502_DEVNAME_SIZE байт , в к оторый бу дет со хранено имя у стройства Возвращаемое зна чени е : Ко д ошибки 4.3.8.9 Получить IP адрес сетевого сервиса Формат: int32_t E502 _EthSvcRecordResolveIPv4Addr (t_e502_eth_svc_record_hnd svc, uint32_t *addr, uint32_t tout) Описание: Функция получает I P-адр е с мо ду ля E-5 02, соотве тствующего се тевому сервису , на к оторый ук азывает переданный описатель. Функция при н е об х о димости мо ж ет выполнять запросы к самому мо ду лю для получения этого адреса, если информа- ции о адресе нет в к еш е. Параметры: sv c  Описатель сетевого сервиса addr  IP-адрес мо ду ля в виде 32-битного слова (аналогично параметру ip_addr функции E502_OpenByIpAddr() ) tout  Время о жидания ответ а от мо д у ля в случае необ х о димости выполнить з а- прос для у ст ановления адреса. Возвращаемое зна чени е : Ко д ошибки 137 +4.3.8.10 Проверк а, ук азывают ли оба описателя на о дин э кзем п ляр сервиса Формат: int32_t E502 _EthSvcRecordIsSameInstance (t_e502_eth_svc_record_hnd svc1, t_e502_eth_svc_record_hnd svc2) Описание: Функция провер яет , ук азывают ли оба описате ля сервисов на о дин и тот ж е экземпляр. Если прило ж ение с о храняет список описателей сервисов при их об- наруж ении, то данная функция мо ж ет ис п ольз оватьс я, например, при событи- ях E502_ETH_SVC_EVENT_REMOVE или E502_ETH_SVC_EVENT_CHANGED , чтобы п о н я ть, к ак ой записи в со храненном списк е соответству ет с обытие (т .е. функция E502_ EthSvcBrowseGetEvent() вернет новый описатель, но ук азывающий на тот ж е эк- земпляр, что и при событии E502_ETH_SVC_EVENT_ADD ) Параметры: sv c1  Первый описатель сетевого сервиса для сравнения sv c2  Второй описатель сетевого сервиса для сравнения Возвращаемое зна чени е : Ко д ошибки. Возвращае т X502_ERR_OK , если оба описателя ук азывают на о дин эк- земпляр. 138 +4.3.8.11 Получить спи сок записей, присутствующих в лок альной сети Формат: int32_t E502 _SearchEthForDevicesIPv4Addr (t_x502_devrec *rec_list, uint32_t flags, uint32_t size, uint32_t *devcount, uint32_t event_tout, uint32_t tcp_tout) Описание: Функция являетс я обертк ой E502_EthSv cBro wse ...() Функция нах о дит все по д- ключенные по интерфейсу Ethernet мо ду ли и инициализиру ет записи о к аждом найденном у стройстве и со храняет их в переданный список (если не ну левой). Воз- вращенные в с пи с к е записи должны быть очищены после использования с помощью X502_FreeDevRecordList() . Параметры: list  Массив для с о хранения з аписей о найденных у стройствах. Долж ен со дер- ж ать место для со хранения не менее size записей. Мо ж ет быть NULL, если size=0, а d e v cn t!=NULL, в случае, ес ли нужно тольк о получить к оличество мо ду лей в системе. size  Определяет , ск ольк о мак симально записей мо ж ет быть со хранено в м ассив list. Бу дут со хранены тольк о первые size записей, ес ли у стройств найдено больше. ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. dev cn t  Если не ну левой ук азатель, то в данную переменную со храняетс я общее число найденных мо ду лей, по дключенных по Ethernet (мо ж ет быть б ол ь ше size). ev en t_tout  Время на время о жидания события в мс функции E502_ EthSvcBrowseGetEvent() tcp_tout  Время для у ст ановления по дключения в мс функции E502_ MakeDevRecordByEthSvc() Возвращаемое зна чени е : Если <0  к о д ошибки, ина че к оличество со храненных записей о найденных у строй- ствах (всег да <= siz e). Именно на этот размер нужно с делать в дальнейшем X502_ FreeDevRecordList() для освобо ждения памяти, выделенной по д информацию, на к оторую ссылаетс я запись. 139 +4.3.8.12 Получить спи сок записей, присутствующих в лок альной сети Формат: int32_t E502 _SvcBrowseForDevices (t_x502_search_eth_cb cb, void *param, u int32_t flags, uint32_t event_tout) Описание: Функция являетс я обертк ой E502_EthSv cBro wse...() Функция нах о дит все по дключенные по интерфейсу Ethernet мо ду ли и вызывает функцию cb t_x502_searc h_eth_cb Параметры: cb  Ук азатель на call b a c k-функцию, к оторая бу дет вызвана с новым найденным экземпляром. param  Параметр для вызова cal lbac k-функции. ags  Флаги из t_x502_getdevs_flags , определяющие поведение функции. ev en t_tout  Время на время о жидания события в мс функции E502_ EthSvcBrowseGetEvent() Возвращаемое зна чени е : Ко д ошибки. 4.3.8.13 У ст ановк а номера tcp порт а для к оманд Формат: int32_t E502 _EthConfigSetTcpCmdPort (t_e502_eth_config_hnd cfg, uint16_t port) Описание: Если номер порт а по умолчанию не по дх о дит , его мо жно поменять этой функцией Параметры: cfg  Описатель к онфигурации сетевого интерфейса p ort  Номер порт а Возвращаемое зна чени е : Ко д ошибки 4.3.8.14 У ст ановк а номера tcp порт а для данных Формат: int32_t E502 _EthConfigSetTcpDataPort (t_e502_eth_config_hnd cfg, uint 16_t port) Описание: Если номер порт а по умолчанию не по дх о дит , его мо жно поменять этой функцией Параметры: cfg  Описатель к онфигурации сетевого интерфейса p ort  Номер порт а Возвращаемое зна чени е : Ко д ошибки 140 +4.3.8.15 Получение номера t cp порт а для к ом а нд Формат: int32_t E502 _EthConfigGetTcpCmdPort (t_e502_eth_config_hnd cfg, uint16_t *port) Описание: Параметры: cfg  Описатель к онфигурации сетевого интерфейса p ort  Ук азатель, ку да з апишетс я номер порт а в случае у спех а Возвращаемое зна чени е : Ко д ошибки 4.3.8.16 Получение номера t cp порт а для данных Формат: int32_t E502 _EthConfigGetTcpDataPort (t_e502_eth_config_hnd cfg, uint 16_t *port) Описание: Параметры: cfg  Описатель к онфигурации сетевого интерфейса p ort  Ук азатель, ку да з апишетс я номер порт а в случае у спех а Возвращаемое зна чени е : Ко д ошибки 4.3.9 Функции для работы с сигнальным процессором 4.3.9.1 Загрузк а прошивки сигнального процессора Bl ac kFin. Формат: int32_t X502 _BfLoadFirmware (t_x502_hnd hnd, const char *filename) Описание: Функция загруж ает прошивку сигнального процессора из ук азанного файла в процессор и запу ск ает ее, провер яет правильность загрузки путем получения вер- сии прошивки (через специальную к оманду). Прошивк а должна быть в бинарном формате LDR. Параметры: hnd  Описатель мо ду ля. lename  Имя файла с загруж аемой прошивк ой. Возвращаемое зна чени е : Ко д ошибки. 141 +4.3.9.2 Проверк а, загруж ена ли прошивк а Blac kFin. Формат: int32_t X502 _BfCheckFirmwareIsLoaded (t_x502_hnd hnd, uint32_t *version) Описание: Функция передает к оманды процессору Blac kFin дл я получения версии прошив- ки и е е состо яния. У спешное выполнение к оманд свидете льству ет о том, что в Blac kFin загруж ена действительная прошивк а. Кроме того прошивк е передаетс я информация о мо ду ле (наличие опций, версия ПЛИС и т .д.) для внутреннего ис - пользования. В случае у спех а мо ду ль перево дитс я в режим DSP . Данная функция мо ж ет служить для проверки, была ли загруж е на прошивк а раньше (чтобы не загруж ать повторно) или для проверки была ли она загруж ена через JT A G-интерфейс. Параметры: hnd  Описатель мо ду ля. v ersion  Если ук азате ль не ну левой, то в данной переменной возвращае тс я версия прошивки Blac kFin в случае у спешной проверки. Возвращаемое зна чени е : Ко д ошибки. 4.3.9.3 Чтение блок а данных из памяти си гнального процессора Формат: int32_t X502 _BfMemRead (t_x502_hnd hnd, uint32_t addr, uint32_t *regs, ui nt32_t size) Описание: Функция считывает блок данных напр ям ую из памяти процессора. Мо ж ет быть прочит аны данные, к ак из внутренней памя ти (L1), т ак и из внешней SD R AM . Для выполнения этой функции в Blac kFin должна быть загруж ена его прошивк а. Функция предназна чена в первую очередь для пользователей, пишущих свою программу для сигнального процессора. Параметры: hnd  Описатель мо ду ля. addr  Адрес памяти, на чиная с к оторого бу дет счит ан блок данных. regs  Массив, в к оторый бу дут со хранено прочит анное со дер жимое памя ти. size  Количество считываемых 32-битных слов. Возвращаемое зна чени е : Ко д ошибки. 142 +4.3.9.4 Запись блок а данных в память сигнал ьного процессора Формат: int32_t X502 _BfMemWrite (t_x502_hnd hnd, uint32_t addr, const uint32_t *regs, uint32_t size) Описание: Функция записывает блок данных напр ямую в памяти процессора Blac kFin. Б лок данных долж ен быть всег да кратен 8 3 2-битным словам (32 байт ам). Запись мо ж е т осуществлятьс я к ак во внутреннюю память (L1), т ак и во внешнюю SDRAM. Для выполнения этой функции в Blac kFin должна быть загруж ена его прошивк а. Функция предназна чена в первую очередь для пользователей, пишущих свою программу для сигнального процессора. Следу ет быть осторо жным, т .к. запись в область данных, использу емую програм- мой мо ж ет привести к ее неработоспос обности. Параметры: hnd  Описатель мо ду ля. addr  Адрес памяти, на чиная с к оторого бу дет записан блок данных. regs  Массив с данными для записи в сигнальный процессор. size  Количество записываемых данны х в 32-битных словах (должно быть кратно 8). Возвращаемое зна чени е : Ко д ошибки. 143 +4.3.9.5 Переда ча управляющей к оманды сигн альному процессору Формат: int32_t X502 _BfExecCmd (t_x502_hnd hnd, uint16_t cmd_code, uint32_t par, const ui nt32_t *snd_data, uint32_t snd_size, uint32_t *rcv_data, uint32_t rcv_size, uint32_t tout, uint32_t *recvd_size) Описание: Функция предназна чена для переда чи пользовательских управляющих к оманд процессору для пользователей, пишущих с вою прошивку Blac kFin. Управление работой сигнального процессора шт атным образом осуществляетс я через управляющие к оманды, к оторые записываютс я в специальную область па- мяти сигнального процессора. Сигнальный процессор обрабатывает к оманду и по завершению записывае т в эту ж е область резу ль т ат . Команды делятьс я на ст андартные, к оторые используютс я библиотек ой x502api и реализованы в шт атной прошивк е сигнального процессора и пользовательские, к оторые пользователь мо ж ет определять по своему у смотрению. Пользо вательские к оманды на чинаютс я с к о да X502_BF_CMD_CODE_USER (0x8000). Параметры: hnd  Описатель мо ду ля. cmd_co de  Ко д к оманды - определяет , что за к оманда выполн я етс я. par  Параметр, передаваемый с к омандой (зна че н ие зависит от к о да к оманды). snd_data  Опциональные данные, передаваемые вместе с к омандой. Если дан- ные не передаютс я, то д о л ж ен передаватьс я ну левой ук азатель и snd_size = 0. snd_size  Количество 32-битных слов, пе р е даваемых в snd_data rcv_data  Массив, в к оторый бу дут переданы данные, возвращенные процес- сором по завершению к оманды. Если данные не должны возвращ атьс я, то долж ен передаватьс я ну левой ук азатель, а rcv_size = 0. rcv_size  Количество 32-битных слов, к оторое о жидаетс я, что вернет процессор по выполнению к оманды. Массив rcv_data долж ен быть рассчит ан на данное к оличество слов. tout  Т айма ут в течении к оторого бу дет о жидатьс я, к ог да процессор заверш и т выполнение к оманды. Функция возвратит управление ли бо по завершению к оманды, либо по т айма уту . recvd_size  Если не являетс я ну левым ук азате лем, то в эту переменную бу дет со хранено к оличество 32-битных с лов, к оторое реально верну л процессор по- сле выполнения к оманды (процессор имеет право вернуть меньше данных, чем запрашивалось в rcv_size). Возвращаемое зна чени е : Ко д ошибки. Ес л и процессор выполнил к оманду с нену левым к о дом завершения, то этот к о д и бу дет возвращен функцией. 144 +4.3.10 Функции для работы с Flash-памятью мо ду ля 4.3.10.1 Чтение блок а данных из Flash-памяти Формат: int32_t X502 _FlashRead (t_x502_hnd hnd, uint32_t addr, uint8_t *data, ui nt32_t size) Описание: Функция считывае т массив д а н ных из Flash-памяти мо ду ля в массив, передан- ный пользователем. Для считывания не нужно специальное разрешение - оно до- ступно всег да. Параметры: hnd  Описатель мо ду ля. addr  Адрес на чала блок а. data  Массив, ку да бу дут со хр а н е ны счит анные данные (долж ен быть не м еньше size байт). size  Количество байт для чтения. Возвращаемое зна чени е : Ко д ошибки. 4.3.10.2 Запись блок а данных во Flash-память мо ду ля Формат: int32_t X502 _FlashWrite (t_x502_hnd hnd, uint32_t addr, const uint8_t * data, uint32_t size) Описание: Функция записывает переданный массив данных во Fl ash -пам ять мо ду ля. Эт а об- ласть должна быть предварительно стерт а с п ом ощью X502_FlashErase() и до на- чала изме нения должна быть вызвана фу нкция X502_FlashWriteEnable() , что бы разрешить любое изменение со дер жимого Flash-памяти. Пользователю для записи доступны тольк о первые X502_FLASH_USER_SIZE байт Flash-памяти. Параметры: hnd  Описатель мо ду ля. addr  Адрес на чала блок а. data  Массив с записываемыми данны м и (долж ен быть не меньше size байт). size  Количество байт для записи. Возвращаемое зна чени е : Ко д ошибки. 145 +4.3.10.3 Стирани е блок а во Flash-памяти Формат: int32_t X502 _FlashErase (t_x502_hnd hnd, uint32_t addr, uint32_t size) Описание: Функция стирает блок во Flash-памяти мо ду ля (все ячейки бу дут чит атьс я к ак 0xFF). Адрес и размер должны быть кратны 4096 байт! Перед вызовом этой функ- ции должна быть разрешена запись в пользовательскую область с помощью X502_ FlashWriteEnable() . Параметры: hnd  Описатель мо ду ля. addr  Адрес на чала блок а (долж ен быть кратен 4K). size  Количество байт для стирания (кратно 4K). Возвращаемое зна чени е : Ко д ошибки. 4.3.10.4 Р а зрешение записи в пользовательскую область Flash -памяти Формат: int32_t X502 _FlashWriteEnable (t_x502_hnd hnd) Описание: Функция разреш ает запись в пользовательскую область Flash-памяти (первые X502_FLASH_USER_SIZE байт). Должна быть вызвана до того, к ак мо жно бу дет ис- пользовать X502_FlashErase() и X502_FlashWrite() для изменения со дер жимого пользовательск ой области памяти. После завершения изменений следу е т вызвать X502_FlashWriteDisable() . Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 4.3.10.5 Запрет за писи в пользовательскую область Flash-памяти Формат: int32_t X502 _FlashWriteDisable (t_x502_hnd hnd) Описание: Функция запрещает запись в польз овательскую область Flash-памяти мо ду- ля ( пе р в ы е X502_FLASH_USER_SIZE байт). Должна быть вызвана после того, к ак нужные данные в пользовательск ой области были изменены с п о мощью X502_FlashErase() и X502_FlashWrite() , чтобы защитить пользовательскую об- ласть от случайной изменения в дальнейшем. Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 146 +4.3.11 Дополнительные вспомог ательные функции 4.3.11.1 Получить версию драйвера мо ду ля L-502. Формат: int32_t L502 _GetDriverVersion (t_x502_hnd hnd, uint32_t *ver) Описание: Функция возвращает версию драйвера, у ст ановленного для ук азанного откры- того у стройства. Версия возвращаетс я в виде 32-битного числа. Строк овое пред- ст авление воз вращенной версии - четыре числа, ст арш ее соответству ет ст аршему байту , младшее - младшему . Ст арший байт - маж орная ве рсия, второй по ст аршинству байт - минорная, тре- тий - ревизия, четвертый - номер сборки (не использу етс я - всег да 0). Это т а версия, к оторая отображ аетс я в диспетчере у ст р о й с тв в Windo ws или с помощью mo dinfo в Lin ux. Данная функция доступна тольк о для у стройств с интерфейсом PCI/PCI-Express (L502) Параметры: hnd  Описатель мо ду ля. v er  32-битное число, предст авляющее собой версию драйвера Возвращаемое зна чени е : Ко д ошибки. 4.3.11.2 Перево д мо ду ля E-502 в режим загрузчик а Формат: int32_t E502 _SwitchToBootloader (t_x502_hnd hnd) Описание: Функция перево дит у с тройство в реж и м заг ру з чик а для возмо жности обновления прошивки к онтроллера Cortex-M4 мо ду ля E-502 с помощью утил иты lb o ot. В зависимос ти от ис пол ь зу емого текущего интерфейса для соединения с мо ду лем, мо ду ль перево ди тс я в режим загрузки прошивки по интерфейсу USB (если соеди- нение было по USB) и ли по TFTP (если соединение бы ло по интерфейсу Ethernet). При у спешном вызове данной функции д а л ьне йшая работ а с текущем соедине- нием невозмо жна, т .е. единственным допу стимым следующим вызовом являетс я X502_Close() . При перех о де в загрузчик нах о дитс я в режиме загрузчик а пор ядк а 30с после чего, если не поступало запросов на перепрошивку загрузчик возвращает управление шт атной прошивк е. Пок а мо ду ль нах о дитс я в режиме загрузчик а с ним невозмо жно у ст ановить соединение с помощью функций данной библи о теки. Параметры: hnd  Описатель у стройства. Возвращаемое зна чени е : Ко д ошибки. 147 +4.3.11.3 Перезагрузк а прошивки ПЛИС Формат: int32_t E502 _ReloadFPGA (t_x502_hnd hnd) Описание: По данной к оманде к онтроллер Cortex-M4 мо ду ля E - 502 выполняет сброс ПЛИС и загрузку прошивки ПЛИС из внутренней Flash-памяти. Это сервисная функция, к оторая использу етс я г лавным образ ом для обновления прошивки ПЛИС. Параметры: hnd  Описатель у стройства. Возвращаемое зна чени е : Ко д ошибки. 4.3.11.4 Переда ча управляющей к оманды к онтроллеру Cortex-M4. Формат: int32_t E502 _CortexExecCmd (t_x502_hnd hnd, uint32_t cmd_code, uint32_t par, const ui nt8_t *snd_data, uint32_t snd_size, uint8_t *rcv_data, uint32_t rcv_size, uint32_t tout, uint32_t *recvd_size) Описание: Функция предназна чена для переда чи пользовательских управляющих к оманд к онтроллеру для случая мо диф ицированной прошивки Cortex-M4. Параметры: hnd  Описатель мо ду ля. cmd_co de  Ко д к оманды - определяет , что за к оманда выполн я етс я. par  Параметр, передаваемый с к омандой (зна че н ие зависит от к о да к оманды). snd_data  Опциональные данные, передаваемые вместе с к омандой. Если дан- ные не передаютс я, то д о л ж ен передаватьс я ну левой ук азатель и snd_size = 0. snd_size  Количество байт , передаваемых в snd_data rcv_data  Массив, в к оторый бу дут переданы данные, возвращенные процес- сором по завершению к оманды. Если данные не должны возвращ атьс я, то долж ен передаватьс я ну левой ук азатель, а rcv_size = 0. rcv_size  Количество байт , к оторое о жидаетс я, что вернет к онтроллер по вы- полнению к оманды. Массив rcv_data долж ен быть рассчит ан на данное к о- личество слов. tout  Т айма ут в течении к оторог о бу дет о жидатьс я, к ог да к онтроллер завершит выполнение к оманды. Функция возвратит управление ли бо по завершению к оманды, либо по т айма уту . recvd_size  Если не являетс я ну левым ук азате лем, то в эту переменную бу дет со хранено к оличество байт , к оторое реально верну л к онтроллер после выпол- нения к оманды (к онтроллер имеет право вернуть меньше данных, чем за- прашивалось в rcv_size). Если ук азатель ну левой, то возвращаение меньшег о к оличества данных счит аетс я ошибк ой. Возвращаемое зна чени е : Ко д ошибки. 148 +4.3.11.5 Получить версию библиотеки Формат: uint32_t X50 2_GetLibraryVersion (void) Описание: Функция возвращает версию библиотеки x502api. Версия возвращаетс я в виде 32-битного числа. Строк овое предст авление возвращенной версии  четыре ч ис л а , ст аршее соответств у ет ст аршему байту , младшее  младшему . Ст арший байт  маж орная версия , второй по ст аршинству байт  минорная, третий  ревизия, четвертый  номер сборки (не использу етс я  всег да 0) Возвращаемое зна чени е : 32-битное число, предст авляющее собой версию библиотеки 4.3.11.6 Получение строк и об ошибк е Формат: const char * X502_GetError String (int32_t err) Описание: Функция возвращает строку , соответствующую переданному к о д у ошибки. В на- сто ящее время возвращаетс я всег да р у сск ая версия с троки (возмо жно в бу дущем бу дет возмо жность сменить язык г лобальной функцией). Следу ет учесть, что в ОС Windo ws строк а возвращаетс я в ст андартной для Windo ws к о дировк е CP1251, в то время к ак в Lin ux использу етс я к о дировк а UTF-8. Параметры: err  Ко д ош и бки, для к оторого нужно вернуть строку . Возвращаемое зна чени е : Ук азатель на строку , соответс твующую к о ду ошибки 4.3.11.7 Морг а ние свето дио дом Формат: int32_t X502 _LedBlink (t_x502_hnd hnd) Описание: При вызове этой функции, ес л и не запущен синхронный вво д/выво д, проис х о дит кратк овременное затух ание красного цвет а свето дио да на передней панели L-502 или свето дио да LED1 мо ду ля E-502. Мо ж ет быть использована для визу альной идентифик ации мо ду ля после его откр ытия . При запущенном синхронном вво де/выво де данный свето дио д всег да горит зеле- ным цветом и данная функция не влияет на его состо яние. Параметры: hnd  Описатель мо ду ля. Возвращаемое зна чени е : Ко д ошибки. 149 +4.3.11.8 У ст ановк а по дт ягивающих резист оров на вх о дных лини ях Формат: int32_t X502 _SetDigInPullup (t_x502_hnd hnd, uint32_t pullups) Описание: Функция мо ж ет использоватьс я для включения по дт ягивающих резисторов на цифровых вх о дах. Для разных мо ду лей по дт ягивающие резисторы реализованы на разных вх о дах. Для мо ду лей E-502 и L-502 мо жно включать их на линиях SYN1 и SYN2. Для L-502 мо жно от дельно задавать включены или отключены по дт яжки на младшей ил и ст аршей половине цифровых линий. Для E-502 мо жно включить по дт ягивающие к ну лю резисторы на вх о дах межмо ду льной синхронизации. Для E- 16 линий TRIG и INT могут быть к ак вх о дом , т ак и вых о дом дл я сигналов ST AR T и CONV. На не ук азанных линиях по дт я гивающие резист ор ы бу дут отключены, если они были включены д о этого. При включении п ит ания все по дт ягивающие резисторы отключены. Параметры: hnd  Описатель мо ду ля. pullups  Флаги (из t_x502_pullups ), определяющие, на к аких линиях включены по дт ягивающие резисторы. Возвращаемое зна чени е : Ко д ошибки. 4.3.11.9 Получение пар аме т ра pullups для мо ду ля Формат: int32_t X502 _GetDigInPullup (t_x502_hnd hnd, uint32_t *pullups) Описание: Получение текущег о состо яния параметра pullups из мо ду ля. Р еализова н о тольк о для E16 Параметры: hnd  Описатель мо ду ля. pullups  Флаги (из t_x502_pullups ), определяющие, на к аких линиях включены по дт ягивающие резисторы. Возвращаемое зна чени е : Ко д ошибки. 150 +4.3.11.10 Проверк а по ддер жки мо ду лем заданной возмо жности Формат: int32_t X502 _CheckFeature (t_x502_hnd hnd, uint32_t feature) Описание: Функция использу етс я для проверки, по ддер живаетс я ли определенная возмо ж- ность из t_x502_features для данного мо ду ля с текущими версиями п рош ивок. Если возмо жность по ддер живаетс я, то бу де т возвращен к о д X502_ERR_OK . Данная функция доступна в библиотек е версии 1.1.6 или выше . Параметры: hnd  Описатель мо ду ля. feature  Зна чение из t_x502_features , определяющие, к акую возмо жность необ- х о димо проверить. Возвращаемое зна чени е : Если возмо жность по д де р живаетс я, то возвращаетс я X502_ERR_OK , ина че  к о д ошибки 4.3.11.11 Эк сперимент альная фу н кция. Игнорировать ошибку с заданным номером Формат: int32_t X502 _SuppressError (t_x502_hnd hnd, int32_t err) Описание: Функция использу етс я для у ст ановки номера ошибки, к оторую API бу дет игно- рировать и про должит работу к ак если бы этой ошибки не было. Данная функция бу дет полезна для тестов самого API или эк спериментов с ним. Параметры: hnd  Описатель мо ду ля. err  Зна чение из t_x502_errs , к акую ошибку игнорир о вать. Р еализовано тольк о для X502_ERR_STREAM_IS_R UNNING Возвращаемое зна чени е : Ко д ошибки 4.3.11.12 Формат: int32_t X502 _SetAfcCoef (t_x502_hnd hnd, double Fd, double SigFreq, double *K, ui nt32_t size, i nt enable) Описание: 4.3.11.13 Формат: int32_t X502 _GetAfcCoef (t_x502_hnd hnd, double *Fd, double *SigFreq, double *K, u int32_t size, int *enable) Описание: 151 +4.3.11.14 Функция зада ния параметров мо ду ля Формат: int32_t X502 _SetParam (t_x502_hnd hnd, uint32_t param, void *value) Описание: Функция использу етс я для у ст ановки параметров мо д у ля В новых версиях api параметры могут добавлятьс я Параметры: hnd  Описатель мо ду ля. param  Зна чение из t_x502_params , номер у ст анавливаемог о параметра v al ue  Зна чение параметра Возвращаемое зна чени е : Ко д ошибки 4.3.11.15 Функция задания параметров цифрового вво да д ля мо ду ля L T A 37. Формат: int32_t LTA3 7_SetDIParam (t_x502_hnd hnd, uint32_t echo_en, uint32_t echo_ch, uint32_t di_ch_en_mask) Описание: Параметры: hnd  Описатель мо ду ля. ec ho_en  Включение режима э х о к анала, данные на вво де - к о д выво д а на э х о к анал, ина че вво д цифровых вх о дов DI ec ho_c h  Номер к анал а из данных к оторого берутс я э х о данные di_c h_en_mask  Маск а вклю че н ных к аналов в поток е вво да Возвращаемое зна чени е : Ко д ошибки 152 +Г лава 5 Метки времени в поток е данных (тольк о для E502-P1) 5.1 Р ежим синхронизации времени по проток олу PTP В мо дифик ации E502-P1 добавлен мех анизм внутренних часов с возмо жностью их плавной по дстройки. Т акж е добавлена п о ддер жк а проток ола PTP для синхронизации времени по сети Ethernet и ре али з ована возмо жность вст авки меток времени в поток данных  на вво д , Т аким образом при включении меток времени по явилась возмо ж- ность вычислять точное время для к онкретных слов из поток а. E502-P1 по ддер ж и в ает тольк о P eer-to-P eer режим проток ола PTP , поэтому сервер реального времени с к о- торым проис х о дит синхронизация долж ен быть настроен именно на этот режим. В режиме PTP P eer-to-P eer к аждый узел сети (в т .ч. к оммут аторы) долж ен быть PTP - совместимым и учитывать задер жку до ближ айшего соседнего, ина че работ а PTP синхронизации не возмо жна. Если все у словия для работы PTP с облю дены, то синхронизация внутреннего зна че- ния времени (внутренних часов) в E502-P1 должна заработ ать автоматически, у строй- ство бу дет получать зна чение точного времени с сервера и к орректировать внутренние часы. Для того чтобы метки времени по явились в поток е  на вво д , необ х о димо специ- ально включить т ак ой режим через соотвтствующее API, по умолчанию этот режим выключен. Для работы с PT P в E502-P1 были добавлены неск ольк о новых регистров. Р анее зарезервированный бит в слове  на вво д теперь озна чает что слово являетс я метк ой времени и для нее вво дитс я признак  захват PTP . Признак  з ахват PTP - атрибут слова м етки време н и, оз н а чает что для поток а слов полученных меж д у двумя ме тк ами времени с у ст ановленным признак ом захват а мо жно вычислить время к аждого слова с определенной точностью. Для обе спечения требу емой точности синхронизации в E502-P1 введены неск ольк о настроек. € Допу стимая рассинхронизация часов, +-нс/с. При к аждом получении зна- чения точного времени от сервера, E502-P1 вычисляет разность зна чения внут- ренних часов со зна чением принятым от сервера. Далее эт а разность делитс я на время прошедшее после последней синхронизации (вычисленное по внутренним 153 +часам). Вычисленное зна чение сравниваетс я с заданным параметром. Синхрони- зация счит аетс я у спешной, если вычисленное зна чение не вых о дит за заданный интервал. € Минимальное к ол-во у спешных синхронизаций. Для того чтобы признак  захват PTP по явилс я, должно произойти минимальное к оличество у спешных синхронизаций. В случае неу да чной синхронизации, признак  захват PTP сбра- сываетс я и цикл о жидания минимального к оличества у спешных синхронизаций повтор яетс я. 5.1.1 Р абот а с мо ду лем при использовании меток времени Р абот а с метк ами времени из API реализована от дельно от функци й управления поток ом и функций получения данных из пот ок а. 1. Включ е ни е вст авки меток времени в поток данных  на вво д : X502_F pgaRegW rite(hnd, E502_REGS_ARM_TIME_CTRL, 1); 2. У ст ановк а настроек захват а: X502_F pgaRegW rite(hnd, E502_REGS_PTP_LOCK_LIMIT, (ptp_limit_ns & 0 x  ) j (ptp_req_hits << 16)) 1. Узнать состо яние признак а  захват PTP : X502_F pgaRegRead(E502_REGS_ARM_TIME_CTRL, &status); 2. Инициализировать к онтек ст для обработки ме ток времени: X502_tstp_init(&tstp_state, adc_freq, din_freq). 3. Обработк а ме ток времени из прочит анных данных с помощью X502_tstp_pro cess_wrd(&tstp_state, cur_wrd), г де cur_wrd - очередное слово полученное с помощью X502_Recv() 5.1.2 Описание регистров PTP E502_REGS_ARM_TIME_CTRL A ddress: 0x110 Bit Name A ccess Description Reset V alue [1] ST A TUS R признак  захват PTP 1: признак  захват PTP присутству- ет , у словия захват а выплнены 0: признак  захват PTP отсутству ет 0 [0] ENABLE R W 1: добавлять мет- ки времени в поток вво да 0: поток вво да без меток времени 0 154 +Bit Name A ccess Description Reset V alue E502_REGS_PTP_LOCK_LIMIT A ddress: 0x706 Bit Name A ccess Description Reset V alue [31:16] ENABLE R W Минимальное к ол-во у спеш- ных синхрони- заций 0 [15:0] ST A TUS R Допу стимая рассинхрони- зация часов, +-нс/с 0 5.1.3 PTP-совместимое обору дование Обору дование, совместная работ а к оторого с E502-P1 по п рот ок олу PTP была про- верена. Сервер времени: блок к оррекции времени ЭНК С-2 произво дства ООО ѕИнж енерный центр ЅЭнергосервисї (www.enip2.ru) Сетевой к оммут атор с по ддер жк ой PTP: блок L- VIMS-SWITCH произво дства ООО  Л КАР Д (www.lcard.ru) 5.2 Конст анты и перечисления 5.2.1 Конст анты и макроопределения Конст ант а Зна чение Описание TSP_NSEC_PER_SE C (1000000000) TSP_WRD1_SSEC_L EN (24) длина в бит ах для SubSecond в WRD1 слове метки времени TSP_WRD2_SSEC_L EN (7) длина в бит ах для SubSecond в WRD2 слове метки времени TSP_WRD2_SEC_LE N (19) длина в бит ах для Second в WRD2 слове метки времени TSP_WRD3_SEC_LE N (13) длина в бит ах для Second в WRD3 слове метки времени TSP_SSEC_WIDTH (TSP_WRD1_SSEC_ LEN + TSP_WRD 2_SSEC_ LEN) общая длина в бит ах для SubSecond в t_x502_tstptime (дробный формат 32.31) TSP_WRD_NUM (((wrd) >> 26) & 3) Номер слова с метк ой времени 0..3 155 +TSP_WRD0_ADC_CL K_NUM_MASK (0x3ffffff) Счетчик преобразования АЦП в WRD0 слове с метк ой времени TSP_WRD1_LOCK_M ASK (1 << 25) Признак захват а време ни от PTP сервера TSP_WRD1_FMARK_ MASK (1 << 24) Признак первой метки после перех о да GO в активное со- сто яние TSP_WRD1_SSEC_M ASK ((1 << TSP_WRD1_ SSEC_LEN) - 1) битовая маск а для SubSecond в WRD1 TSP_WRD2_SEC_MA SK (0x3ffff80) битовая маск а для S e cond в WRD2 TSP_WRD2_SSEC_M ASK ((1 << TSP_WRD2_ SSEC_LEN) - 1) битовая маск а для SubSecond в WRD2 TSP_WRD2_SECSSE C_MASK ((1 << (TSP_WRD2_ SEC_LEN + TSP_WRD2_ SSEC_LEN)) - 1) битовая маск а для Second + SubSecond в WRD2 TSP_WRD3_SEC_MA SK ((1 << TSP_WRD3_ SEC_LEN) - 1) битовая маск а для S e cond в WRD3 TSP_WRD1_IS_FMA RK (!!((wrd) & TSP_ WRD1_FMARK_MASK )) макрос для проверки выст ав- лен ли признак первой метки для слова WRD1 TSP_WRD1_IS_LOC K (!!((wrd) & TSP_ WRD1_LOCK_MASK) ) макрос для проверки выст ав- лен ли признак lo c k для слова WRD1 TSP_WRD1_GET_SS EC ((wrd) & TSP_WRD1_ SSEC_MASK) макрос для получения SubSecond из слова WRD1 TSP_WRD2_GET_SE CSSEC ((uint64_t)((wr d) & TSP_WRD2_SECSSE C_ MASK) << TSP_WRD1_ SSEC_LEN) макрос для получ е ни я Second + SubSecond из слова WRD2 TSP_WRD2_GET_SS EC ((wrd) & TSP_WRD2_ SSEC_MASK) макрос для получения SubSecond из слова WRD2 TSP_WRD3_GET_SE C ((uint64_t)((wr d) & TSP_WRD3_SEC_MA SK) << (TSP_WRD1_SSEC_ LEN + TSP_WRD2_ SSEC_LEN + TSP_ WRD2_SEC_LEN)) макрос для получ е ни я Second из слова WRD3 SSEC_MAX (0x7fffffff) мак симально во змо жное зна- чение SubSecond 156 +TSTP_SSEC_TO_NS EC (time > 0 ? ((uint32_ t)((((double)(( time) & SSEC_MA X)) / (1U << TSP_ SSEC_WIDTH)) * TSP_NSEC_PER_ SEC)) : ((uint32_ t)((((double)(( time*(-1)) & SSEC_MA X)) / (1U << TSP_SSEC_ WIDTH)) * TSP_NSEC_ PER_SEC))) перево д SubSecond в н а н ос е- кунды TSTP_SECSSEC_TO _SEC (time > 0 ? (uint32_t)((tim e) >> TSP_SSEC_WIDTH) : (uint32 _t)((time * -1) >> TSP_SSEC_ WIDTH)) получение целых секунд из t_x502_tstptime TSTP_SECSSEC_TO _SEC_DOUBLE (((double)(time )) / (1U << TSP_SSEC_ WIDTH)) перево д в секунды с плавающей запятой из t_x502_tstptime TSTP_SEC_TO_SSE C (((uint64_t)(ti me)) << TSP_SSEC_WIDTH) перево д секунд в t_x502_tstptime 5.2.2 Структура д ля хранения к онтек ст а при обработк е поток а слов на вво д с включенными метк ами времен и Тип: t_x502_tstp_state Описание: Структура для хранения к онтек ст а при об р аб отк е поток а слов на вво д с включенными метк ами вре мени Поле Тип Описание поля wrd uint32_t [4] зна чение слов последней метки времени adc_freq uint32_t частот а АЦП din_freq uint32_t частот а DIN tstp_start_time t_x502_tstptime время первой метки времени tstp_mark_rcvd bool признак, что первая метк а време ни по- лучена cur_wrd uint32_t зна чение текущего обрабатываемого слова processed_wrds uint32_t к ол-во обработ анных слов из поток а adcwrds_after_ tstp uint32_t к ол-во слов АЦП после последней метки времени dinwrds_after_ tstp uint32_t к ол-во слов DIN после последней метки времени 157 +wrds_after_tstp uint32_t общее к ол-во слов после последней мет- ки времени last_tstp_time t_x502_tstptime время последней метки времени 5.2.3 Тип данных для хранени я времени Время хранитс я в се- кундах прошедшее с на чала этой эпо хи (00:00:00 UTC, 1 Январ я 1970 го да) Дробный формат хранения 32.31: 32 целых бит , 31 дробных бит , ст аршие 32 бит а - секунды, младшие 31 бит - доли секунды (SubSecond) = 1 / (1 << 31) секунд Тип: t_x502_tstptime Описание: Тип данных для хранения времени Время хранитс я в секундах про- шедшее с на чала этой эпо хи (00:00:00 UTC, 1 Январ я 1970 го да) Дробный формат хранения 32.31: 32 целых бит , 31 дробных бит , ст аршие 32 бит а - секунды, младшие 31 бит - доли секунды (Su bSec ond) = 1 / (1 << 31) секунд 5.3 Функции для работы с метк ами времен и 5.3.1 Инициализация ts tp_ st a te, в нем хранитс я текущий к он- тек ст для о пераций с метк ами времени из поток а на в во д. Формат: void X502_ts tp_init (t_x502_tstp_state *tstp_state, uint32_t adc_freq, uint32_t din_freq) Описание: Данная функция иниц иализиру ет структуру в к оторой хранитс я к онтек ст д ля работы с метк ами времени Необ х о димо ук азывать на частоту АЦ П и DIN т . к. время для слов между двумя метк ами бу дет счит атьс я в зависимости от частоты. Параметры: tstp_state  Ук азатель на существующую струтуру t_x502_tstp_ state adc_freq  Частот а АЦП din_freq  Частот а DIN 158 +5.3.2 Обработ ать очередное слово wrd из поток а на в во д. Формат: void X502_ts tp_process_wrd (t_x502_tstp_state *tstp_state, uint32_t wrd) Описание: Функция должна быть вызвана тольк о о дин раз и пос л е довательно для к аждого слова полученного из X502_Recv Параметры: tstp_state  Ук аза тель на струтуру t_x502_tstp_state предварительно инициа- лизированную через tstp_init() wrd  Слово из поток а на вво д 5.3.3 Узнать вр емя текущего обработ анного слова Формат: void X502_ts tp_get_curwrd_time (t_x502_tstp_state *tstp_state, t_x502_tstptime *ret) Описание: Узнать время текущег о слова к оторое до этого было обработ ано функцией tstp_pro cess_wrd() Формат времени: 32бит а - секунды, 31 бит сабсекунды = 1 / (1 << 31) секунд Параметры: tstp_state  Ук аза тель на струтуру t_x502_tstp_state предварительно инициа- лизированную через tstp_init() ret  Ук азатель на t_x502_tstptime по к оторому бу дет со хранено расчит анное зна чение времени для текущего слова 5.3.4 Возвращает признак того что ч асы синхронизированы Формат: bool X502_ts tp_get_lock (t_x502_tstp_state *tstp_state) Описание: Возвращает признак захват PTP для текущего обработ анного слова Параметры: tstp_state  Ук аза тель на струтуру t_x502_tstp_state предварительно инициа- лизированную через tstp_init() Возвращаемое зна чени е : true: присутству ет признак захват PTP для текущего обработ анного слова, false: признак захват PTP отсутству е т 159 +FaD  +C8М МIМJ +jEC'МKМL +jFC&МMМN +jHC%МOМP +jSC$МQМR +jVC#МSМT +jXC"МUМV +j[C!МWМX +ГC МYМZ +ГCМ[М +ГCМ]М^ +ГCМ_М` +ГCМaМb +Г CМc• +Г#C•• +Г.C•• +Г1C•• +Г4C•• +ГBC• • + +ГEC• •  +ГGC• • +ГRC•• +ГUC•• +ГXC•• C•• C•• C•• C •• C •• "C ••    =C•  {'B8^  & B'' &  y=B' р ь g*g,g-g.g/g0g1g2g3g4g5g6g7g8g<g:gќхg9g +gg"g$g'g F.FANF З   #+++,+-+.+/+0+1+3+*А°+2  +5+6+7+8+9+=+;+4Е+:+>+?+@+A+B+C+D+E+K+L+M+I+<ИЧ+F+G №7 №8 + +Z +j К+N+O+P+Q+R+S+T+U+V+W+]+JФw+X+Y+[ КҐ' № _Q _Zµ' > O+_+`+a+b+cµµµµµµµµµµ µ +µ µµ+^аЄµ µ } № _S–  № _V _Xµµµµµµюгµµµфxµµ s= sJҐ2 ^ a sµµµµ µ!µ"µ#µ$µ%µ,µ*µGµ&µ . Ґ    _  №  +j  +Г& +Г50 +Г +Г" +Г$ +Г%}$ +Г  К  КW КX КY # # # # Кc КT'[ КZ К К] К_ Кb #  #  #  #  #9ы # # #Ѓ? # # # # # +@§ # # # # # #! #" # #Hк # # # XФ #0 #2 #5 #, #8}  г  Ц#­  Ц$ Ц& Ц'}/ Ц* Ц+ Ц, Ц8 Ц6 Ц  Ц- Ц/ Ц1 Ц2 Ц4 Ц5 Ц: Ц; Ц< Ц= Ц> Ц? Ц@ ЦK Ц7ѕi ЦA ЦC ЦD Ц9 ЦF ЦG ЦI ЦJ ЦM ЦW ЦLЖЌ ЦN ЦP ЦR ЦS ЦU ЦV Ц` ЦXР] ЦY Ц Ц^ Ц_1 +1 ЦaЪ: Цb111111!i1 111111 йЫ1 111}011 hЌ Ќ +Ќ Ќ Ќ ЌЌЌЌЌЌЌЌЌЌЌЌЌ+Ќ ¦ +  +@; +A2bc} { +[­ +]" +^_ +_ã +a +b< +c; +d¹ +es +fç +gÎ +i6 +j +l  +m +ne +oè +pÜ +qþ +s~ +uJ +v„ +w» +xã +z +{F +|? +}ª +~£ +x +€¦ +c +‚† +ƒz +„¡ +…Ö +‡ +ˆ +‰9 +Š8 +‹0 +ŒZ +À +Žü +Y +‘{ +’ð +”- +•  +–W +—y +˜ú +š, +›  +œ¹ +ž! +žì +  +¡# +¢. +£² +¤¦ +¦? +§ˆ +¨{ +© +«* +¬d +­Ä +®Ë +¯— +°¯ +±ã +³n +´¥ +µ¬ +¶ó +¸  +¹ +ºU +» +¼D +½ +¾: +¿b +ÀA +Á¤ +Âõ +Ä8 +Å +Æ +ÆÖ +ÇÅ +ÈÅ +ɹ +Êý +Ì8 +ÍT +Ώ +ÏÁ +Ћ +Ñr +Ò$ +Òß +ÓÞ +Ô¢ +Õ^ +փ +×S +د +Ú +Û- +Ü| +ÝÖ +Þþ +àr +áÍ +âÚ +ã÷}}} +äï +æ; +ç` +èt +éˆ +ê½ +ëó +í3 +î +ï© +ðà +ò< +ó^ +ô  +õE +öG +÷® +ø÷}}} +ú; +üŸ +þ +ÿ8 k  8 í æ & u Œ ã} +} }  ‹ à » G ‡ Û º  3 …  D Џ ф \ No newline at end of file diff --git a/x502api.h b/x502api.h new file mode 100644 index 0000000..b775cb3 --- /dev/null +++ b/x502api.h @@ -0,0 +1,3129 @@ +#ifndef X502API_H +#define X502API_H + + + +#include "lcard_pstdint.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include "Windows.h" + + #define X502_EXPORT(type) type APIENTRY +#else + #ifndef APIENTRY + #define APIENTRY + #endif + + #if __GNUC__ >= 4 + #define X502_EXPORT(type) __attribute__ ((visibility("default"))) type + #else + #define X502_EXPORT(type) type + #endif +#endif + + +/***************************************************************************//** + @addtogroup const_list + @{ + *****************************************************************************/ + +#define E502_DEVICE_NAME "E502" +#define L502_DEVICE_NAME "L502" +#define E16_DEVICE_NAME "E16" +#define LTA37_DEVICE_NAME "LTA37" +#define LTA11_DEVICE_NAME "LTA11" + +/** */ +#define X502_LTABLE_MAX_CH_CNT 256 + +/** E16 */ +#define E16_LTABLE_MAX_CH_CNT 128 + +/** */ +#define X502_ADC_RANGE_CNT 6 +#define E16_ADC_RANGE_CNT 4 +#define LTA11_ADC_RANGE_CNT 4 + +/** */ +#define X502_ADC_COMM_CH_CNT 32 + +/** */ +#define X502_ADC_DIFF_CH_CNT 16 + + +/** */ +#define X502_LCH_AVG_SIZE_MAX 128 +/** */ +#define X502_ADC_FREQ_DIV_MAX (1024*1024) +/** + * E16 E16_REF_FREQ_48000KHZ */ +#define E16_ADC_FREQ_DIV_MAX (0x800000) +#define LTA11_ADC_FREQ_DIV_MAX (0x800000) +/** */ +#define X502_DIN_FREQ_DIV_MAX (1024*1024) +/** + * E16 E16_REF_FREQ_48000KHZ */ +#define E16_DIN_FREQ_DIV_MAX (0x800000) +#define LTA37_DIN_FREQ_DIV_MAX 64 + +/** , + * X502_SetAdcFreq X502_CalcAdcFreq2 f_acq = 0 */ +#define E16_ADC_FREQ_DEFAULT 500000 +#define LTA11_ADC_FREQ_DEFAULT 500000 +#define LTA11_MAX_ADC_FREQ 1000000 + +/** DIN , + * X502_SetDinFreq X502_CalcDinFreq2 f_din = 0 */ +#define E16_DIN_FREQ_DEFAULT 500000 +/** , + * X502_SetOutFreq X502_CalcOutFreq2 f_dout = 0 */ +#define E16_OUT_FREQ_DEFAULT 500000 + + +/** */ +#define X502_OUT_FREQ_DIV_MIN 2 +/** */ +#define X502_OUT_FREQ_DIV_MAX 1024 +/** + * E16 E16_REF_FREQ_48000KHZ */ +#define E16_OUT_FREQ_DIV_MAX 0x8000 +/** ( + L-502 0.5) */ +#define X502_OUT_FREQ_DIV_DEFAULT 2 + +/** + #X502_OUT_FREQ_REF_LF_VAL */ +#define X502_OUT_FREQ_DIV_MIN_REF_LF 1 +/** , + #X502_OUT_FREQ_DIV_MIN_REF_LF */ +#define X502_OUT_FREQ_REF_LF_VAL 700000 + + +/** */ +#define X502_ADC_INTERFRAME_DELAY_MAX (0x1FFFFF) +/** E16*/ +#define E16_ADC_INTERFRAME_DELAY_MAX (0xFFFF) + +/** BlackFin*/ +#define X502_BF_CMD_DEFAULT_TOUT 500 + +/** , */ +#define X502_ADC_SCALE_CODE_MAX 6000000 +/** , */ +#define E16_ADC_SCALE_CODE_MAX (0x80 * 0x7fff) +/** , */ +#ifndef LTA11_ADC_SCALE_CODE_MAX + #define LTA11_ADC_SCALE_CODE_MAX (0x80 * 0x7fff) +#endif +/** , */ +#define X502_DAC_SCALE_CODE_MAX 30000 +#define E16_DAC_SCALE_CODE_MAX 0x7fff +#define LTA37_DAC_SCALE_CODE_MAX 0x650000 + +/** */ +#define X502_DEVNAME_SIZE 32 +/** */ +#define X502_SERIAL_SIZE 32 +/** board implementation */ +#define X502_IMPLEMENTATION_SIZE 16 +/** */ +#define X502_LOCATION_STR_SIZE 64 +/** MAC- Ethernet */ +#define X502_MAC_ADDR_SIZE 6 +/** */ +#define X502_INSTANCE_NAME_SIZE 64 +/** */ +#define X502_PASSWORD_SIZE 32 + +/** */ +#define X502_EXT_REF_FREQ_MAX 1500000 + +/** E502-P1 */ +#define E502_P1_EXT_REF_FREQ_MAX 2000000 + + +/** Flash- */ +#define X502_FLASH_USER_SIZE 0x100000 + +/** BlackFin */ +#define X502_BF_REQ_TOUT 500 + + +/** */ +#define X502_DAC_RANGE 5. +#define E16_DAC_RANGE 10. + +/** 1:1 1:10 */ +#define LTA37_DAC_RANGE20V 20. +#define LTA37_DAC_RANGE2V 2. + +#define LTA37_DACRANGE_CNT 2 + +/** */ +#define X502_DAC_CH_CNT 2 +#ifndef LTA37_DAC_CH_CNT + #define LTA37_DAC_CH_CNT 10 +#endif + + +/** */ +#define X502_DAC_CH_CNT_MAX 20 + +/** */ +#define X502_DOUT_LINES_CNT 16 + + +/** , , */ +#define X502_STREAM_IN_MSG_OVERFLOW 0x01010000 + + +/** #t_x502_devrec. , + ( + ) */ +#define X502_DEVREC_SIGN 0x4C524543 + + +/** */ +typedef enum { + /** */ + X502_ERR_OK = 0, + /** */ + X502_ERR_INVALID_HANDLE = -1, + /** */ + X502_ERR_MEMORY_ALLOC = -2, + /** */ + X502_ERR_ALREADY_OPENED = -3, + /** */ + X502_ERR_DEVICE_NOT_FOUND = -4, + /** ( - , + ) */ + X502_ERR_DEVICE_ACCESS_DENIED = -5, + /** */ + X502_ERR_DEVICE_OPEN = -6, + /** */ + X502_ERR_INVALID_POINTER = -7, + /** */ + X502_ERR_STREAM_IS_RUNNING = -8, + /** , tcp- errno */ + X502_ERR_RECV = -9, + /** */ + X502_ERR_SEND = -10, + /** */ + X502_ERR_STREAM_OVERFLOW = -11, + /** */ + X502_ERR_UNSUP_STREAM_MSG = -12, + /** */ + X502_ERR_MUTEX_CREATE = -13, + /** */ + X502_ERR_MUTEX_INVALID_HANDLE = -14, + /** */ + X502_ERR_MUTEX_LOCK_TOUT = -15, + /** */ + X502_ERR_MUTEX_RELEASE = -16, + /** */ + X502_ERR_INSUFFICIENT_SYSTEM_RESOURCES= -17, + /** */ + X502_ERR_NOT_IMPLEMENTED = -18, + /** */ + X502_ERR_INSUFFICIENT_ARRAY_SIZE = -19, + /** FPGA */ + X502_ERR_FPGA_REG_READ = -20, + /** FPGA */ + X502_ERR_FPGA_REG_WRITE = -21, + /** */ + X502_ERR_STREAM_IS_NOT_RUNNING = -22, + /** */ + X502_ERR_INTERFACE_RELEASE = -23, + /** */ + X502_ERR_THREAD_START = -24, + /** */ + X502_ERR_THREAD_STOP = -25, + /** */ + X502_ERR_DEVICE_DISCONNECTED = -26, + /** */ + X502_ERR_IOCTL_INVALID_RESP_SIZE = -27, + /** */ + X502_ERR_INVALID_DEVICE = -28, + /** */ + X502_ERR_INVALID_DEVICE_RECORD = -29, + /** */ + X502_ERR_INVALID_CONFIG_HANDLE = -30, + /** */ + X502_ERR_DEVICE_NOT_OPENED = -31, + /** */ + X502_ERR_INVALID_OP_FOR_IFACE = -32, + /** */ + X502_ERR_FPGA_NOT_LOADED = -33, + /** USB- */ + X502_ERR_INVALID_USB_CONFIGURATION = -34, + /** */ + X502_ERR_INVALID_SVC_BROWSE_HANDLE = -35, + /** */ + X502_ERR_INVALID_SVC_RECORD_HANDLE = -36, + /** */ + X502_ERR_DNSSD_NOT_RUNNING = -37, + /** */ + X502_ERR_DNSSD_COMMUNICATION = -38, + /** */ + X502_ERR_SVC_RESOLVE_TIMEOUT = -39, + /** */ + X502_ERR_INSTANCE_NAME_ENCODING = -40, + /** */ + X502_ERR_INSTANCE_MISMATCH = -41, + /** */ + X502_ERR_NOT_SUP_BY_FIRMWARE = -42, + /** */ + X502_ERR_NOT_SUP_BY_DRIVER = -43, + /** */ + X502_ERR_OUT_CYCLE_SETUP_TOUT = -44, + /** */ + X502_ERR_UNKNOWN_FEATURE_CODE = -45, + + + /** */ + X502_ERR_INVALID_LTABLE_SIZE = -102, + /** */ + X502_ERR_INVALID_LCH_NUMBER = -103, + /** */ + X502_ERR_INVALID_LCH_RANGE = -104, + /** */ + X502_ERR_INVALID_LCH_MODE = -105, + /** */ + X502_ERR_INVALID_LCH_PHY_NUMBER = -106, + /** */ + X502_ERR_INVALID_LCH_AVG_SIZE = -107, + /** */ + X502_ERR_INVALID_ADC_FREQ_DIV = -108, + /** */ + X502_ERR_INVALID_DIN_FREQ_DIV = -109, + /** */ + X502_ERR_INVALID_MODE = -110, + /** */ + X502_ERR_INVALID_DAC_CHANNEL = -111, + /** */ + X502_ERR_INVALID_REF_FREQ = -112, + /** */ + X502_ERR_INVALID_INTERFRAME_DELAY = -113, + /** */ + X502_ERR_INVALID_SYNC_MODE = -114, + /** */ + X502_ERR_INVALID_STREAM_CH = -115, + /** */ + X502_ERR_INVALID_OUT_FREQ_DIV = -116, + + /** */ + X502_ERR_REF_FREQ_NOT_LOCKED = -131, + /** */ + X502_ERR_IOCTL_FAILD = -132, + /** */ + X502_ERR_IOCTL_TIMEOUT = -133, + /** */ + X502_ERR_GET_INFO = -134, + /** */ + X502_ERR_DIG_IN_NOT_RDY = -135, + /** */ + X502_ERR_RECV_INSUFFICIENT_WORDS = -136, + /** , , */ + X502_ERR_DAC_NOT_PRESENT = -137, + /** */ + X502_ERR_SEND_INSUFFICIENT_WORDS = -138, + /** */ + X502_ERR_NO_CMD_RESPONSE = -139, + + /** */ + X502_ERR_PROC_INVALID_CH_NUM = -140, + /** */ + X502_ERR_PROC_INVALID_CH_RANGE = -141, + /** Flash- */ + X502_ERR_FLASH_INVALID_ADDR = -142, + /** Flash- */ + X502_ERR_FLASH_INVALID_SIZE = -143, + /** Flash- */ + X502_ERR_FLASH_WRITE_TOUT = -144, + /** Flash- */ + X502_ERR_FLASH_ERASE_TOUT = -145, + /** Flash- 4 */ + X502_ERR_FLASH_SECTOR_BOUNDARY = -146, + + /** */ + X502_ERR_SOCKET_OPEN = -147, + /** */ + X502_ERR_CONNECTION_TOUT = -148, + /** */ + X502_ERR_CONNECTION_CLOSED_BY_DEV = -149, + /** */ + X502_ERR_SOCKET_SET_BUF_SIZE = -150, + /** */ + X502_ERR_NO_DATA_CONNECTION = -151, + /** */ + X502_ERR_NO_STREAM_END_MSG = -152, + /** */ + X502_ERR_CONNECTION_RESET = -153, + /** */ + X502_ERR_HOST_UNREACHABLE = -154, + /** TCP-, + + ( TCP ) */ + X502_ERR_TCP_CONNECTION_ERROR = -155, + + + + + /** BlackFin */ + X502_ERR_LDR_FILE_OPEN = -180, + /** BlackFin */ + X502_ERR_LDR_FILE_READ = -181, + /** BlackFin */ + X502_ERR_LDR_FILE_FORMAT = -182, + /** LDR-, + BlackFin HDMA */ + X502_ERR_LDR_FILE_UNSUP_FEATURE = -183, + /** BlackFin */ + X502_ERR_LDR_FILE_UNSUP_STARTUP_ADDR = -184, + /** / BlackFin */ + X502_ERR_BF_REQ_TIMEOUT = -185, + /** BlackFin */ + X502_ERR_BF_CMD_IN_PROGRESS = -186, + /** BlackFin */ + X502_ERR_BF_CMD_TIMEOUT = -187, + /** BlackFin */ + X502_ERR_BF_CMD_RETURN_INSUF_DATA = -188, + /** BlackFin */ + X502_ERR_BF_LOAD_RDY_TOUT = -189, + /** + */ + X502_ERR_BF_NOT_PRESENT = -190, + /** BlackFin HDMA */ + X502_ERR_BF_INVALID_ADDR = -191, + /** , BlackFin */ + X502_ERR_BF_INVALID_CMD_DATA_SIZE = -192 +} t_x502_errs; + + +/** */ +typedef enum { + X502_IFACE_UNKNOWN = 0, /**< */ + X502_IFACE_USB = 1, /**< USB */ + X502_IFACE_ETH = 2, /**< Ethernet TCP/IP */ + X502_IFACE_PCI = 3 /**< PCI/PCIe */ +} t_x502_iface; + +/** , */ +typedef enum { + /** , , + */ + X502_GETDEVS_FLAGS_ONLY_NOT_OPENED = 1 +} t_x502_getdevs_flags; + + + +/** @brief + + . + Ȕ + X502_AsyncOutDig() X502_PrepareData() .*/ +typedef enum { + X502_DIGOUT_WORD_DIS_H = 0x00020000, /**< ( ) + */ + X502_DIGOUT_WORD_DIS_L = 0x00010000, /**< + */ + E16_DIGOUT_WORD_DIS = 0x00030000 /**< E16 + */ +} t_x502_digout_word_flags; + +/** */ +typedef enum { + E16_REF_FREQ_48000KHZ = 48000000, /**< 48 E16 */ +/** LTA, lta_api */ +#ifndef LTA11_REF_FREQ_30000KHZ + #define LTA11_REF_FREQ_30000KHZ 30000000 /**< 30 LTA11 */ +#endif +#ifndef LTA37_REF_FREQ_24576KHZ + #define LTA37_REF_FREQ_24576KHZ 24576000 /**< 24,576 LTA37 */ +#endif + X502_REF_FREQ_2000KHZ = 2000000, /**< 2 */ + X502_REF_FREQ_1500KHZ = 1500000 /**< 1.5 */ +} t_x502_ref_freq; + + +/** io_mode io_hard */ +typedef enum { + X502_MODE_REF_FREQ_2000 = 0, /**< 2 */ + X502_MODE_REF_FREQ_1500 = 2, /**< 1.5 */ + E16_MODE_REF_FREQ_48000 = 3 /**< 48 E16*/ +} t_x502_io_mode; + +/** */ +typedef enum { + X502_ADC_RANGE_10 = 0, /**< +/-10V */ + X502_ADC_RANGE_5 = 1, /**< +/-5V */ + X502_ADC_RANGE_2 = 2, /**< +/-2V */ + X502_ADC_RANGE_1 = 3, /**< +/-1V */ + X502_ADC_RANGE_05 = 4, /**< +/-0.5V */ + X502_ADC_RANGE_02 = 5 /**< +/-0.2V */ +} t_x502_adc_range; + +/** E16 */ +typedef enum { + E16_ADC_RANGE_10000 = 0, /**< +/-10V */ + E16_ADC_RANGE_2500 = 1, /**< +/-2.5V */ + E16_ADC_RANGE_625 = 2, /**< +/-0.625V */ + E16_ADC_RANGE_156 = 3, /**< +/-0.156V */ +} t_e16_adc_range; + +/** LTA11 */ +#ifndef LTA37_DAC_RANGE_20000 + #define LTA11_ADC_RANGE_10000 0 /**< +/-10V */ +#endif +#ifndef LTA11_ADC_RANGE_2500 + #define LTA11_ADC_RANGE_2500 1 /**< +/-2.5V */ +#endif +#ifndef LTA11_ADC_RANGE_625 + #define LTA11_ADC_RANGE_625 2 /**< +/-0.625V */ +#endif +#ifndef LTA11_ADC_RANGE_156 + #define LTA11_ADC_RANGE_156 3 /**< +/-0.156V */ +#endif + +typedef enum { + X502_DAC_RANGE_5000 = 0, /**< +/-5V x502 */ + E16_DAC_RANGE_10000 = 0, /**< +/-10V E16 */ +/** LTA, lta_api */ +#ifndef LTA37_DAC_RANGE_20000 + #define LTA37_DAC_RANGE_20000 0 /**< 1:10 +/-20V LTA37 */ +#endif +#ifndef LTA37_DAC_RANGE_2000 + #define LTA37_DAC_RANGE_2000 1 /**< 1:1 +/-2V LTA37 */ +#endif +} t_x502devs_dac_range; + +/** */ +typedef enum { + X502_LCH_MODE_COMM = 0, /**< */ + X502_LCH_MODE_DIFF = 1, /**< */ + X502_LCH_MODE_ZERO = 2 /**< */ +} t_x502_lch_mode; + +/** @brief + + + - */ +typedef enum { + X502_SYNC_INTERNAL = 0, /**< */ + X502_SYNC_EXTERNAL_MASTER = 1, /**< (START_IN/CONV_IN X502_SetSyncStartMode/X502_SetSyncMode) */ + X502_SYNC_DI_SYN1_RISE = 2, /**< DI_SYN1 */ + X502_SYNC_DI_SYN1_FALL = 3, /**< DI_SYN1 */ + X502_SYNC_DI_SYN2_RISE = 6, /**< DI_SYN2 */ + X502_SYNC_DI_SYN2_FALL = 7, /**< DI_SYN2 */ + /** E16! + TRIG INT + E16_MODE_TRIG_OUTPUT E16_MODE_INT_OUTPUT + */ + E16_SYNC_TRIG_RISE = 2, /**< TRIG */ + E16_SYNC_TRIG_FALL = 3, /**< TRIG */ + E16_SYNC_INT_RISE = 6, /**< INT */ + E16_SYNC_INT_FALL = 7, /**< INT */ + /** , E16*/ + E16_SYNC_ADC_ABOVE_LEVEL = 8, /**< */ + E16_SYNC_ADC_BELOW_LEVEL = 9, /**< */ + E16_SYNC_ADC_EDGE_RISE = 10, /**< */ + E16_SYNC_ADC_EDGE_FALL = 11, /**< */ + +/** LTA, lta_api */ +#ifndef LTA37_SYNC_INTERNAL + #define LTA37_SYNC_INTERNAL 0 /**< */ +#endif +#ifndef LTA37_SYNC_DI2_RISE + #define LTA37_SYNC_DI2_RISE 1 /**< DI2 */ +#endif +#ifndef LTA37_SYNC_DI2_FALL + #define LTA37_SYNC_DI2_FALL 2 /**< DI2 */ +#endif + +#ifndef LTA37_DO8_START_OUT + #define LTA37_DO8_START_OUT 4 /**< LTA37: DO8 */ +#endif + +#ifndef LTA11_SYNC_INTERNAL + #define LTA11_SYNC_INTERNAL 0 /**< */ +#endif +#ifndef LTA11_SYNC_EXT_RISE + #define LTA11_SYNC_EXT_RISE 2 /**< Sync/Start */ +#endif +#ifndef LTA11_SYNC_EXT_FALL + #define LTA11_SYNC_EXT_FALL 3 /**< Sync/Start */ +#endif +#ifndef LTA11_SYNC_EXT_HIGH + #define LTA11_SYNC_EXT_HIGH 6 /**< Start */ +#endif +#ifndef LTA11_SYNC_EXT_LOW + #define LTA11_SYNC_EXT_LOW 7 /**< Start */ +#endif + /** , LTA11*/ +#ifndef LTA11_SYNC_ADC_ABOVE_LEVEL + #define LTA11_SYNC_ADC_ABOVE_LEVEL 8 /**< */ +#endif +#ifndef LTA11_SYNC_ADC_BELOW_LEVEL + #define LTA11_SYNC_ADC_BELOW_LEVEL 9 /**< */ +#endif +#ifndef LTA11_SYNC_ADC_EDGE_RISE + #define LTA11_SYNC_ADC_EDGE_RISE 10 /**< */ +#endif +#ifndef LTA11_SYNC_ADC_EDGE_FALL + #define LTA11_SYNC_ADC_EDGE_FALL 11 /**< */ +#endif +} t_x502_sync_mode; + +/** , */ +typedef enum { + /** , */ + X502_PROC_FLAGS_VOLT = 0x00000001, + /** , + . + BlackFin + . */ + X502_PROC_FLAGS_DONT_CHECK_CH = 0x00010000 +} t_x502_proc_flags; + + +/** */ +typedef enum { + X502_STREAM_ADC = 0x01, /**< */ + X502_STREAM_DIN = 0x02, /**< */ + X502_STREAM_DAC1 = 0x10, /**< */ + X502_STREAM_DAC2 = 0x20, /**< */ + X502_STREAM_DOUT = 0x40, /**< */ + /** , */ + X502_STREAM_ALL_IN = X502_STREAM_ADC | X502_STREAM_DIN, + /** , */ + X502_STREAM_ALL_OUT = X502_STREAM_DAC1 | X502_STREAM_DAC2 | X502_STREAM_DOUT +} t_x502_streams; + +/** , */ +typedef enum { + X502_STREAM_OUT_WORD_TYPE_DOUT = 0x0, /**< */ + X502_STREAM_OUT_WORD_TYPE_DAC1 = 0x40000000, /**< 1- */ + X502_STREAM_OUT_WORD_TYPE_DAC2 = 0x80000000, /**< 2- */ +/** LTA, lta_api */ +#ifndef LTA37_STREAM_OUT_WORD_TYPE_DOUT + #define LTA37_STREAM_OUT_WORD_TYPE_DOUT (12 << 24) /**< LTA37*/ +#endif +} t_x502_stream_out_wrd_type; + +/** */ +typedef enum { + X502_MODE_FPGA = 0, /**< + BlackFin */ + X502_MODE_DSP = 1, /**< + , + */ + X502_MODE_DEBUG = 2 /**< */ +} t_x502_mode; + +#define X502_DAC_CH(ch, range, ch_cnt) ((ch_cnt * range) + ch) +#ifndef LTA37_DAC_CH + #define LTA37_DAC_CH(ch, range) X502_DAC_CH(ch, range, LTA37_DAC_CH_CNT) +#endif + +/** @brief + + X502_AsyncOutDac() */ +typedef enum { + X502_DAC_CH1 = 0, /**< */ + X502_DAC_CH2 = 1, /**< */ + +/** LTA, lta_api */ +#ifndef LTA37_DAC_CH1 + #define LTA37_DAC_CH1 0 /**< 1:1 1 LTA37 */ +#endif +#ifndef LTA37_DAC_CH2 + #define LTA37_DAC_CH2 1 /**< 1:1 2 LTA37 */ +#endif +#ifndef LTA37_DAC_CH3 + #define LTA37_DAC_CH3 2 /**< 1:1 3 LTA37 */ +#endif +#ifndef LTA37_DAC_CH4 + #define LTA37_DAC_CH4 3 /**< 1:1 4 LTA37 */ +#endif +#ifndef LTA37_DAC_CH5 + #define LTA37_DAC_CH5 4 /**< 1:1 5 LTA37 */ +#endif +#ifndef LTA37_DAC_CH6 + #define LTA37_DAC_CH6 5 /**< 1:1 6 LTA37 */ +#endif +#ifndef LTA37_DAC_CH7 + #define LTA37_DAC_CH7 6 /**< 1:1 7 LTA37 */ +#endif +#ifndef LTA37_DAC_CH8 + #define LTA37_DAC_CH8 7 /**< 1:1 8 LTA37 */ +#endif +#ifndef LTA37_DAC_CH9 + #define LTA37_DAC_CH9 8 /**< 1:1 9 LTA37 */ +#endif +#ifndef LTA37_DAC_CH10 + #define LTA37_DAC_CH10 9 /**< 1:1 10 LTA37 */ +#endif +#ifndef LTA37_DAC_CH1_10 + #define LTA37_DAC_CH1_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 1 LTA37 */ +#endif +#ifndef LTA37_DAC_CH2_10 + #define LTA37_DAC_CH2_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 2 LTA37 */ +#endif +#ifndef LTA37_DAC_CH3_10 + #define LTA37_DAC_CH3_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 3 LTA37 */ +#endif +#ifndef LTA37_DAC_CH4_10 + #define LTA37_DAC_CH4_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 4 LTA37 */ +#endif +#ifndef LTA37_DAC_CH5_10 + #define LTA37_DAC_CH5_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 5 LTA37 */ +#endif +#ifndef LTA37_DAC_CH6_10 + #define LTA37_DAC_CH6_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 6 LTA37 */ +#endif +#ifndef LTA37_DAC_CH7_10 + #define LTA37_DAC_CH7_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 7 LTA37 */ +#endif +#ifndef LTA37_DAC_CH8_10 + #define LTA37_DAC_CH8_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 8 LTA37 */ +#endif +#ifndef LTA37_DAC_CH9_10 + #define LTA37_DAC_CH9_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 9 LTA37 */ +#endif +#ifndef LTA37_DAC_CH10_10 + #define LTA37_DAC_CH10_10 LTA37_DAC_CH(LTA37_DAC_CH1, LTA37_DAC_RANGE_2000) /**< 1:10 10 LTA37 */ +#endif +} t_x502_dac_ch; + +/** @brief , + + , X502_AsyncOutDac() + X502_PrepareData(), , + */ +typedef enum { + /** , + . , , + */ + X502_DAC_FLAGS_VOLT = 0x0001, + /** , + . */ + X502_DAC_FLAGS_CALIBR = 0x0002 +} t_x502_dacout_flags; + + + +/** */ +typedef enum { + X502_STREAM_CH_IN = 0, /**< */ + X502_STREAM_CH_OUT = 1, /**< */ + X502_STREAM_CH_CNT +} t_x502_stream_ch; + + +/** @brief , + + , + . . */ +typedef enum { + X502_PULLUPS_DI_H = 0x01, /**< ( L502) */ + X502_PULLUPS_DI_L = 0x02, /**< ( L502) */ + X502_PULLUPS_DI_SYN1 = 0x04, /**< SYN1 */ + X502_PULLUPS_DI_SYN2 = 0x08, /**< SYN2 */ + X502_PULLDOWN_CONV_IN = 0x10, /**< 0 + CONV_IN ( E502) */ + X502_PULLDOWN_START_IN = 0x20, /**< 0 + START_IN ( E502) */ + + E16_MODE_TRIG_OUTPUT = 0x04, /**< E16: TRIG , */ + E16_MODE_INT_OUTPUT = 0x08, /**< E16: INT , */ + E16_MODE_TRIG_START_OUTPUT = 0x10, /**< E16: START TRIG, CONV (TRIG ) */ + E16_MODE_INT_START_OUTPUT = 0x20, /**< E16: START INT, CONV (INT ) */ + E16_MODE_RELAY_ON = 0x40, /**< E16: , digital: +15, -15, : +3, GND, */ + E16_MODE_RELAY_OFF = 0x80, /**< E16: */ + + E16_MODE_PWM_MANUAL = 0x100, /**< E16: , + API Ethernet USB */ + E16_MODE_PWM_ON = 0x200, /**< E16: . E16_MODE_PWM_MANUAL, , */ + +/** LTA, lta_api */ +#ifndef LTA37_RELAY_12_ON + #define LTA37_RELAY_12_ON (1 << 0) /**< LTA37: 1, 2 */ +#endif +#ifndef LTA37_RELAY_34_ON + #define LTA37_RELAY_34_ON (1 << 1) /**< LTA37: 3, 4 */ +#endif +#ifndef LTA37_RELAY_56_ON + #define LTA37_RELAY_56_ON (1 << 2) /**< LTA37: 5, 6 */ +#endif +#ifndef LTA37_RELAY_78_ON + #define LTA37_RELAY_78_ON (1 << 3) /**< LTA37: 7, 8 */ +#endif +#ifndef LTA37_RELAY_9A_ON + #define LTA37_RELAY_9A_ON (1 << 4) /**< LTA37: 9, 10 */ + +#endif +#ifndef LTA37_RELAY_ALL_CH_ON + #define LTA37_RELAY_ALL_CH_ON (LTA37_RELAY_12_ON | LTA37_RELAY_34_ON | LTA37_RELAY_56_ON | LTA37_RELAY_78_ON | LTA37_RELAY_9A_ON) + /**< LTA37: */ +#endif +#ifndef LTA11_MODE_PTP_SYNC + #define LTA11_MODE_PTP_SYNC 0x04 /**< LTA11: PTP */ +#endif + +} t_x502_pullups; + + +/** , */ +typedef enum { + /** */ + X502_DEVFLAGS_DAC_PRESENT = 0x00000001, + /** */ + X502_DEVFLAGS_GAL_PRESENT = 0x00000002, + /** BlackFin */ + X502_DEVFLAGS_BF_PRESENT = 0x00000004, + /** 3 , / (0 --- ADSP-BF523) */ + X502_DEVFLAGS_PROC_TYPE = 0x00000038, + /** 2 , (0 --- AD5542AARUZ, 1 --- DAC8581IPW) */ + X502_DEVFLAGS_DAC_TYPE = 0x000000C0, + + /** , USB */ + X502_DEVFLAGS_IFACE_SUPPORT_USB = 0x00000100, + /** , Ethernet */ + X502_DEVFLAGS_IFACE_SUPPORT_ETH = 0x00000200, + /** , PCI/PCI-Express */ + X502_DEVFLAGS_IFACE_SUPPORT_PCI = 0x00000400, + + /** , */ + X502_DEVFLAGS_INDUSTRIAL = 0x00008000, + + /** , Flash- */ + X502_DEVFLAGS_FLASH_DATA_VALID = 0x00010000, + /** , Flash- + */ + X502_DEVFLAGS_FLASH_ADC_CALIBR_VALID = 0x00020000, + /** , Flash- + */ + X502_DEVFLAGS_FLASH_DAC_CALIBR_VALID = 0x00040000, + X502_DEVFLAGS_FLASH_AFC_CALIBR_VALID = 0x00080000, + + /** , */ + X502_DEVFLAGS_FPGA_LOADED = 0x00800000, + /** , ( t_x502_devrec) */ + X502_DEVFLAGS_DEVREC_OPENED = 0x01000000, + /** , GD32 */ + X502_DEVFLAGS_FPGA_AWAITING_GD32 = 0x02000000, + /** , GD32 E502-P1 */ + X502_DEVFLAGS_GD_PRESENT = 0x02000000 +} t_x502_dev_flags; + +/** @brief + + location #t_x502_devrec */ +typedef enum { + /** */ + X502_LOCATION_TYPE_NONE = 0, + /** */ + X502_LOCATION_TYPE_ADDR = 1, + /** */ + X502_LOCATION_TYPE_INSTANCE_NAME = 2 +} t_x502_location_type; + + +/** @brief + + X502_OutCycleSetup() X502_OutCycleStop() */ +typedef enum { + /** , + . + ( 256 , + ), + */ + X502_OUT_CYCLE_FLAGS_FORCE = 0x01, + /** , + ( X502_OutCycleSetup()) + ( X502_OutCycleStop()). + , . + + + ( + #X502_OUT_CYCLE_FLAGS_FORCE). + X502_OutCycleCheckSetupDone(). + , + X502_OutCycleCheckSetupDone(), . */ + X502_OUT_CYCLE_FLAGS_WAIT_DONE = 0x02 +} t_x502_out_cycle_flags; + + + +/** @brief + + , + , .. */ +typedef enum { + /** , #X502_OUT_FREQ_DIV_DEFAULT */ + X502_FEATURE_OUT_FREQ_DIV = 1, + /** X502_OutGetStatusFlags() */ + X502_FEATURE_OUT_STATUS_FLAGS = 2 +} t_x502_features; + +/** */ +typedef enum { + /** , */ + X502_OUT_STATUS_FLAG_BUF_IS_EMPTY = 0x01, + /** , + - + X502_OutGetStatusFlags() ( , ) */ + X502_OUT_STATUS_FLAG_BUF_WAS_EMPTY = 0x02 +} t_x502_out_status_flags; + + +/** */ +typedef enum { + X502_PARAM_UNKNOWN = 0, /**< */ + LTA37_WRITE_CTRL2_REG = 1, /**< */ +} t_x502_params; + +/** @} */ + + +/***************************************************************************//** + @addtogroup type_list + @{ + *****************************************************************************/ + +/** @brief + + , + . , + , + X502_OpenByDevRecord() */ +typedef struct st_x502_devrec_inptr t_x502_devrec_inptr; + +/** @brief + + , , */ +typedef struct { + uint32_t sign; /**< . + ( - ), + #X502_DEVREC_SIGN) */ + char devname[X502_DEVNAME_SIZE]; /**< */ + char serial[X502_SERIAL_SIZE]; /**< */ + char location[X502_LOCATION_STR_SIZE]; /**< ( ) */ + uint32_t flags; /**< #t_x502_dev_flags, */ + uint8_t iface; /**< , */ + uint8_t location_type; /**< , location + ( #t_x502_location_type) */ + char res[122]; /**< */ + t_x502_devrec_inptr* internal; /**< + , + */ +} t_x502_devrec; + + +/** @brief + + , + . + , + . + . + X502_Create() + X502_Free(). */ +typedef struct st_x502* t_x502_hnd; + +/** @brief + + , + . */ +typedef char (*t_x502_serial_list)[X502_SERIAL_SIZE]; + +/** @brief . + + + . + (val - offs) * k, val - */ +typedef struct { + double offs; /**< */ + double k; /**< */ +} t_x502_cbr_coef; + +/** @brief + + , */ +typedef struct { + double Fd; /**< , . */ + double SigFreq; /**< , . */ + /** + * @fieldref{TLTR35_AFC_COEF,SigFreq} + * @fieldref{TLTR35_AFC_COEF,Fd} . */ + double K[X502_DAC_CH_CNT_MAX]; +} t_x502_afc_coef; + +/** @brief + + , , + L-502/E-502 */ +typedef struct { + /** */ + t_x502_cbr_coef adc[X502_ADC_RANGE_CNT]; + /** */ + t_x502_cbr_coef dac[X502_DAC_CH_CNT_MAX]; + /** LTA37 */ + t_x502_afc_coef afc_coef; +} t_x502_cbr; + +/** @brief L-502/E-502 + + , L-502/E-502, + + ! ! + ! +*/ +typedef struct { + char name[X502_DEVNAME_SIZE]; /**< ("L502" "E502" "E16") */ + char serial[X502_SERIAL_SIZE]; /**< */ + + uint32_t devflags; /**< #t_x502_dev_flags, + */ + uint16_t fpga_ver; /**< ( - , - ) */ + uint8_t plda_ver; /**< , */ + uint8_t board_rev; /**< */ + uint32_t mcu_firmware_ver; /**< Cortex-M4. E-502 */ + uint32_t flash_size; /**< flash- */ + uint8_t factory_mac[X502_MAC_ADDR_SIZE]; /**< MAC- --- + Ethernet- */ + t_x502_cbr cbr; /**< ( Flash-) */ +} t_x502_info; + +/** @} */ + + +/** @addtogroup func_list + @{ **/ + +/***************************************************************************//** + @addtogroup func_hnd + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + , E-502 L-502. + + . + @return NULL , - +*******************************************************************************/ +X502_EXPORT(t_x502_hnd) X502_Create(void); + +/***************************************************************************//** + @brief + + , X502_Create(). + , + ! + @param[in] hnd + @return +*******************************************************************************/ +X502_EXPORT(int32_t) X502_Free(t_x502_hnd hnd); +/** @} */ + + + + + + + +/***************************************************************************//** + @addtogroup func_devrec + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + E-502 L-502 . + , + . + ( ) + . + + @param[in] hnd . + @param[in] devrec , + + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_OpenByDevRecord(t_x502_hnd hnd, const t_x502_devrec *devrec); + +/***************************************************************************//** + @brief + + , + , . + + , + . + X502_OpenByDevRecord() + , . + ( + , 1). + + @param[in] list + , () . + @param[in] size + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_FreeDevRecordList(t_x502_devrec *list, uint32_t size); + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_open + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + E-502/L-502, + ( ). + . + X502_Free(). + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_Close(t_x502_hnd hnd); + + +/***************************************************************************//** + @brief , + + , . + , #X502_ERR_OK. , + #X502_ERR_DEVICE_NOT_OPENED. + + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_IsOpened(t_x502_hnd hnd); + + + +/***************************************************************************//** + @brief + + L-502/E-502, . + ! ( api) + , + (x502api.h == x502api.dll)! + @param[in] hnd . + @param[out] info ( #t_x502_info). + @return . +*******************************************************************************/ +#ifdef _WIN32 + #pragma deprecated(X502_GetDevInfo) +#else + __attribute__((__deprecated__)) +#endif +X502_EXPORT(int32_t) X502_GetDevInfo(t_x502_hnd hnd, t_x502_info* info); + +/***************************************************************************//** + @brief + + L-502/E-502, . + ! ( api) + , + (x502api.h == x502api.dll)! + @param[in] hnd . + @param[out] info ( #t_x502_info). + @param[in] size sizeof(t_x502_info). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetDevInfo2(t_x502_hnd hnd, t_x502_info* info, uint32_t size); + +/** @} */ + +/***************************************************************************//** + @addtogroup func_config + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + ( + X502_SetXXX) . + . + @param[in] hnd . + @param[in] flags ( - 0). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_Configure(t_x502_hnd hnd, uint32_t flags); + + +/***************************************************************************//** + @brief + + + . + @param[in] hnd . + @param[in] lch . + ( 0 #X502_LTABLE_MAX_CH_CNT-1 #E16_LTABLE_MAX_CH_CNT-1 E16) + @param[in] phy_ch , 0 + (0-15 , + 0-31 ) + @param[in] mode ( #t_x502_lch_mode) + @param[in] range ( #t_x502_adc_range) + @param[in] avg ( E16). + , + . + 1 ( ) + #X502_LCH_AVG_SIZE_MAX. + + , + @return . +*******************************************************************************/ +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); + + +/***************************************************************************//** + @brief E16 + + : + double ranges[] = {10, 2.5, 0.625, 0.15625}; + + @param[in] ranges_len + @return double ranges_len NULL . +*******************************************************************************/ +X502_EXPORT(double const*) E16_GetAdcRanges(uint32_t *ranges_len); + +/***************************************************************************//** + @brief E502 + + : + double ranges[] = {10., 5., 2., 1., 0.5, 0.2}; + + @param[in] ranges_len + @return double ranges_len NULL . +*******************************************************************************/ +X502_EXPORT(double const*) E502_GetAdcRanges(uint32_t *ranges_len); + +/***************************************************************************//** + @brief + + E16: + double ranges[] = {10, 2.5, 0.625, 0.15625}; + E502: + double ranges[] = {10., 5., 2., 1., 0.5, 0.2}; + + @param[in] hnd . + @param[in] ranges_len + @return double ranges_len NULL . +*******************************************************************************/ +X502_EXPORT(double const*) X502_GetAdcRanges(t_x502_hnd hnd, uint32_t *ranges_len); + +/***************************************************************************//** + @brief + + . + @param[in] hnd + @param[in] lch_cnt + ( 1 #X502_LTABLE_MAX_CH_CNT #E16_LTABLE_MAX_CH_CNT E16) + @return +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetLChannelCount(t_x502_hnd hnd, uint32_t lch_cnt); + + +/***************************************************************************//** + @brief + + X502_SetLChannelCount() + . + @param[in] hnd + @param[out] lch_cnt + @return +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetLChannelCount(t_x502_hnd hnd, uint32_t* lch_cnt); + +/***************************************************************************//** + @brief + + + ( , ) , + . + + X502_SetAdcFreq(), + . + + @param[in] hnd . + @param[in] adc_freq_div ( 1 #X502_ADC_FREQ_DIV_MAX). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetAdcFreqDivider(t_x502_hnd hnd, uint32_t adc_freq_div); + +/***************************************************************************//** + @brief + + , + , + + , . + + X502_SetAdcFreq(), + + ( ). + + @param[in] hnd . + @param[in] delay ( 0 + #X502_ADC_INTERFRAME_DELAY_MAX) + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetAdcInterframeDelay(t_x502_hnd hnd, uint32_t delay); + +/***************************************************************************//** + @brief . + + + , + . + + X502_SetDinFreq(), + + . + + @param[in] hnd . + @param[in] din_freq_div + ( 1 #X502_DIN_FREQ_DIV_MAX). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetDinFreqDivider(t_x502_hnd hnd, uint32_t din_freq_div); + + + +/***************************************************************************//** + @brief + + + , . + + ( ). + . + + X502_SetOutFreq(), + . + + @note L-502, , + #X502_OUT_FREQ_DIV_DEFAULT, 0.5 . + E-502 . + X502_CheckFeature(). + + @param[in] hnd . + @param[in] out_freq_div + ( #X502_OUT_FREQ_DIV_MIN #X502_OUT_FREQ_DIV_MAX). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetOutFreqDivider(t_x502_hnd hnd, uint32_t out_freq_div); + + + +/***************************************************************************//** + @brief + + , + f_acq. + , . + + , + ( ) + . + f_frame ( + ). + f_frame , + . + + , + X502_SetSyncMode() X502_SetRefFreq() / X502_SetExtRefFreqValue(), + . + + , + , + X502_SetLChannelCount(). + + + , + , X502_SetRefFreq(). + + + @param[in] hnd . + @param[in,out] f_acq + . + . + @param[in,out] f_frame + ( ) + . + . + , + ( ). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame); + + +/***************************************************************************//** + @brief + + , + . + , . + + , + X502_SetSyncMode() + X502_SetRefFreq()/ X502_SetExtRefFreqValue(), + . + + + , + , X502_SetRefFreq(). + + @param[in] hnd . + @param[in,out] f_din + . + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetDinFreq(t_x502_hnd hnd, double *f_din); + + + +/***************************************************************************//** + @brief + + , + . + , . + + , + X502_SetSyncMode() + X502_SetRefFreq() / X502_SetExtRefFreqValue(), + . + + + , + , X502_SetRefFreq(). + + @note L-502, , + , #X502_OUT_FREQ_DIV_DEFAULT, + 0.5 . + E-502 . + + X502_CheckFeature(). + + + @param[in] hnd . + @param[in,out] f_dout + . + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetOutFreq(t_x502_hnd hnd, double *f_dout); + + + +/***************************************************************************//** + @brief + + + ( ) , + X502_SetAdcFreq() + X502_SetAdcFreqDivider() / X502_SetAdcInterframeDelay(). + + @param[in] hnd . + @param[out] f_acq NULL, + . + @param[out] f_frame NULL, + . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_GetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame); + + +/***************************************************************************//** + @brief + + , + / + . + + + 2 1.5 (2 ), + #t_x502_ref_freq. + + + X502_SetExtRefFreqValue(). + + E-502 1.5 + PLDA 1 . + + @param[in] hnd . + @param[in] freq #t_x502_ref_freq, + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetRefFreq(t_x502_hnd hnd, uint32_t freq); + +/***************************************************************************//** + @brief + + ( X502_SetSyncMode() , + #X502_SYNC_INTERNAL) + , , + 1.5 . + + , + + X502_SetAdcFreq(), X502_SetDinFreq() X502_SetOutFreq(), + + . + + 1.1.4 . + + @param[in] hnd . + @param[in] freq . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetExtRefFreqValue(t_x502_hnd hnd, double freq); + +/***************************************************************************//** + @brief ( E16) + + @param[in] hnd . + @param[in] phy_ch , 0 + (0-15 , + 0-31 ) + @param[in] mode ( #t_x502_lch_mode) + @param[in] range ( #t_x502_adc_range) + @param[in] value . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetAdcSyncStartValue(t_x502_hnd hnd, uint32_t phy_ch, uint32_t mode, uint32_t range, double value); + +/***************************************************************************//** + @brief + + , + X502_SetAdcFreq(), X502_SetDinFreq() + X502_SetOutFreq(), + . + + , + X502_SetRefFreq() (1.5 2 ), --- , + X502_SetExtRefFreqValue(). + + 1.1.4 . + + @param[in] hnd . + @param[in] freq . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetRefFreqValue(t_x502_hnd hnd, double *freq); + + + + +/***************************************************************************//** + @brief + + - + . + + #X502_SYNC_INTERNAL + , X502_SetRefFreq(). + X502_StreamsStart() + , X502_SetSyncStartMode(), + X502_StreamsStop(). + + + . + + @param[in] hnd . + @param[in] sync_mode #t_x502_sync_mode, + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetSyncMode(t_x502_hnd hnd, uint32_t sync_mode); + +/***************************************************************************//** + @brief + + / . + + X502_SetSyncMode() + #X502_SYNC_INTERNAL, + , + + (.. + ). + + , + (. #t_x502_sync_mode). + #X502_SYNC_INTERNAL + X502_StreamsStart(), - + X502_StreamsStart() . + .. , + X502_StreamsStart(). + + @param[in] hnd . + @param[in] sync_start_mode #t_x502_sync_mode, + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetSyncStartMode(t_x502_hnd hnd, uint32_t sync_start_mode); + + +/***************************************************************************//** + @brief + + , + BlackFin. + . + X502_BfLoadFirmware() + . + + , + , + , + (, JTAG ). + + @param[in] hnd . + @param[in] mode #t_x502_mode. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_SetMode(t_x502_hnd hnd, uint32_t mode); +/***************************************************************************//** + @brief + + . + @param[in] hnd . + @param[out] mode + ( #t_x502_mode). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_GetMode(t_x502_hnd hnd, uint32_t* mode); +/***************************************************************************//** + @brief + + . + , + Flash- + . + + (val - offs) * k, val --- + . + + , + . + , Flash- + . + + @param[in] hnd . + @param[in] range ( #t_x502_adc_range). + @param[in] k . + @param[in] offs . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_SetAdcCoef(t_x502_hnd hnd, uint32_t range, double k, double offs); + +/***************************************************************************//** + @brief + + + . , + Flash- , , + X502_SetAdcCoef() . + + @param[in] hnd . + @param[in] range ( #t_x502_adc_range). + @param[in] k + . + @param[in] offs . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetAdcCoef(t_x502_hnd hnd, uint32_t range, double* k, double* offs); + + + +/***************************************************************************//** + @brief + + , + x502api + , #X502_DAC_FLAGS_CALIBR. + + + (val + offs) * k, val --- ( ). + + , + Flash- . + + + . Flash-, .. + + Flash-. + + @param[in] hnd . + @param[in] ch ( #t_x502_dac_ch). + @param[in] k . + @param[in] offs . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_SetDacCoef(t_x502_hnd hnd, uint32_t ch, double k, double offs); + + +/***************************************************************************//** + @brief + + . + , + Flash- , , + X502_SetDacCoef() . + + @param[in] hnd . + @param[in] ch ( #t_x502_dac_ch). + @param[in] k + . + @param[in] offs . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetDacCoef(t_x502_hnd hnd, uint32_t ch, double* k, double* offs); + + +/***************************************************************************//** + @brief + + , + , + , . + + X502_SetAdcFreq(), + + , . + + E16 ref_freq E16_REF_FREQ_48000KHZ, + X502_CalcAdcFreq2! + + + @param[in] ref_freq ( ) + @param[in] lch_cnt , . + . + f_frame , + 0. + @param[in,out] f_acq + . + , . + @param[in,out] f_frame + ( ) + . . + , + . + , + + ( ). + @param[out] result_freq_div + . + , + . + @param[out] result_frame_delay + . + , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CalcAdcFreq(double ref_freq, uint32_t lch_cnt, double *f_acq, + double *f_frame, uint32_t *result_freq_div, uint32_t *result_frame_delay); + + /***************************************************************************//** + @brief + + , + , + , . + + X502_SetAdcFreq(), + , . + E16 X502. + + + @param[in] hnd . + @param[in] ref_freq ( ) + @param[in] lch_cnt , . + . + f_frame , + 0. + @param[in,out] f_acq + . + , . + @param[in,out] f_frame + ( ) + . . + , + . + , + + ( ). + @param[out] result_freq_div + . + , + . + @param[out] result_frame_delay + . + , + . + @return . + ******************************************************************************/ +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); + +/***************************************************************************//** + @brief + + , + , , + . + + X502_SetDinFreq(), + + , . + + E16 ref_freq E16_REF_FREQ_48000KHZ, + X502_CalcDinFreq2! + + @param[in] ref_freq ( ) + @param[in,out] f_din + . + , + . + @param[out] result_freq_div + + . + , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CalcDinFreq(double ref_freq, double *f_din, uint32_t *result_freq_div); + +/***************************************************************************//** + @brief + + , + , , + . + + X502_SetDinFreq(), , . + + @param[in] hnd . + @param[in] ref_freq ( ) + @param[in,out] f_din + . + , + . + @param[out] result_freq_div + + . + , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CalcDinFreq2(t_x502_hnd hnd, double ref_freq, double *f_din, uint32_t *result_freq_div); + +/***************************************************************************//** + @brief + + , + , , + . + + X502_SetOutFreq(), + + , . + + , + (. X502_SetOutFreq()). + + E16 ref_freq E16_REF_FREQ_48000KHZ, + X502_CalcOutFreq2! + + @param[in] ref_freq ( ) + @param[in,out] f_dout + . + , + . + @param[out] result_freq_div + . + , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CalcOutFreq(double ref_freq, double *f_dout, uint32_t *result_freq_div); + +/***************************************************************************//** + @brief + + , + , , + . + + X502_SetOutFreq(), + + , . + + , + (. X502_SetOutFreq()). + + @param[in] hnd . + @param[in] ref_freq ( ) + @param[in,out] f_dout + . + , + . + @param[out] result_freq_div + . + , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CalcOutFreq2(t_x502_hnd hnd, double ref_freq, double *f_dout, uint32_t *result_freq_div); + +/** @} */ + + +/***************************************************************************//** + @addtogroup func_async - + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief + + . + , , + ( ). + + , + , + . + + @note , + ( X502_StreamsStart() + , ). + + @param[in] hnd . + @param[in] ch ( #t_x502_dac_ch). + @param[in] data ( ) + @param[in] flags #t_x502_dacout_flags. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_AsyncOutDac(t_x502_hnd hnd, uint32_t ch, double data, uint32_t flags); + +/***************************************************************************//** + @brief + + . + , , + ( ). + + , + , + . + + @note , + ( X502_StreamsStart() + , ). + + @param[in] hnd . + @param[in] range ( LTA37 1:1 1:10) ( #t_x502devs_dac_range) + @param[in] ch ( #t_x502_dac_ch). + @param[in] data ( ) + @param[in] flags #t_x502_dacout_flags. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_AsyncOutDac2(t_x502_hnd hnd, uint32_t range, uint32_t ch, double data, uint32_t flags); + +/***************************************************************************//** + @brief + + . + X502_PrepareData() - 16 + , - ( + ). + + , + , . + + , , + , , + , + . + + @note , + ( X502_StreamsStart() + , ). + + @param[in] hnd . + @param[in] val - , - + #t_x502_digout_word_flags. + 0..15 OUT1..OUT16 (E16) + DO1..DO16 (x502) + @param[in] msk - + ( + val). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_AsyncOutDig(t_x502_hnd hnd, uint32_t val, uint32_t msk); + + +/***************************************************************************//** + @brief + + . + ( + #X502_STREAM_DIN). + + E-502/L-502 , + / + X502_StreamsStart(), + + , E16 . + + E16 17 - INT, 18 - TRIG + + @note , + ( X502_StreamsStart() + , ). + + @param[in] hnd . + @param[out] din + . + 18 , 14 - . + , + . + + E-502 L-502. + + , , + ! + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_AsyncInDig(t_x502_hnd hnd, uint32_t* din); + + +/***************************************************************************//** + @brief + + + . , + X502_SetAdcFreq(). + . , + X502_AsyncGetAdcFrame() + . + + , + X502_ProcessAdcData(), , + X502_ProcessAdcData(). + + + . + + , + , + . + + @param[in] hnd . + @param[in] flags t_x502_proc_flags + @param[in] tout + @param[out] data , + . , + double , + + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_AsyncGetAdcFrame(t_x502_hnd hnd, uint32_t flags, + uint32_t tout, double* data); + +/** @} */ + + + + + +/***************************************************************************//** + @addtogroup func_streams - + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief / + + / + . + X502_Configure(), . + X502_StreamsStart(). + + + , + , + (. @ref sect_sync_mode_buf) + @param[in] hnd . + @param[in] streams #t_x502_streams, , + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_StreamsEnable(t_x502_hnd hnd, uint32_t streams); +/****************************************************************************//** + @brief / + + . + . + , X502_StreamsEnable(). + @param[in] hnd . + @param[in] streams #t_x502_streams, , + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_StreamsDisable(t_x502_hnd hnd, uint32_t streams); + +/****************************************************************************//** + @brief , + + , , + . + + @param[in] hnd . + @param[out] streams #t_x502_streams, , + . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetEnabledStreams(t_x502_hnd hnd, uint32_t* streams); + +/***************************************************************************//** + @brief / + + . + . , + , + + . + + DMA , + , + DMA , + , X502_PreloadStart() ( + ). + + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_StreamsStart(t_x502_hnd hnd); + +/***************************************************************************//** + @brief / + + / . + ( + ) + . + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_StreamsStop(t_x502_hnd hnd); + + +/***************************************************************************//** + @brief , / + + X502_StreamsStart() + - BlackFin. + , + #X502_ERR_STREAM_IS_NOT_RUNNING, , + + @param[in] hnd . + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_IsRunning(t_x502_hnd hnd); + + + +/***************************************************************************//** + @brief + + , + . + , + , ( + ) ( , ). + X502_ProcessData(). + + , , + + . + , . + + + X502_GetRecvReadyCount(). + + X502_Recv() + X502_StreamsStart(). + + @param[in] hnd . + @param[out] buf , . + @param[in] size (32- ). + @param[in] tout . + @return < 0 - . + >= 0 - . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_Recv(t_x502_hnd hnd, uint32_t* buf, uint32_t size, uint32_t tout); + + +/***************************************************************************//** + @brief + + , + . + , , + ( , 1 2). + X502_PrepareData(). + + , + . + + X502_GetSendReadyCount(). + + , , + . + + + X502_PreloadStart(). + + @param[in] hnd . + @param[in] buf , + @param[in] size (32- ). + @param[in] tout ( ) . + @return < 0 - . + >= 0 - . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_Send(t_x502_hnd hnd, const uint32_t* buf, uint32_t size, uint32_t tout); + + + +/***************************************************************************//** + @brief + + , X502_Recv(). + + , ( #X502_PROC_FLAGS_VOLT). + + , + ( + - ). + + , + X502_ProcessData(), + . + + @param[in] hnd . + @param[in] src , X502_Recv(). + @param[out] dest , + . + @param[in,out] size - src, - + + dest + @param[in] flags #t_x502_proc_flags + @return . + ****************************************************************************/ +X502_EXPORT(int32_t) X502_ProcessAdcData(t_x502_hnd hnd, const uint32_t* src, + double *dest, uint32_t *size, uint32_t flags); + +/***************************************************************************//** + @brief + + , X502_Recv(). + , + - , double, + . + + . + , + . + , + #X502_ADC_SCALE_CODE_MAX + . + + , , + (, ). + @param[in] hnd . + @param[in] src , X502_Recv(). + @param[in] size (32- ) src. + @param[in] flags #t_x502_proc_flags, + . + "". + @param[out] adc_data , , + . + NULL, + ( adc_data_size NULL, + 0). + @param[in,out] adc_data_size + adc_data. + adc_data_size, adc_data + adc_data_size . + + + . + NULL, adc_data = NULL + @param[out] din_data , + . + , + X502_AsyncInDig(). + @param[in,out] din_data_size adc_data_size + din_data , + + . NULL, + din_data = NULL. + @return . + ****************************************************************************/ +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); + +/***************************************************************************//** + @brief + + X502_ProcessData(), + . + , , + . + usr_data + ( ). + , + BlackFin. + @param[in] hnd . + @param[in] src , + X502_Recv(). + @param[in] size (32- ) src. + @param[in] flags #t_x502_proc_flags. + @param[out] adc_data , + (. X502_ProcessData()). + @param[in,out] adc_data_size . X502_ProcessData() + @param[out] din_data , + . . X502_ProcessData(). + @param[in,out] din_data_size . X502_ProcessData(). + @param[out] usr_data , + . + @param[in,out] usr_data_size usr_data + + . + NULL usr_data = NULL. + @return . + ****************************************************************************/ +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); + + + +/***************************************************************************//** + @brief + + - , + . + , . + + , . + + n*size , n - + ( 1 3). + + 32- , 16- + , - + #t_x502_digout_word_flags, + ( ) . + + , , + , + . + , + #X502_DAC_SCALE_CODE_MAX , +5V. + + @param[in] hnd . + @param[in] dac1 + NULL, . + @param[in] dac2 + NULL, . + @param[in] digout + NULL, . + @param[in] size . + @param[in] flags , , + #t_x502_dacout_flags. + @param[out] out_buf , + . + n*size (n - + ) + @return . +*******************************************************************************/ +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); + +/***************************************************************************//** + @brief + + + + X502_Send(). + + : 1- + , 1- + .., .. + , , + , + . + + 32- , 16- + , - + #t_x502_digout_word_flags, + ( ) . + + + [ ](@ref TLTR35_CONFIG::OutDataFmt). + . + + @param[in] hnd . + @param[in] dac_data . , + . + @param[in,out] dac_size dac_data, + , + . + @param[in] dout_data . + , + . + @param[in,out] dout_size dout_data, + , + . + @param[in] flags , , + #t_x502_dacout_flags. + @param[out] result + . + @param[in,out] snd_size result, + , 32- + result . + @param[in] ch_enabled , + 1 - 1 , 2 - 2 , .. + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_PrepareData2(t_x502_hnd hnd, const double *dac_data, + uint32_t *dac_size, const uint32_t *dout_data, + uint32_t *dout_size, uint32_t flags, + uint32_t *result, uint32_t *snd_size, uint32_t ch_enabled); + +/***************************************************************************//** + @brief + + . + , , + , + . + , + #X502_DAC_SCALE_CODE_MAX , +5V. + + @param[in] hnd . + @param[in] range ( LTA37 1:1 1:10) ( #t_x502devs_dac_range) + @param[in] dac_ch . + @param[in] dac_val dac_ch . + @param[in] flags , , + #t_x502_dacout_flags. + @param[out] out_buf dac_ch. + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_PrepareDacWrd(t_x502_hnd hnd, uint32_t dac_ch, double dac_val, + int32_t flags, + uint32_t* out_wrd); + +/***************************************************************************//** + @brief + + , + X502_Recv(). + X502_Recv() , , + X502_Recv() ( + ). + Ethernet + Windows. + @param[in] hnd . + @param[out] rdy_cnt . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_GetRecvReadyCount(t_x502_hnd hnd, uint32_t *rdy_cnt); + + +/***************************************************************************//** + @brief + + , + . + + X502_Send() . + Ethernet (TCP). + @param[in] hnd . + @param[out] rdy_cnt , + . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_GetSendReadyCount(t_x502_hnd hnd, uint32_t *rdy_cnt); + +/***************************************************************************//** + @brief + + + , + X502_ProcessData()/ + X502_ProcessAdcData() , . + + , , + . + + . + X502_ProcessData() , + , , + X502_ProcessData(). + + , 7 , X502_ProcessData() + 7 , + X502_GetNextExpectedLchNum() 0 ( + ). + X502_ProcessData() 7*n + 5 , + 5 ( + 0,1,2,3,4 ). + + @param[in] hnd . + @param[out] lch ( ). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_GetNextExpectedLchNum(t_x502_hnd hnd, uint32_t *lch); + + + +/***************************************************************************//** + @brief + + + . + , + X502_StreamsStart(). + + . + + X502_Send(). + + @param[in] hnd . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_PreloadStart(t_x502_hnd hnd); + + + +/***************************************************************************//** + @brief + + ( L502) + ( E502) . + + X502_Send(). + + ( + ) - .. + X502_OutCycleSetup(). + . + + L-502 , + . + E-502 . + E-502 L-502. + + @param[in] hnd . + @param[in] size + . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_OutCycleLoadStart(t_x502_hnd hnd, uint32_t size); + +/***************************************************************************//** + @brief + + . + - ( X502_StreamsStart()), + , + -. + + , + , + #X502_OUT_CYCLE_FLAGS_FORCE. + + #X502_OUT_CYCLE_FLAGS_WAIT_DONE, + , + . + + , , + - X502_StreamsStart(). + + X502_OutCycleLoadStart() + ! + + @param[in] hnd . + @param[in] flags #t_x502_out_cycle_flags. + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_OutCycleSetup(t_x502_hnd hnd, uint32_t flags); + + +/***************************************************************************//** + @brief + + X502_OutCycleSetup #X502_OUT_CYCLE_FLAGS_WAIT_DONE + . + + X502_OutCycleLoadStart() X502_OutCycleSetup() + ! + + @param[in] hnd . + @param[in] flags #t_x502_out_cycle_flags. + @param[in] tout , + . + , + . + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_OutCycleSetupWaitDone(t_x502_hnd hnd, uint32_t tout); + +/***************************************************************************//** + @brief + + + X502_OutCycleSetup(). + , + . + + X502_StreamsStop() ( + X502_StreamsDisable()) + . + + , + , . X502_StreamsStop() + , , .. + , + #X502_OUT_CYCLE_FLAGS_WAIT_DONE. + + @param[in] hnd . + @param[in] flags #t_x502_out_cycle_flags. + @return . + ***************************************************************************/ +X502_EXPORT(int32_t) X502_OutCycleStop(t_x502_hnd hnd, uint32_t flags); + + +/***************************************************************************//** + @brief , + + , + X502_OutCycleSetup() + X502_OutCycleStop(). + #X502_OUT_CYCLE_FLAGS_WAIT_DONE , + ( ). + + , 1.1.2, + ARM 1.0.2 E-502 + 1.0.9 L-502. , + , #X502_ERR_NOT_SUP_BY_FIRMWARE + #X502_ERR_NOT_SUP_BY_DRIVER. + + X502_OutCycleSetup() + X502_StreamsStart(), , + , + .. + ( E502). + + X502_OutCycleSetup() + + . , + , + . + + X502_OutCycleStop() + X502_StreamsStop(), ( ), + + . + + @param[in] hnd . + @param[out] done 0, + , 1 --- ( + , ) + @return . + ****************************************************************************/ +X502_EXPORT(int32_t) X502_OutCycleCheckSetupDone(t_x502_hnd hnd, uint32_t *done); + + + +/***************************************************************************//** + @brief + + . + #X502_OUT_STATUS_FLAG_BUF_WAS_EMPTY , + , + , - + . + + @param[in] hnd . + @param[out] status --- #t_x502_out_status_flags, + Ȕ. + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_OutGetStatusFlags(t_x502_hnd hnd, uint32_t *status); + + +/***************************************************************************//** + @brief + + , + . + , - + . + + X502_SetStreamBufSize , + X502_StreamsStart + X502_StreamsEnable , + X502_SetStreamBufSize + X502_StreamsStart X502_StreamsEnable. + + @param[in] hnd . + @param[in] ch , + ( #t_x502_stream_ch). + @param[in] size 32- , + 0 - + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetStreamBufSize(t_x502_hnd hnd, uint32_t ch, uint32_t size); + +/***************************************************************************//** + @brief + + ( + PCI-Express USB) + . + , + . + + @param[in] hnd . + @param[in] dma_ch , + ( #t_x502_stream_ch). + @param[in] step 32- + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetStreamStep(t_x502_hnd hnd, uint32_t dma_ch, uint32_t step); + +/** @} */ + + + +/***************************************************************************//** + @addtogroup func_dsp + @{ +*******************************************************************************/ +/***************************************************************************//** + @brief BlackFin + + + , + ( ). + LDR. + @param[in] hnd . + @param[in] filename . + @return . + *****************************************************************************/ +X502_EXPORT(int32_t) X502_BfLoadFirmware(t_x502_hnd hnd, const char* filename); + + + +/***************************************************************************//** + @brief , BlackFin + + BlackFin + . , + BlackFin . + ( , + ..) . + DSP. + + , + ( ) + JTAG-. + + @param[in] hnd . + @param[out] version , + BlackFin + . + @return . + *****************************************************************************/ +X502_EXPORT(int32_t) X502_BfCheckFirmwareIsLoaded(t_x502_hnd hnd, uint32_t *version); + +/***************************************************************************//** + @brief + + . + , (L1), SDRAM. + BlackFin . + + , + . + + @param[in] hnd . + @param[in] addr , + . + @param[out] regs , + . + @param[in] size 32- . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_BfMemRead(t_x502_hnd hnd, uint32_t addr, uint32_t* regs, + uint32_t size); + +/***************************************************************************//** + @brief + + BlackFin. + 8 32- (32 ). + (L1), SDRAM. + BlackFin . + + , + . + + @note , .. , + . + + @param[in] hnd . + @param[in] addr , + . + @param[out] regs . + @param[in] size 32- + ( 8). + @return . +*******************************************************************************/ +X502_EXPORT(int32_t) X502_BfMemWrite(t_x502_hnd hnd, uint32_t addr, + const uint32_t* regs, uint32_t size); + + +/***************************************************************************//** + @brief + + + , BlackFin. + + + , + . + . + + , x502api + , + . + X502_BF_CMD_CODE_USER (0x8000). + + @param[in] hnd . + @param[in] cmd_code - , . + @param[in] par , ( + ). + @param[in] snd_data , . + , + snd_size = 0. + @param[in] snd_size 32- , snd_data + @param[out] rcv_data , , + . + , + , rcv_size = 0. + @param[in] rcv_size 32- , , + . + rcv_data + . + @param[in] tout , + . + , + . + @param[out] recvd_size , + 32- , + + ( , + rcv_size). + @return . + , + . +*******************************************************************************/ +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); +/** @} */ + + + + + + +/***************************************************************************//** + @addtogroup func_flash Flash- + @{ +*******************************************************************************/ + +/***************************************************************************//** + @brief Flash- + + Flash- , + . - + . + @param[in] hnd . + @param[in] addr . + @param[out] data , + ( size ). + @param[in] size . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_FlashRead(t_x502_hnd hnd, uint32_t addr, uint8_t* data, + uint32_t size); +/***************************************************************************//** + @brief Flash- + + Flash- . + X502_FlashErase() + X502_FlashWriteEnable(), + Flash-. + #X502_FLASH_USER_SIZE + Flash-. + @param[in] hnd . + @param[in] addr . + @param[in] data ( + size ). + @param[in] size . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_FlashWrite(t_x502_hnd hnd, uint32_t addr, + const uint8_t* data, uint32_t size); +/***************************************************************************//** + @brief Flash- + + Flash- ( + 0xFF). 4096 ! + + X502_FlashWriteEnable(). + @param[in] hnd . + @param[in] addr ( 4K). + @param[in] size ( 4K). + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_FlashErase(t_x502_hnd hnd, uint32_t addr, uint32_t size); +/***************************************************************************//** + @brief Flash- + + Flash- ( + #X502_FLASH_USER_SIZE ). , + X502_FlashErase() X502_FlashWrite() + . + X502_FlashWriteDisable(). + @param[in] hnd . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_FlashWriteEnable(t_x502_hnd hnd); +/***************************************************************************//** + @brief Flash- + + Flash- + ( #X502_FLASH_USER_SIZE ). , + + X502_FlashErase() X502_FlashWrite(), + . + @param[in] hnd . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_FlashWriteDisable(t_x502_hnd hnd); + +/** @} */ + + + + + +/***************************************************************************//** + @addtogroup func_misc + @{ +*******************************************************************************/ +/**************************************************************************//** + @brief + + x502api. + 32- . + --- , + , --- . + + --- , --- , + --- , --- ( --- 0) + + @return 32- , + *****************************************************************************/ +X502_EXPORT(uint32_t) X502_GetLibraryVersion(void); + +/***************************************************************************//** + @brief + + , . + ( + ). + + @note , Windows + Windows CP1251, Linux + UTF-8. + @param[in] err , . + @return , + ******************************************************************************/ +X502_EXPORT(const char*) X502_GetErrorString(int32_t err); + +/***************************************************************************//** + @brief + + , /, + + L-502 LED1 E-502. + + . + + / + . + + @param[in] hnd . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_LedBlink(t_x502_hnd hnd); + + +/***************************************************************************//** + @brief + + + . + . E-502 L-502 SYN1 SYN2. + L-502 + . E-502 + . + E-16 TRIG INT , START CONV. + + , + . + + . + + @param[in] hnd . + @param[in] pullups ( #t_x502_pullups), , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetDigInPullup(t_x502_hnd hnd, uint32_t pullups); + +/***************************************************************************//** + @brief pullups + + pullups . E16 + + @param[in] hnd . + @param[out] pullups ( #t_x502_pullups), , + . + @return . + ******************************************************************************/ +X502_EXPORT(int32_t) X502_GetDigInPullup(t_x502_hnd hnd, uint32_t *pullups); + +/***************************************************************************//** + @brief + + , + #t_x502_features . + + , #X502_ERR_OK. + + 1.1.6 . + + @param[in] hnd . + @param[in] feature #t_x502_features, , + . + @return , + #X502_ERR_OK, --- + ******************************************************************************/ +X502_EXPORT(int32_t) X502_CheckFeature(t_x502_hnd hnd, uint32_t feature); + +/***************************************************************************//** + @brief . + + , API + . + API . + + @param[in] hnd . + @param[in] err #t_x502_errs, . + X502_ERR_STREAM_IS_RUNNING + + @return + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SuppressError(t_x502_hnd hnd, int32_t err); + + +X502_EXPORT(int32_t) X502_SetAfcCoef(t_x502_hnd hnd, double Fd, double SigFreq, double *K, uint32_t size, int enable); +X502_EXPORT(int32_t) X502_GetAfcCoef(t_x502_hnd hnd, double *Fd, double *SigFreq, double *K, uint32_t size, int *enable); + + +/***************************************************************************//** + @brief + + + api + + @param[in] hnd . + @param[in] param #t_x502_params, + @param[in] value + + @return + ******************************************************************************/ +X502_EXPORT(int32_t) X502_SetParam(t_x502_hnd hnd, uint32_t param, void *value); + +/***************************************************************************//** + @brief LTA37 + + @param[in] hnd . + @param[in] echo_en , - , DI + @param[in] echo_ch + @param[in] di_ch_en_mask + + @return + ******************************************************************************/ +X502_EXPORT(int32_t) LTA37_SetDIParam(t_x502_hnd hnd, uint32_t echo_en, uint32_t echo_ch, uint32_t di_ch_en_mask); + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + + +#endif // X502API_H diff --git a/x502tstp.h b/x502tstp.h new file mode 100644 index 0000000..d4f9d9a --- /dev/null +++ b/x502tstp.h @@ -0,0 +1,167 @@ +#ifndef E502TSTP_H +#define E502TSTP_H + +#include "x502api.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup tstpfunc_list Функции для работы с метками времени + @{ **/ + +/***************************************************************************//** + @addtogroup tstptype_list Константы и перечисления + @{ + *****************************************************************************/ + +/** Тип данных для хранения времени + * Время хранится в секундах прошедшее с начала этой эпохи (00:00:00 UTC, 1 Января 1970 года) + * Дробный формат хранения 32.31: 32 целых бит, 31 дробных бит, + * старшие 32 бита - секунды, младшие 31 бит - доли секунды (SubSecond) = 1 / (1<<31) секунд + */ +typedef uint64_t t_x502_tstptime; + + +#define TSP_NSEC_PER_SEC (1000000000) + +/** длина в битах для SubSecond в WRD1 слове метки времени */ +#define TSP_WRD1_SSEC_LEN (24) +/** длина в битах для SubSecond в WRD2 слове метки времени */ +#define TSP_WRD2_SSEC_LEN (7) +/** длина в битах для Second в WRD2 слове метки времени */ +#define TSP_WRD2_SEC_LEN (19) +/** длина в битах для Second в WRD3 слове метки времени */ +#define TSP_WRD3_SEC_LEN (13) +/** общая длина в битах для SubSecond в t_x502_tstptime (дробный формат 32.31) */ +#define TSP_SSEC_WIDTH (TSP_WRD1_SSEC_LEN + TSP_WRD2_SSEC_LEN) + + +/** Номер слова с меткой времени 0..3 */ +#define TSP_WRD_NUM(wrd) (((wrd) >> 26) & 3) +/** Счетчик преобразования АЦП в WRD0 слове с меткой времени */ +#define TSP_WRD0_ADC_CLK_NUM_MASK (0x3ffffff) + +/** Признак захвата времени от PTP сервера */ +#define TSP_WRD1_LOCK_MASK (1 << 25) + +/** Признак первой метки после перехода GO в активное состояние */ +#define TSP_WRD1_FMARK_MASK (1 << 24) +/** битовая маска для SubSecond в WRD1 */ +#define TSP_WRD1_SSEC_MASK ((1 << TSP_WRD1_SSEC_LEN) - 1) +/** битовая маска для Second в WRD2 */ +#define TSP_WRD2_SEC_MASK (0x3ffff80) +/** битовая маска для SubSecond в WRD2 */ +#define TSP_WRD2_SSEC_MASK ((1 << TSP_WRD2_SSEC_LEN) - 1) +/** битовая маска для Second + SubSecond в WRD2 */ +#define TSP_WRD2_SECSSEC_MASK ((1 << (TSP_WRD2_SEC_LEN + TSP_WRD2_SSEC_LEN)) - 1) +/** битовая маска для Second в WRD3 */ +#define TSP_WRD3_SEC_MASK ((1 << TSP_WRD3_SEC_LEN) - 1) + +/** макрос для проверки выставлен ли признак первой метки для слова WRD1 */ +#define TSP_WRD1_IS_FMARK(wrd) (!!((wrd) & TSP_WRD1_FMARK_MASK)) +/** макрос для проверки выставлен ли признак lock для слова WRD1 */ +#define TSP_WRD1_IS_LOCK(wrd) (!!((wrd) & TSP_WRD1_LOCK_MASK)) +/** макрос для получения SubSecond из слова WRD1 */ +#define TSP_WRD1_GET_SSEC(wrd) ((wrd) & TSP_WRD1_SSEC_MASK) +/** макрос для получения Second + SubSecond из слова WRD2 */ +#define TSP_WRD2_GET_SECSSEC(wrd) ((uint64_t)((wrd) & TSP_WRD2_SECSSEC_MASK) << TSP_WRD1_SSEC_LEN) +/** макрос для получения SubSecond из слова WRD2 */ +#define TSP_WRD2_GET_SSEC(wrd) ((wrd) & TSP_WRD2_SSEC_MASK) +/** макрос для получения Second из слова WRD3 */ +#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)) +/** максимально возможное значение SubSecond */ +#define SSEC_MAX (0x7fffffff) +/** перевод SubSecond в наносекунды */ +#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))) +/** получение целых секунд из t_x502_tstptime */ +#define TSTP_SECSSEC_TO_SEC(time) (time > 0 ? (uint32_t)((time) >> TSP_SSEC_WIDTH) : (uint32_t)((time * -1) >> TSP_SSEC_WIDTH)) +/** перевод в секунды с плавающей запятой из t_x502_tstptime */ +#define TSTP_SECSSEC_TO_SEC_DOUBLE(time) (((double)(time)) / (1U << TSP_SSEC_WIDTH)) +/** перевод секунд в t_x502_tstptime */ +#define TSTP_SEC_TO_SSEC(time) (((uint64_t)(time)) << TSP_SSEC_WIDTH) + +/** Структура для хранения контекста при обработке потока слов "на ввод" с включенными метками времени */ +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