manually merged with ARM version

This commit is contained in:
2025-11-13 17:43:55 +03:00
parent f978759ae0
commit 04015fb4cb
463 changed files with 119514 additions and 45 deletions

795
x502/x502api_config.c Normal file
View File

@ -0,0 +1,795 @@
#include "x502api_private.h"
#include "x502_fpga_regs.h"
#define SYNC_FREQ_CODE(mode) ((mode == X502_SYNC_DI_SYN2_RISE) ? X502_SYNC_DI_SYN1_FALL : \
(mode == X502_SYNC_DI_SYN1_FALL) ? X502_SYNC_DI_SYN2_RISE : mode)
#define CHECK_SYNC_MODE(mode) (((mode)) != X502_SYNC_INTERNAL) \
&& ((mode)!=X502_SYNC_EXTERNAL_MASTER) \
&& ((mode)!=X502_SYNC_DI_SYN1_RISE) \
&& ((mode)!=X502_SYNC_DI_SYN2_RISE) \
&& ((mode)!=X502_SYNC_DI_SYN1_FALL) \
&& ((mode)!=X502_SYNC_DI_SYN2_FALL) \
? X502_ERR_INVALID_SYNC_MODE : X502_ERR_OK
/** Максимальное значения частоты АЦП для варианта E16*/
#define E16_ADC_FREQ_MAX 1000000
/** Максимальное значения частоты DIN для варианта E16*/
#define E16_DIN_FREQ_MAX 1000000
/** Максимальное значения частоты OUT для варианта E16*/
#define E16_OUT_FREQ_MAX 1000000
static const uint16_t f_regadd_k[X502_ADC_RANGE_CNT] = {X502_REGS_IOARITH_K10,
X502_REGS_IOARITH_K5,
X502_REGS_IOARITH_K2,
X502_REGS_IOARITH_K1,
X502_REGS_IOARITH_K05,
X502_REGS_IOARITH_K02};
static const uint16_t f_regadd_offs[X502_ADC_RANGE_CNT] = {X502_REGS_IOARITH_B10,
X502_REGS_IOARITH_B5,
X502_REGS_IOARITH_B2,
X502_REGS_IOARITH_B1,
X502_REGS_IOARITH_B05,
X502_REGS_IOARITH_B02};
static uint32_t f_get_out_freq_div_min(double ref_freq) {
return ref_freq > X502_OUT_FREQ_REF_LF_VAL ? X502_OUT_FREQ_DIV_MIN : X502_OUT_FREQ_DIV_MIN_REF_LF;
}
X502_EXPORT(int32_t) X502_SetLChannel(t_x502_hnd hnd, uint32_t lch, uint32_t phy_ch,
uint32_t mode, uint32_t range, uint32_t avg) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
/* Для измерения собственного нуля номер канала не имеет значения */
if (mode == X502_LCH_MODE_ZERO)
phy_ch = 0;
if ((mode != X502_LCH_MODE_COMM) && (mode != X502_LCH_MODE_DIFF) &&
(mode != X502_LCH_MODE_ZERO)) {
err = X502_ERR_INVALID_LCH_MODE;
} else if ((phy_ch >= X502_ADC_COMM_CH_CNT) ||
((mode == X502_LCH_MODE_DIFF) && (phy_ch >= X502_ADC_DIFF_CH_CNT))) {
err = X502_ERR_INVALID_LCH_PHY_NUMBER;
} else if (range >= X502_ADC_RANGE_CNT) {
err = X502_ERR_INVALID_LCH_RANGE;
} else if (avg > X502_LCH_AVG_SIZE_MAX) {
err = X502_ERR_INVALID_LCH_AVG_SIZE;
}
if (!err) {
hnd->set.lch[lch].ch = phy_ch;
hnd->set.lch[lch].range = range;
hnd->set.lch[lch].mode = mode;
hnd->set.lch[lch].avg = avg;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetLChannelCount(t_x502_hnd hnd, uint32_t lch_cnt) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if (lch_cnt > X502_LTABLE_MAX_CH_CNT) {
err = X502_ERR_INVALID_LTABLE_SIZE;
} else if (x502_is_E16(hnd) && lch_cnt > E16_LTABLE_MAX_CH_CNT) {
err = X502_ERR_INVALID_LTABLE_SIZE;
} else {
hnd->set.lch_cnt = lch_cnt;
}
}
return err;
}
X502_EXPORT(int32_t) X502_GetLChannelCount(t_x502_hnd hnd, uint32_t* lch_cnt) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (lch_cnt==NULL))
err = X502_ERR_INVALID_POINTER;
if (!err)
*lch_cnt = hnd->set.lch_cnt;
return err;
}
X502_EXPORT(int32_t) X502_SetAdcFreqDivider(t_x502_hnd hnd, uint32_t adc_freq_div) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if ((adc_freq_div==0) ||
(x502_is_E16(hnd) && adc_freq_div > E16_ADC_FREQ_DIV_MAX) ||
(!x502_is_E16(hnd) && adc_freq_div > X502_ADC_FREQ_DIV_MAX)) {
err = X502_ERR_INVALID_ADC_FREQ_DIV;
} else {
hnd->set.adc_freq_div = adc_freq_div;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetAdcInterframeDelay(t_x502_hnd hnd, uint32_t delay) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err && (delay > X502_ADC_INTERFRAME_DELAY_MAX))
err = X502_ERR_INVALID_INTERFRAME_DELAY;
if (!err) {
hnd->set.adc_frame_delay = delay;
}
return err;
}
X502_EXPORT(int32_t) X502_SetDinFreqDivider(t_x502_hnd hnd, uint32_t din_freq_div) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if ((din_freq_div==0) ||
(x502_is_E16(hnd) && din_freq_div > E16_DIN_FREQ_DIV_MAX) ||
(!x502_is_E16(hnd) && din_freq_div > X502_DIN_FREQ_DIV_MAX)) {
err = X502_ERR_INVALID_ADC_FREQ_DIV;
} else {
hnd->set.din_freq_div = din_freq_div;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetOutFreqDivider(t_x502_hnd hnd, uint32_t out_freq_div) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
/* Проверяем, поддерживается ли возможность установить значение, отличное от стандартного */
if (out_freq_div != X502_OUT_FREQ_DIV_DEFAULT) {
err = X502_CheckFeature(hnd, X502_FEATURE_OUT_FREQ_DIV);
}
}
if (!err) {
double ref_freq;
X502_GetRefFreqValue(hnd, &ref_freq);
if ((out_freq_div < f_get_out_freq_div_min(ref_freq)) ||
(x502_is_E16(hnd) && out_freq_div > E16_OUT_FREQ_DIV_MAX) ||
(!x502_is_E16(hnd) && out_freq_div > X502_OUT_FREQ_DIV_MAX)) {
err = X502_ERR_INVALID_OUT_FREQ_DIV;
} else {
hnd->set.out_freq_div = out_freq_div;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetMode(t_x502_hnd hnd, uint32_t mode) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err && (mode==X502_MODE_DSP) &&
!(hnd->info.devflags & X502_DEVFLAGS_BF_PRESENT)) {
err = X502_ERR_BF_NOT_PRESENT;
}
if (!err) {
uint32_t val;
err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_BF_CTL, &val);
if (!err) {
val &= ~(X502_REGBIT_BF_CTL_CLK_DIV_Msk | X502_REGBIT_BF_CTL_DBG_MODE_Msk | X502_REGBIT_BF_CTL_DSP_MODE_Msk);
if (mode==X502_MODE_DSP) {
/* в DSP режиме сброс должен быть снят с blackfin, иначе не будут работать
команды по HostDMA */
val |= X502_REGBIT_BF_CTL_DSP_MODE_Msk | X502_REGBIT_BF_CTL_BF_RESET_Msk;
} else if (mode==X502_MODE_DEBUG) {
val |= X502_REGBIT_BF_CTL_DBG_MODE_Msk;
} else if (mode!=X502_MODE_FPGA) {
err = X502_ERR_INVALID_MODE;
}
}
if (!err)
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CTL, val);
/* при переходе в режим DSP сбрасываем автомат HDMA */
if (!err && (mode==X502_MODE_DSP))
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_BF_CMD, X502_BF_CMD_HDMA_RST);
if (!err)
hnd->mode = mode;
}
return err;
}
X502_EXPORT(int32_t) X502_GetMode(t_x502_hnd hnd, uint32_t* mode) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (mode==NULL))
err = X502_ERR_INVALID_POINTER;
if (!err) {
*mode = hnd->mode;
}
return err;
}
#define IS_E16_FREQ(hnd, ref_freq) ((hnd && x502_is_E16(hnd)) || (uint32_t)ref_freq == E16_REF_FREQ_48000KHZ)
X502_EXPORT(int32_t) X502_CalcAdcFreq2(t_x502_hnd hnd, double ref_freq, uint32_t lch_cnt, double *f_acq,
double *f_frame, uint32_t *adc_freq_div, uint32_t *adc_frame_delay) {
int32_t err = (f_acq==NULL) ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
if (err == X502_ERR_OK) {
uint32_t cur_adc_freq_div, cur_frame_delay = 0;
uint32_t div_max = X502_ADC_FREQ_DIV_MAX;
double set_freq = *f_acq;
if (set_freq <= 0) {
if (IS_E16_FREQ(hnd, ref_freq)) {
set_freq = E16_ADC_FREQ_DEFAULT;
} else {
set_freq = ref_freq;
}
}
if (IS_E16_FREQ(hnd, ref_freq)) {
div_max = E16_ADC_FREQ_DIV_MAX;
if (set_freq > E16_ADC_FREQ_MAX) {
set_freq = E16_ADC_FREQ_MAX;
}
}
cur_adc_freq_div = (uint32_t)(ref_freq/set_freq+0.49);
if (cur_adc_freq_div == 0)
cur_adc_freq_div = 1;
if (cur_adc_freq_div > div_max)
cur_adc_freq_div = div_max;
set_freq = ref_freq/cur_adc_freq_div;
*f_acq = set_freq;
if (f_frame==NULL) {
cur_frame_delay = 0;
} else {
if (lch_cnt == 0)
lch_cnt = 1;
if (*f_frame <= 0) {
cur_frame_delay = 0;
} else {
int32_t frame_div = (int32_t)((ref_freq/(*f_frame)
- lch_cnt*ref_freq/set_freq)+0.49);
cur_frame_delay = frame_div <=0 ? 0 :
frame_div > X502_ADC_INTERFRAME_DELAY_MAX ?
X502_ADC_INTERFRAME_DELAY_MAX : frame_div;
}
*f_frame = 1./(lch_cnt/set_freq +
cur_frame_delay/ref_freq);
}
if (adc_freq_div != NULL)
*adc_freq_div = cur_adc_freq_div;
if (adc_frame_delay != NULL)
*adc_frame_delay = cur_frame_delay;
}
return err;
}
X502_EXPORT(int32_t) X502_CalcAdcFreq(double ref_freq, uint32_t lch_cnt, double *f_acq,
double *f_frame, uint32_t *adc_freq_div, uint32_t *adc_frame_delay) {
return X502_CalcAdcFreq2(NULL, ref_freq, lch_cnt, f_acq, f_frame, adc_freq_div, adc_frame_delay);
}
X502_EXPORT(int32_t) X502_SetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
double ref_freq;
X502_GetRefFreqValue(hnd, &ref_freq);
err = X502_CalcAdcFreq2(hnd, ref_freq, hnd->set.lch_cnt, f_acq, f_frame,
&hnd->set.adc_freq_div, &hnd->set.adc_frame_delay);
}
return err;
}
X502_EXPORT(int32_t) X502_GetAdcFreq(t_x502_hnd hnd, double *f_acq, double *f_frame) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (f_acq == NULL) && (f_frame==NULL))
err = X502_ERR_INVALID_POINTER;
if (!err) {
double ref_freq, set_freq;
X502_GetRefFreqValue(hnd, &ref_freq);
set_freq = ref_freq/hnd->set.adc_freq_div;
if (f_acq!=NULL) {
*f_acq = set_freq;
}
if (f_frame!=NULL) {
*f_frame = 1./(hnd->set.lch_cnt/set_freq +
hnd->set.adc_frame_delay/ref_freq);
}
}
return err;
}
X502_EXPORT(int32_t) X502_CalcDinFreq2(t_x502_hnd hnd, double ref_freq, double *f_din, uint32_t *result_freq_div) {
int32_t err = f_din==NULL ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
if (err == X502_ERR_OK) {
uint32_t freq_div;
double set_freq = *f_din;
uint32_t div_max = X502_DIN_FREQ_DIV_MAX;
if (set_freq<=0) {
if (IS_E16_FREQ(hnd, ref_freq)) {
set_freq = E16_DIN_FREQ_DEFAULT;
} else {
set_freq = ref_freq;
}
}
if (IS_E16_FREQ(hnd, ref_freq)) {
div_max = E16_DIN_FREQ_DIV_MAX;
if (set_freq > E16_DIN_FREQ_MAX) {
set_freq = E16_DIN_FREQ_MAX;
}
}
freq_div = (uint32_t)(ref_freq/set_freq+0.49);
if (freq_div == 0)
freq_div = 1;
if (freq_div > div_max)
freq_div = div_max;
set_freq = ref_freq/freq_div;
*f_din = set_freq;
if (result_freq_div != NULL)
*result_freq_div = freq_div;
}
return err;
}
X502_EXPORT(int32_t) X502_CalcDinFreq(double ref_freq, double *f_din, uint32_t *result_freq_div) {
return X502_CalcDinFreq2(NULL, ref_freq, f_din, result_freq_div);
}
X502_EXPORT(int32_t) X502_SetDinFreq(t_x502_hnd hnd, double *f_din) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
double ref_freq;
X502_GetRefFreqValue(hnd, &ref_freq);
err = X502_CalcDinFreq2(hnd, ref_freq, f_din, &hnd->set.din_freq_div);
}
return err;
}
X502_EXPORT(int32_t) X502_CalcOutFreq2(t_x502_hnd hnd, double ref_freq, double *f_dout, uint32_t *result_freq_div) {
int32_t err = f_dout==NULL ? X502_ERR_INVALID_POINTER : X502_ERR_OK;
if (err == X502_ERR_OK) {
const uint32_t out_div_min = f_get_out_freq_div_min(ref_freq);
uint32_t out_freq_div;
uint32_t div_max = X502_OUT_FREQ_DIV_MAX;
double set_freq = *f_dout;
if (set_freq <= 0) {
if (IS_E16_FREQ(hnd, ref_freq)) {
set_freq = E16_OUT_FREQ_DEFAULT;
} else {
set_freq = ref_freq;
}
}
if (IS_E16_FREQ(hnd, ref_freq)) {
div_max = E16_OUT_FREQ_DIV_MAX;
if (set_freq > E16_OUT_FREQ_MAX) {
set_freq = E16_OUT_FREQ_MAX;
}
}
out_freq_div = (uint32_t)(ref_freq/set_freq+0.49);
if (out_freq_div < out_div_min)
out_freq_div = out_div_min;
if (out_freq_div > div_max)
out_freq_div = div_max;
set_freq = ref_freq/out_freq_div;
*f_dout = set_freq;
if (result_freq_div != NULL)
*result_freq_div = out_freq_div;
}
return err;
}
X502_EXPORT(int32_t) X502_CalcOutFreq(double ref_freq, double *f_dout, uint32_t *result_freq_div) {
return X502_CalcOutFreq2(NULL, ref_freq, f_dout, result_freq_div);
}
X502_EXPORT(int32_t) X502_SetOutFreq(t_x502_hnd hnd, double *f_dout) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err && (f_dout==NULL))
err = X502_ERR_INVALID_POINTER;
if (!err) {
double ref_freq;
X502_GetRefFreqValue(hnd, &ref_freq);
/* Если не поддерживается возможность установки нестандартного делителя, то
всегда устанавливаем стандартный */
if (X502_CheckFeature(hnd, X502_FEATURE_OUT_FREQ_DIV) != X502_ERR_OK) {
hnd->set.out_freq_div = X502_OUT_FREQ_DIV_DEFAULT;
*f_dout = ref_freq/hnd->set.out_freq_div;
} else {
err = X502_CalcOutFreq2(hnd, ref_freq, f_dout, &hnd->set.out_freq_div);
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetRefFreq(t_x502_hnd hnd, uint32_t freq) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if (x502_is_E16(hnd)) {
// для E16 ref freq всегда 48 МГц
hnd->set.ref_freq = E16_REF_FREQ_48000KHZ;
} else {
hnd->set.ref_freq = freq;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetExtRefFreqValue(t_x502_hnd hnd, double freq) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err)
hnd->set.ext_ref_freq = freq;
return err;
}
X502_EXPORT(int32_t) X502_SetAdcSyncStartValue(t_x502_hnd hnd, uint32_t phy_ch, uint32_t mode, uint32_t range, double value) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
hnd->set.adc_sync_ch = phy_ch;
hnd->set.adc_sync_range = range;
hnd->set.adc_sync_mode = mode;
hnd->set.adc_sync_val = value;
}
return err;
}
X502_EXPORT(int32_t) X502_GetRefFreqValue(t_x502_hnd hnd, double *freq) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err) {
if ((hnd->set.sync_mode == X502_SYNC_INTERNAL) ||
!(hnd->set.ext_ref_freq > 0)) {
*freq = hnd->set.ref_freq;
} else {
*freq = hnd->set.ext_ref_freq;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetSyncMode(t_x502_hnd hnd, uint32_t sync_mode) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
err = CHECK_SYNC_MODE(sync_mode);
}
if (!err) {
hnd->set.sync_mode = sync_mode;
}
return err;
}
X502_EXPORT(int32_t) X502_SetSyncStartMode(t_x502_hnd hnd, uint32_t sync_start_mode) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if (sync_start_mode==E16_SYNC_ADC_EDGE_RISE ||
sync_start_mode==E16_SYNC_ADC_EDGE_FALL ||
sync_start_mode==E16_SYNC_ADC_ABOVE_LEVEL ||
sync_start_mode==E16_SYNC_ADC_BELOW_LEVEL) {
if (x502_is_E16(hnd) == false) {
// реализовано только в E16
return X502_ERR_INVALID_SYNC_MODE;
}
} else {
err = CHECK_SYNC_MODE(sync_start_mode);
}
}
if (!err) {
hnd->set.sync_start_mode = sync_start_mode;
}
return err;
}
uint32_t get_ltable_val(t_x502_hnd hnd, uint32_t phy_ch, uint32_t mode, uint32_t range, uint32_t avg) {
uint32_t wrd = ((phy_ch & 0xF) << 3) | (range & 0x7);
if (mode == X502_LCH_MODE_ZERO) {
wrd |= (3 << 7);
} else if (mode == X502_LCH_MODE_COMM) {
wrd |= (phy_ch & 0x10 ? 2 : 1) << 7;
}
if (avg) {
uint32_t avg_val = avg;
if (avg_val > hnd->set.adc_freq_div)
avg_val = hnd->set.adc_freq_div;
wrd |= ((avg_val-1) & 0x7F) << 9;
}
return wrd;
}
X502_EXPORT(int32_t) X502_Configure(t_x502_hnd hnd, uint32_t flags) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
/* Проверяем правильность установленной опорной частоты.
Для внутренней может быть только одно из двух значений,
для внешней главное, чтобы не принимало требуемой */
if ((hnd->set.sync_mode==X502_SYNC_INTERNAL)
&& (hnd->set.ref_freq!=E16_REF_FREQ_48000KHZ)
&& (hnd->set.ref_freq!=X502_REF_FREQ_2000KHZ)
&&(hnd->set.ref_freq!=X502_REF_FREQ_1500KHZ)) {
err = X502_ERR_INVALID_REF_FREQ;
} else if (hnd->set.ext_ref_freq > 2000000) {
err = X502_ERR_INVALID_REF_FREQ;
}
}
if (!err) {
if (hnd->mode == X502_MODE_FPGA) {
uint32_t ch;
/* записываем логическую таблицу */
for (ch=0; (ch < hnd->set.lch_cnt) && !err; ch++) {
uint32_t wrd = get_ltable_val(hnd, hnd->set.lch[ch].ch, hnd->set.lch[ch].mode, hnd->set.lch[ch].range, hnd->set.lch[ch].avg);
err = hnd->iface_hnd->fpga_reg_write(hnd, (X502_REGS_IOHARD_LTABLE +
hnd->set.lch_cnt - 1 - ch) & 0xFFFF, wrd);
}
if (!err) {
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_LCH_CNT,
hnd->set.lch_cnt-1);
}
if (!err) {
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ADC_FREQ_DIV,
hnd->set.adc_freq_div-1);
}
if (!err) {
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_ADC_FREQ_DIV,
hnd->set.adc_freq_div-1);
}
if (!err) {
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ADC_FRAME_DELAY,
hnd->set.adc_frame_delay);
}
if (!err) {
// для варианта E16 ref_freq будет всегда 48000000
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_IO_MODE,
(SYNC_FREQ_CODE(hnd->set.sync_mode) & 0x7)
| ((hnd->set.sync_start_mode&0xF)<<3)
| ((hnd->set.ref_freq==X502_REF_FREQ_2000KHZ ? X502_MODE_REF_FREQ_2000 :
(hnd->set.ref_freq==X502_REF_FREQ_1500KHZ ? X502_MODE_REF_FREQ_1500: E16_MODE_REF_FREQ_48000)) << 7)
| (((hnd->set.out_freq_div-1) & (x502_is_E16(hnd) ? 0x7FFF : 0x3FF))<<9));
}
if (x502_is_E16(hnd)) {
// старт по аналоговому сигналу реализован только в E16
if (!err) {
uint32_t wrd = get_ltable_val(hnd, hnd->set.adc_sync_ch, hnd->set.adc_sync_mode, hnd->set.adc_sync_range, 0);
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_N_CHAN_SYN, wrd);
}
if (!err) {
uint32_t threshold;
threshold = hnd->set.adc_sync_val / hnd->set.f_scales[hnd->set.adc_sync_range] * E16_ADC_SCALE_CODE_MAX;
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_THRESHOLD, threshold);
}
}
if (!err) {
err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_DIGIN_FREQ_DIV,
hnd->set.din_freq_div-1);
}
} else if (hnd->mode == X502_MODE_DSP) {
uint32_t ch;
err = x502_bf_set_par(hnd, L502_BF_PARAM_LCH_CNT, &hnd->set.lch_cnt, 1);
for (ch=0; !err && (ch < hnd->set.lch_cnt); ch++) {
uint32_t ch_par[] = {ch, hnd->set.lch[ch].ch,
hnd->set.lch[ch].mode,
hnd->set.lch[ch].range,
hnd->set.lch[ch].avg > hnd->set.adc_freq_div ?
hnd->set.adc_freq_div : hnd->set.lch[ch].avg} ;
err = x502_bf_set_par(hnd, L502_BF_PARAM_LCH, ch_par,
sizeof(ch_par)/sizeof(ch_par[0]));
}
if (!err) {
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_FREQ_DIV,
&hnd->set.adc_freq_div, 1);
}
if (!err) {
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_FRAME_DELAY,
&hnd->set.adc_frame_delay, 1);
}
if (!err) {
err = x502_bf_set_par(hnd, L502_BF_PARAM_REF_FREQ_SRC,
&hnd->set.ref_freq, 1);
}
if (!err) {
uint32_t sync_code = SYNC_FREQ_CODE(hnd->set.sync_mode);
err = x502_bf_set_par(hnd, L502_BF_PARAM_SYNC_MODE,
&sync_code, 1);
}
if (!err) {
err = x502_bf_set_par(hnd, L502_BF_PARAM_SYNC_START_MODE,
&hnd->set.sync_start_mode, 1);
}
if (!err) {
err = x502_bf_set_par(hnd, L502_BF_PARAM_DAC_FREQ_DIV,
&hnd->set.out_freq_div, 1);
}
if (!err)
{
err = x502_bf_set_par(hnd, L502_BF_PARAM_DIN_FREQ_DIV,
&hnd->set.din_freq_div, 1);
}
if (!err) {
err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_CONFIGURE, 0, NULL,
0, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL);
}
} else {
err = X502_ERR_INVALID_MODE;
}
}
return err;
}
X502_EXPORT(int32_t) X502_SetAdcCoef(t_x502_hnd hnd, uint32_t range, double k, double offs) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (hnd->flags & PRIV_FLAGS_STREAM_RUN))
err = X502_ERR_STREAM_IS_RUNNING;
if (!err) {
if (x502_is_E16(hnd)) {
if (range >= E16_ADC_RANGE_CNT) {
err = X502_ERR_INVALID_LCH_RANGE;
}
} else {
if (range >= X502_ADC_RANGE_CNT) {
err = X502_ERR_INVALID_LCH_RANGE;
}
}
}
if (!err) {
uint32_t kval = (uint32_t)(k*0x400000);
uint32_t offs_val = (uint32_t)(-offs);
if (hnd->mode == X502_MODE_FPGA) {
err = hnd->iface_hnd->fpga_reg_write(hnd, f_regadd_k[range], kval);
if (!err)
err = hnd->iface_hnd->fpga_reg_write(hnd, f_regadd_offs[range], offs_val);
} else if (hnd->mode == X502_MODE_DSP) {
uint32_t wrds[3] = {range, kval, offs_val};
err = x502_bf_set_par(hnd, L502_BF_PARAM_ADC_COEF, wrds, 3);
} else {
err = X502_ERR_INVALID_MODE;
}
}
if (!err) {
hnd->info.cbr.adc[range].k = k;
hnd->info.cbr.adc[range].offs = offs;
}
return err;
}
X502_EXPORT(int32_t) X502_GetAdcCoef(t_x502_hnd hnd, uint32_t range, double* k, double* offs) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err) {
if (range >= X502_ADC_RANGE_CNT) {
err = X502_ERR_INVALID_LCH_RANGE;
}
}
if (!err) {
*k = hnd->info.cbr.adc[range].k;
*offs = hnd->info.cbr.adc[range].offs;
}
return err;
}
X502_EXPORT(int32_t) X502_SetDacCoef(t_x502_hnd hnd, uint32_t ch, double k, double offs) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (ch!=X502_DAC_CH1) && (ch!=X502_DAC_CH2)) {
err = X502_ERR_INVALID_DAC_CHANNEL;
}
if (!err) {
hnd->info.cbr.dac[ch].offs = offs;
hnd->info.cbr.dac[ch].k = k;
}
return err;
}
X502_EXPORT(int32_t) X502_GetDacCoef(t_x502_hnd hnd, uint32_t ch, double* k, double* offs) {
int32_t err = X502_CHECK_HND_OPENED(hnd);
if (!err && (ch!=X502_DAC_CH1) && (ch!=X502_DAC_CH2)) {
err = X502_ERR_INVALID_DAC_CHANNEL;
}
if (!err) {
if (offs!=NULL)
*offs = hnd->info.cbr.dac[ch].offs;
if (k!=NULL)
*k = hnd->info.cbr.dac[ch].k;
}
return err;
}