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