moved libs to the lib directory
This commit is contained in:
731
lib/x502/x502api.c
Normal file
731
lib/x502/x502api.c
Normal file
@ -0,0 +1,731 @@
|
||||
#include "x502api.h"
|
||||
#include "x502api_private.h"
|
||||
#include "x502_fpga_regs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static const double f_x502_scales[] = {10., 5., 2., 1., 0.5, 0.2};
|
||||
// В E16 только 4 диапазона!
|
||||
static const double f_e16_scales[] = {10., 2.5, 0.625, 0.15625, 0., 0.};
|
||||
|
||||
|
||||
X502_EXPORT(double const*) E16_GetAdcRanges(uint32_t *ranges_len) {
|
||||
if (ranges_len) {
|
||||
*ranges_len = E16_ADC_RANGE_CNT;
|
||||
}
|
||||
return f_e16_scales;
|
||||
}
|
||||
|
||||
X502_EXPORT(double const*) E502_GetAdcRanges(uint32_t *ranges_len) {
|
||||
if (ranges_len) {
|
||||
*ranges_len = X502_ADC_RANGE_CNT;
|
||||
}
|
||||
return f_x502_scales;
|
||||
}
|
||||
|
||||
X502_EXPORT(double const*) X502_GetAdcRanges(t_x502_hnd hnd, uint32_t *ranges_len) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if (err != X502_ERR_OK) {
|
||||
if (x502_is_E16(hnd)) {
|
||||
return E16_GetAdcRanges(ranges_len);
|
||||
} else {
|
||||
return E502_GetAdcRanges(ranges_len);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(t_x502_hnd) X502_Create(void) {
|
||||
t_x502_hnd hnd = calloc(sizeof(t_x502), 1);
|
||||
if (hnd != NULL) {
|
||||
hnd->sign = X502_SIGN;
|
||||
}
|
||||
|
||||
return hnd;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_Free(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (hnd->flags & PRIV_FLAGS_OPENED)
|
||||
err = X502_Close(hnd);
|
||||
|
||||
hnd->sign = 0;
|
||||
free(hnd);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_Close(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && (hnd->flags & PRIV_FLAGS_OPENED)) {
|
||||
int32_t stop_err;
|
||||
if (hnd->flags & PRIV_FLAGS_STREAM_RUN) {
|
||||
/* остановка потока */
|
||||
err = X502_StreamsStop(hnd);
|
||||
}
|
||||
|
||||
hnd->flags &= ~PRIV_FLAGS_OPENED;
|
||||
|
||||
|
||||
stop_err = hnd->iface_hnd->close(hnd);
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
|
||||
if (hnd->mutex_cfg!=OSSPEC_INVALID_MUTEX) {
|
||||
stop_err = osspec_mutex_destroy(hnd->mutex_cfg);
|
||||
hnd->mutex_cfg = OSSPEC_INVALID_MUTEX;
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
}
|
||||
|
||||
if (hnd->mutex_bf!=OSSPEC_INVALID_MUTEX) {
|
||||
stop_err = osspec_mutex_destroy(hnd->mutex_bf);
|
||||
hnd->mutex_bf = OSSPEC_INVALID_MUTEX;
|
||||
if (err == X502_ERR_OK)
|
||||
err = stop_err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_IsOpened(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && !(hnd->flags & PRIV_FLAGS_OPENED)) {
|
||||
err = X502_ERR_DEVICE_NOT_OPENED;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_OpenByDevRecord(t_x502* hnd, const t_x502_devrec *devrec) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
if ((err == X502_ERR_OK) && ((devrec==NULL) || (devrec->sign!=X502_DEVREC_SIGN)))
|
||||
err = X502_ERR_INVALID_DEVICE_RECORD;
|
||||
if (X502_IsOpened(hnd) == X502_ERR_OK) {
|
||||
X502_Close(hnd);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->iface_hnd = (const t_x502_dev_iface *)(devrec->internal->iface);
|
||||
memcpy(hnd->info.serial, devrec->serial, X502_SERIAL_SIZE);
|
||||
memcpy(hnd->info.name, devrec->devname, X502_DEVNAME_SIZE);
|
||||
hnd->iface = devrec->iface;
|
||||
hnd->info.devflags = devrec->flags;
|
||||
err = hnd->iface_hnd->open(hnd, devrec);
|
||||
if (err == X502_ERR_OK) {
|
||||
X502_SetLChannel(hnd, 0, 0, X502_LCH_MODE_COMM, X502_ADC_RANGE_10, 0);
|
||||
hnd->set.lch_cnt = 1;
|
||||
hnd->set.adc_frame_delay = 0;
|
||||
hnd->set.sync_mode = X502_SYNC_INTERNAL;
|
||||
hnd->set.sync_start_mode = X502_SYNC_INTERNAL;
|
||||
|
||||
|
||||
hnd->set.ext_ref_freq = 0;
|
||||
hnd->streams = 0;
|
||||
|
||||
if (x502_is_E16(hnd)) {
|
||||
hnd->set.ref_freq = E16_REF_FREQ_48000KHZ;
|
||||
hnd->set.dac_range = E16_DAC_RANGE;
|
||||
hnd->set.dac_code_max = E16_DAC_SCALE_CODE_MAX;
|
||||
hnd->set.adc_code_max = E16_ADC_SCALE_CODE_MAX;
|
||||
hnd->set.f_scales = f_e16_scales;
|
||||
|
||||
hnd->set.adc_freq_div = E16_REF_FREQ_48000KHZ / E16_ADC_FREQ_DEFAULT;
|
||||
hnd->set.din_freq_div = E16_REF_FREQ_48000KHZ / E16_DIN_FREQ_DEFAULT;
|
||||
hnd->set.out_freq_div = E16_REF_FREQ_48000KHZ / E16_OUT_FREQ_DEFAULT;
|
||||
} else {
|
||||
hnd->set.ref_freq = X502_REF_FREQ_2000KHZ;
|
||||
hnd->set.dac_range = X502_DAC_RANGE;
|
||||
hnd->set.dac_code_max = X502_DAC_SCALE_CODE_MAX;
|
||||
hnd->set.adc_code_max = X502_ADC_SCALE_CODE_MAX;
|
||||
hnd->set.f_scales = f_x502_scales;
|
||||
|
||||
hnd->set.adc_freq_div = 1;
|
||||
hnd->set.din_freq_div = 1;
|
||||
hnd->set.out_freq_div = 2;
|
||||
}
|
||||
|
||||
hnd->flags = PRIV_FLAGS_OPENED;
|
||||
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->mutex_bf = osspec_mutex_create();
|
||||
if (hnd->mutex_bf == OSSPEC_INVALID_MUTEX)
|
||||
err = X502_ERR_MUTEX_CREATE;
|
||||
} else {
|
||||
hnd->mutex_bf = OSSPEC_INVALID_MUTEX;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
hnd->mutex_cfg = osspec_mutex_create();
|
||||
if (hnd->mutex_cfg == OSSPEC_INVALID_MUTEX)
|
||||
err = X502_ERR_MUTEX_CREATE;
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(hnd->info.devflags & X502_DEVFLAGS_FPGA_LOADED)) {
|
||||
err = X502_ERR_FPGA_NOT_LOADED;
|
||||
} else {
|
||||
|
||||
|
||||
/* определяем - в каком режиме работаем (BF или FPGA) */
|
||||
uint32_t bf_ctl;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_BF_CTL, &bf_ctl);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t mode = bf_ctl;
|
||||
if (mode & X502_REGBIT_BF_CTL_DBG_MODE_Msk) {
|
||||
hnd->mode = X502_MODE_DEBUG;
|
||||
} else if (mode & X502_REGBIT_BF_CTL_DSP_MODE_Msk) {
|
||||
hnd->mode = X502_MODE_DSP;
|
||||
} else {
|
||||
hnd->mode = X502_MODE_FPGA;
|
||||
}
|
||||
|
||||
|
||||
if (hnd->mode==X502_MODE_DSP) {
|
||||
/* если blackfin находится в состоянии сброса, то возвращаемся в режим
|
||||
FPGA, т.к. все команды к HostDMA все равно не выполнятся */
|
||||
if (!(bf_ctl & X502_REGBIT_BF_CTL_BF_RESET_Msk)) {
|
||||
err = X502_SetMode(hnd, X502_MODE_FPGA);
|
||||
} else {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
|
||||
/** @todo Для BlackFin проверить наличие прошивки */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* проверка захвата PLL (сейчас невозможна в режиме DSP) */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode!=X502_MODE_DSP)) {
|
||||
uint32_t val;
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOHARD_IO_MODE, &val);
|
||||
if (err == X502_ERR_OK) {
|
||||
if (!(val & X502_REGBIT_ADC_SLV_CLK_LOCK_Msk)) {
|
||||
err = X502_ERR_REF_FREQ_NOT_LOCKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* читаем информацию о версии прошивки ПЛИС'ов и наличии опций */
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t hard_id=0;
|
||||
int32_t id_err = hnd->iface_hnd->fpga_reg_read(hnd, hnd->iface_hnd->id_reg_addr, &hard_id);
|
||||
if (id_err == X502_ERR_OK) {
|
||||
hnd->info.fpga_ver = (hard_id >> 16) & 0x7FFF;
|
||||
hnd->info.plda_ver = (hard_id >> 4) & 0xF;
|
||||
hnd->info.board_rev = (hard_id >> 8) & 0xF;
|
||||
FILL_HARD_ID_FLAGS(hnd->info.devflags, hard_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* если был запущен сбор - то останавливаем его */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA)) {
|
||||
hnd->last_dout = 0;
|
||||
|
||||
if (hnd->iface_hnd->fpga_mode_init != NULL)
|
||||
err = hnd->iface_hnd->fpga_mode_init(hnd);
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0);
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_OUTSWAP_BFCTL, 0);
|
||||
|
||||
if ((err == X502_ERR_OK) && (hnd->iface_hnd->stream_running != NULL)) {
|
||||
int32_t running;
|
||||
unsigned ch;
|
||||
for (ch=0; (ch < X502_STREAM_CH_CNT) && (err == X502_ERR_OK); ch++) {
|
||||
err = hnd->iface_hnd->stream_running(hnd, ch, &running);
|
||||
if ((err == X502_ERR_OK) && running) {
|
||||
err = hnd->iface_hnd->stream_stop(hnd, ch, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* читаем информацию из EEPROM (в первую очередь -
|
||||
калибровочные коэффициенты) */
|
||||
if (err == X502_ERR_OK || err == X502_ERR_FPGA_NOT_LOADED) {
|
||||
int i;
|
||||
|
||||
for (i=0; i < X502_ADC_RANGE_CNT; i++) {
|
||||
hnd->info.cbr.adc[i].offs = 0;
|
||||
hnd->info.cbr.adc[i].k = 1.;
|
||||
}
|
||||
|
||||
for (i=0; i < X502_DAC_CH_CNT; i++) {
|
||||
hnd->info.cbr.dac[i].offs = 0;
|
||||
hnd->info.cbr.dac[i].k = 1;
|
||||
}
|
||||
|
||||
x502_check_eeprom(hnd, 0);
|
||||
}
|
||||
|
||||
/* записываем конфигурацию по умолчанию, чтобы быть уверенным,
|
||||
что установлена нужная конфигурация */
|
||||
if ((err == X502_ERR_OK) && (hnd->mode==X502_MODE_FPGA))
|
||||
err = X502_Configure(hnd, 0);
|
||||
//if (!err)
|
||||
// err = _fpga_reg_write(hnd, L502_REGS_IOHARD_PRELOAD_ADC, 1);
|
||||
|
||||
if ((err != X502_ERR_OK) && (err != X502_ERR_FPGA_NOT_LOADED) && (err != X502_ERR_REF_FREQ_NOT_LOCKED))
|
||||
X502_Close(hnd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_Open(t_x502_hnd hnd, const char* serial,
|
||||
const char *devname, t_x502_get_devinfo_list_cb get_list) {
|
||||
int32_t err = X502_CHECK_HND(hnd);
|
||||
int32_t get_info_res = 0;
|
||||
uint32_t fnd_cnt;
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
get_info_res = get_list(NULL, 0, 0, &fnd_cnt);
|
||||
if (get_info_res < 0) {
|
||||
err = get_info_res;
|
||||
} else if (!fnd_cnt) {
|
||||
err = X502_ERR_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
t_x502_devrec *info_list = malloc(sizeof(t_x502_devrec)*fnd_cnt);
|
||||
if (info_list==NULL) {
|
||||
err = X502_ERR_MEMORY_ALLOC;
|
||||
} else {
|
||||
/* получаем информацию по всем устройствам драйвера lpcie */
|
||||
get_info_res = get_list(info_list, fnd_cnt, 0, NULL);
|
||||
if (get_info_res < 0) {
|
||||
err = get_info_res;
|
||||
} else {
|
||||
int32_t i, ser_size=0, fnd=0, open_err = 0;
|
||||
|
||||
if (serial!=NULL) {
|
||||
/* если серийный задан - смотрим его размер, отсекая
|
||||
* все что начинается с признака кноца строки */
|
||||
for (ser_size=0; (ser_size < X502_SERIAL_SIZE) &&
|
||||
!((serial[ser_size]=='\0') ||
|
||||
(serial[ser_size]=='\n') ||
|
||||
(serial[ser_size]=='\r')); ser_size++)
|
||||
{}
|
||||
}
|
||||
|
||||
for (i=0; !fnd && (i < get_info_res); i++) {
|
||||
/* ищем устройство L502 с совпадающим серийным */
|
||||
if (((devname==NULL) || !strcmp(info_list[i].devname, devname)) &&
|
||||
((ser_size==0) || !strncmp(serial, info_list[i].serial,
|
||||
ser_size))) {
|
||||
/* пробуем открыть устройство */
|
||||
err = X502_OpenByDevRecord(hnd, &info_list[i]);
|
||||
|
||||
/* если серийный номер не был указан, то сохраняем
|
||||
код ошибки и идем дальше, пробовать открыть
|
||||
следующее устройство */
|
||||
if (err && (ser_size==0)) {
|
||||
open_err = err;
|
||||
err = 0;
|
||||
} else {
|
||||
/* иначе заканчиваем поиск */
|
||||
fnd = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* если не нашли устройство - устанавливаем соотвествующий код
|
||||
ошибки */
|
||||
if (!fnd) {
|
||||
err = open_err ? open_err : X502_ERR_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
X502_FreeDevRecordList(info_list, fnd_cnt);
|
||||
free(info_list);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size,
|
||||
uint32_t flags, uint32_t *devcnt, const char *devname,
|
||||
t_x502_get_devinfo_list_cb get_list) {
|
||||
uint32_t fnd_cnt=0, put_cnt=0;
|
||||
/* получаем количество устройств, поддерживаемых драйвером lpcie */
|
||||
int32_t res = get_list(NULL, 0, flags, &fnd_cnt);
|
||||
if ((res>=0) && fnd_cnt) {
|
||||
t_x502_devrec *info_list = malloc(sizeof(t_x502_devrec)*fnd_cnt);
|
||||
if (info_list==NULL) {
|
||||
res = X502_ERR_MEMORY_ALLOC;
|
||||
} else {
|
||||
/* получаем информацию по всем устройствам драйвера lpcie */
|
||||
res = get_list(info_list, fnd_cnt, flags, NULL);
|
||||
if (res>0) {
|
||||
int32_t i;
|
||||
for (i=0; i < res; i++) {
|
||||
/* проверяем, что это устройство - E502 */
|
||||
if (!strcmp(info_list[i].devname, devname)) {
|
||||
/* если есть место в списке, то сохраняем серийный номер
|
||||
устройства */
|
||||
if (put_cnt < size) {
|
||||
memcpy(serials[put_cnt], info_list[i].serial,
|
||||
X502_SERIAL_SIZE);
|
||||
}
|
||||
put_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
X502_FreeDevRecordList(info_list, fnd_cnt);
|
||||
free(info_list);
|
||||
}
|
||||
}
|
||||
|
||||
if (devcnt != NULL)
|
||||
*devcnt = put_cnt;
|
||||
|
||||
return res < 0 ? res : put_cnt > size ? (int32_t)size : (int32_t)put_cnt;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FreeDevRecordList(t_x502_devrec *list, uint32_t size) {
|
||||
uint32_t i;
|
||||
int32_t err = X502_ERR_OK;
|
||||
if (list!=NULL) {
|
||||
for (i=0; (i < size) && (err==X502_ERR_OK); i++) {
|
||||
if (list[i].sign!=X502_DEVREC_SIGN) {
|
||||
err = X502_ERR_INVALID_DEVICE_RECORD;
|
||||
} else {
|
||||
t_x502_devrec_inptr *devinfo_ptr = (t_x502_devrec_inptr*)list[i].internal;
|
||||
if (devinfo_ptr != NULL) {
|
||||
const t_x502_dev_iface *iface = (const t_x502_dev_iface *)devinfo_ptr->iface;
|
||||
if (iface!=NULL)
|
||||
iface->free_devinfo_ptr(devinfo_ptr);
|
||||
|
||||
}
|
||||
list[i].internal = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetDevInfo(t_x502_hnd hnd, t_x502_info* info) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (info==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
if (err == X502_ERR_OK)
|
||||
*info = hnd->info;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_GetNextExpectedLchNum(t_x502_hnd hnd, uint32_t *lch) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (lch==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK)
|
||||
*lch = hnd->proc_adc_ch;
|
||||
return err;
|
||||
}
|
||||
|
||||
#define STREAM_IN_WRD_TYPE(wrd) wrd & 0x80000000 ? STREAM_IN_WRD_ADC : \
|
||||
(wrd & 0xFF000000) == 0x0 ? STREAM_IN_WRD_DIN : \
|
||||
((wrd & 0xFF000000)>>24) == 0x01 ? STREAM_IN_WRD_MSG : STREAM_IN_WRD_USR
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessAdcData(t_x502_hnd hnd, const uint32_t* src, double *dest,
|
||||
uint32_t *size, uint32_t flags) {
|
||||
if (size == NULL)
|
||||
return X502_ERR_INVALID_POINTER;
|
||||
return X502_ProcessDataWithUserExt(hnd, src, *size, flags, dest, size,
|
||||
NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessData(t_x502_hnd hnd, const uint32_t *src, uint32_t size, uint32_t flags,
|
||||
double *adc_data, uint32_t *adc_data_size,
|
||||
uint32_t *din_data, uint32_t *din_data_size) {
|
||||
return X502_ProcessDataWithUserExt(hnd, src, size, flags, adc_data, adc_data_size,
|
||||
din_data, din_data_size, NULL, NULL);
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_ProcessDataWithUserExt(t_x502_hnd hnd, const uint32_t* src, uint32_t size,
|
||||
uint32_t flags, double *adc_data,
|
||||
uint32_t *adc_data_size, uint32_t *din_data, uint32_t *din_data_size,
|
||||
uint32_t *usr_data, uint32_t *usr_data_size) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (adc_data_size==NULL) && (adc_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && (din_data_size==NULL) && (din_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && (usr_data_size==NULL) && (usr_data!=NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t adc_cnt = 0, din_cnt=0, usr_cnt = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i=0; (i<size) && (err == X502_ERR_OK); i++) {
|
||||
register uint32_t wrd = src[i];
|
||||
t_stream_in_wrd_type type = STREAM_IN_WRD_TYPE(wrd);
|
||||
/* проверяем - это данные от АЦП или цифровых входов */
|
||||
switch (type) {
|
||||
case STREAM_IN_WRD_ADC: {
|
||||
uint32_t ch_num = (wrd >> 24) & 0xF;
|
||||
uint32_t ch_mode = (wrd >> 28) & 0x3;
|
||||
int32_t val;
|
||||
uint32_t range;
|
||||
|
||||
/* проверяем совпадение каналов */
|
||||
switch (ch_mode) {
|
||||
case 0:
|
||||
ch_mode = X502_LCH_MODE_DIFF;
|
||||
break;
|
||||
case 1:
|
||||
ch_mode = X502_LCH_MODE_COMM;
|
||||
break;
|
||||
case 2:
|
||||
ch_mode = X502_LCH_MODE_COMM;
|
||||
ch_num+=16;
|
||||
break;
|
||||
case 3:
|
||||
ch_mode = X502_LCH_MODE_ZERO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & X502_PROC_FLAGS_DONT_CHECK_CH) &&
|
||||
((hnd->set.lch[hnd->proc_adc_ch].mode != ch_mode) ||
|
||||
(hnd->set.lch[hnd->proc_adc_ch].ch != ch_num))) {
|
||||
err = X502_ERR_PROC_INVALID_CH_NUM;
|
||||
} else {
|
||||
/* проверяем формат - пришло откалиброванное 24-битное слово,
|
||||
или неоткалиброванное 16-битное */
|
||||
if (wrd & 0x40000000) {
|
||||
val = wrd & 0xFFFFFF;
|
||||
if (wrd & 0x800000)
|
||||
val |= 0xFF000000;
|
||||
|
||||
range = hnd->set.lch[hnd->proc_adc_ch].range;
|
||||
} else {
|
||||
range = (wrd >> 16) & 0x7;
|
||||
if (!(flags & X502_PROC_FLAGS_DONT_CHECK_CH) &&
|
||||
(range != hnd->set.lch[hnd->proc_adc_ch].range)) {
|
||||
err = X502_ERR_PROC_INVALID_CH_RANGE;
|
||||
} else {
|
||||
val = wrd & 0xFFFF;
|
||||
if (wrd & 0x8000)
|
||||
val |= 0xFFFF0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
double res_val = val;
|
||||
if (flags & X502_PROC_FLAGS_VOLT) {
|
||||
res_val = hnd->set.f_scales[range]*res_val/hnd->set.adc_code_max;
|
||||
}
|
||||
|
||||
|
||||
if ((adc_data!=NULL) && (adc_cnt<*adc_data_size)) {
|
||||
*adc_data++ = res_val;
|
||||
adc_cnt++;
|
||||
} else if (adc_data==NULL) {
|
||||
adc_cnt++;
|
||||
}
|
||||
|
||||
if (++hnd->proc_adc_ch ==hnd->set.lch_cnt)
|
||||
hnd->proc_adc_ch = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STREAM_IN_WRD_DIN:
|
||||
if ((din_data!=NULL) && (din_cnt<*din_data_size)) {
|
||||
*din_data++ = wrd & 0x3FFFF;
|
||||
din_cnt++;
|
||||
} else if (din_data==NULL) {
|
||||
din_cnt++;
|
||||
}
|
||||
break;
|
||||
case STREAM_IN_WRD_MSG:
|
||||
err = wrd==X502_STREAM_IN_MSG_OVERFLOW ? X502_ERR_STREAM_OVERFLOW :
|
||||
X502_ERR_UNSUP_STREAM_MSG;
|
||||
break;
|
||||
case STREAM_IN_WRD_USR:
|
||||
if ((usr_data!=NULL) && (usr_cnt<*usr_data_size)) {
|
||||
*usr_data++ = wrd;
|
||||
usr_cnt++;
|
||||
} else if (usr_data==NULL) {
|
||||
usr_cnt++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (adc_data_size!=NULL)
|
||||
*adc_data_size = adc_cnt;
|
||||
if (din_data_size!=NULL)
|
||||
*din_data_size = din_cnt;
|
||||
if (usr_data_size!=NULL)
|
||||
*usr_data_size = usr_cnt;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t prepare_dac_wrd(t_x502_hnd hnd, double val, uint32_t flags, const t_x502_cbr_coef* coef) {
|
||||
uint16_t wrd = 0;
|
||||
if (flags & X502_DAC_FLAGS_VOLT) {
|
||||
val = (val / hnd->set.dac_range) * hnd->set.dac_code_max;
|
||||
}
|
||||
if (flags & X502_DAC_FLAGS_CALIBR) {
|
||||
val = (val + coef->offs) * coef->k;
|
||||
}
|
||||
if (val > SHRT_MAX) {
|
||||
wrd = SHRT_MAX;
|
||||
} else
|
||||
if (val < SHRT_MIN) {
|
||||
wrd = SHRT_MIN;
|
||||
} else {
|
||||
wrd = val;
|
||||
}
|
||||
return wrd;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_PrepareData(t_x502_hnd hnd, const double* dac1, const double* dac2,
|
||||
const uint32_t* digout, uint32_t size, int32_t flags,
|
||||
uint32_t* out_buf) {
|
||||
int err = X502_CHECK_HND_OPENED(hnd);
|
||||
if ((err == X502_ERR_OK) && (out_buf==NULL))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
if ((err == X502_ERR_OK) && ((dac1==NULL) && (dac2==NULL) && (digout==NULL)))
|
||||
err = X502_ERR_INVALID_POINTER;
|
||||
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t i;
|
||||
for (i = 0; (i < size) && (err == X502_ERR_OK); i++) {
|
||||
if ((dac1 != NULL) && (hnd->streams & X502_STREAM_DAC1)) {
|
||||
uint32_t wrd = prepare_dac_wrd(hnd, *dac1++, flags, &hnd->info.cbr.dac[0]);
|
||||
*out_buf++ = wrd | X502_STREAM_OUT_WORD_TYPE_DAC1;
|
||||
}
|
||||
if ((dac2 != NULL) && (hnd->streams & X502_STREAM_DAC2)) {
|
||||
uint32_t wrd = prepare_dac_wrd(hnd, *dac2++, flags, &hnd->info.cbr.dac[1]);
|
||||
*out_buf++ = wrd | X502_STREAM_OUT_WORD_TYPE_DAC2;
|
||||
}
|
||||
if ((digout != NULL) && (hnd->streams & X502_STREAM_DOUT)) {
|
||||
uint32_t wrd = *digout++;
|
||||
*out_buf++ = (wrd &0x3FFFF)
|
||||
| X502_STREAM_OUT_WORD_TYPE_DOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FpgaRegWrite(t_x502_hnd hnd, uint32_t reg, uint32_t val) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->fpga_reg_write(hnd, reg & 0xFFFF, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_FpgaRegRead(t_x502_hnd hnd, uint32_t reg, uint32_t *val) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->fpga_reg_read(hnd, reg, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(uint32_t) X502_GetLibraryVersion(void) {
|
||||
return (X502API_VER_MAJOR << 24) | (X502API_VER_MINOR<<16) |
|
||||
(X502API_VER_PATCH << 8);
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_DevRecordInit(t_x502_devrec *rec) {
|
||||
if (rec!=NULL) {
|
||||
memset(rec, 0, sizeof(t_x502_devrec));
|
||||
rec->sign = X502_DEVREC_SIGN;
|
||||
}
|
||||
return X502_ERR_OK;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_LedBlink(t_x502_hnd hnd) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
int32_t err2;
|
||||
err = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_LED, 0) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_LED, 0);
|
||||
SLEEP_MS(200);
|
||||
err2 = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_LED, 1) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_LED, 1);
|
||||
if (err == X502_ERR_OK)
|
||||
err = err2;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
X502_EXPORT(int32_t) X502_SetDigInPullup(t_x502_hnd hnd, uint32_t pullups) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
uint32_t val = 0;
|
||||
if (pullups & X502_PULLUPS_DI_L)
|
||||
val |= 0x1;
|
||||
if (pullups & X502_PULLUPS_DI_H)
|
||||
val |= 0x2;
|
||||
if (pullups & X502_PULLUPS_DI_SYN1)
|
||||
val |= 0x4;
|
||||
if (pullups & X502_PULLUPS_DI_SYN2)
|
||||
val |= 0x8;
|
||||
if (pullups & X502_PULLDOWN_CONV_IN)
|
||||
val |= 0x10;
|
||||
if (pullups & X502_PULLDOWN_START_IN)
|
||||
val |= 0x20;
|
||||
if (pullups & E16_MODE_RELAY_ON)
|
||||
val |= 0x40;
|
||||
|
||||
err = hnd->mode == X502_MODE_DSP ? bf_fpga_reg_wr(hnd, X502_REGS_IOHARD_DIGIN_PULLUP, val) :
|
||||
X502_FpgaRegWrite(hnd, X502_REGS_IOHARD_DIGIN_PULLUP, val);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
X502_EXPORT(int32_t) X502_CheckFeature(t_x502_hnd hnd, uint32_t feature) {
|
||||
int32_t err = X502_CHECK_HND_OPENED(hnd);
|
||||
if (err == X502_ERR_OK) {
|
||||
err = hnd->iface_hnd->check_feature(hnd, feature);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI DllMain(HINSTANCE hmod, DWORD reason, LPVOID resvd) {
|
||||
switch (reason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user