Files
E502_ADC_BF_PC_companion/lib/x502/x502api_config.c

796 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}