#include "x502api_private.h" #include "ltimer.h" uint32_t prepare_dac_wrd(t_x502_hnd hnd, double val, uint32_t flags, const t_x502_cbr_coef* coef); X502_EXPORT(int32_t) X502_AsyncOutDac(t_x502_hnd hnd, uint32_t ch, double data, uint32_t flags) { 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.devflags & X502_DEVFLAGS_DAC_PRESENT)) err = X502_ERR_DAC_NOT_PRESENT; if (!err) { uint32_t wr_val = prepare_dac_wrd(hnd, data, flags, &hnd->info.cbr.dac[ch]); if (ch==X502_DAC_CH1) { wr_val |= X502_STREAM_OUT_WORD_TYPE_DAC1; } else { wr_val |= X502_STREAM_OUT_WORD_TYPE_DAC2; } if (hnd->mode == X502_MODE_FPGA) { err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ASYNC_OUT, wr_val); } else if (hnd->mode == X502_MODE_DSP) { err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_OUT, ch==X502_DAC_CH1 ? L502_BF_CMD_ASYNC_TYPE_DAC1 : L502_BF_CMD_ASYNC_TYPE_DAC2, (uint32_t*)&wr_val, 1, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL); } else { err = X502_ERR_INVALID_MODE; } } return err; } X502_EXPORT(int32_t) X502_AsyncOutDig(t_x502_hnd hnd, uint32_t val, uint32_t msk) { int32_t err = X502_CHECK_HND_OPENED(hnd); if (!err) { if(hnd->mode == X502_MODE_FPGA) { err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT); if (!err) { int32_t release_err; /* маскированные биты берем из последнего выведенного значения */ if (msk) { val = val & ~msk; val |= hnd->last_dout & msk; } err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_ASYNC_OUT, val | X502_STREAM_OUT_WORD_TYPE_DOUT); /* сохраняем выведенное значения, для последующего использования в маске */ if (!err) hnd->last_dout = val; release_err = osspec_mutex_release(hnd->mutex_cfg); if (!err) err = release_err; } } else if (hnd->mode == X502_MODE_DSP) { uint32_t wrds[2] = {val, msk}; err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_OUT, L502_BF_CMD_ASYNC_TYPE_DOUT, wrds, 2, NULL, 0, X502_BF_CMD_DEFAULT_TOUT, NULL); } else { err = X502_ERR_INVALID_MODE; } } return err; } static int32_t f_read_digin(t_x502_hnd hnd, uint32_t* din) { int32_t err = 0; uint32_t val; int rdy=0; t_ltimer tmr; /* читаем состояние входов, чтобы сбросить флаг готовности */ if (!x502_is_E16(hnd)) { err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOARITH_DIN_ASYNC, &val); } /* читаем синхронный ввод до готовности данных или пока не выйдем по таймауту*/ ltimer_set(&tmr, LTIMER_MS_TO_CLOCK_TICKS(500)); while (!rdy && !ltimer_expired(&tmr) && (err == X502_ERR_OK)) { err = hnd->iface_hnd->fpga_reg_read(hnd, X502_REGS_IOARITH_DIN_ASYNC, &val); if (!err && (val & 0x80000000)) { rdy = 1; *din = (val & 0x3FFFF); } } if (!err && !rdy) err = X502_ERR_DIG_IN_NOT_RDY; return err; } X502_EXPORT(int32_t) X502_AsyncInDig(t_x502_hnd hnd, uint32_t* din) { int32_t err = X502_CHECK_HND_OPENED(hnd); if (!err & (din==NULL)) err = X502_ERR_INVALID_POINTER; if (!err) err = osspec_mutex_lock(hnd->mutex_cfg, X502_MUTEX_CFG_LOCK_TOUT); if (!err) { if (x502_is_E16(hnd)) { err = f_read_digin(hnd, din); } else if (hnd->mode == X502_MODE_FPGA) { if (hnd->flags & PRIV_FLAGS_STREAM_RUN) { err = f_read_digin(hnd, din); } else { /* запрещаем прием данных */ err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOARITH_IN_STREAM_ENABLE, 0); if (!err) { err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_PRELOAD_ADC, 1); if (!err) { /* запускаем чтение цифровых входов */ err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 1); } } if (!err) { int32_t stop_err; err = f_read_digin(hnd, din); /* останавливаем сбор данных */ stop_err = hnd->iface_hnd->fpga_reg_write(hnd, X502_REGS_IOHARD_GO_SYNC_IO, 0); if (!err) err = stop_err; } } } else if (hnd->mode == X502_MODE_DSP) { err = X502_BfExecCmd(hnd, L502_BF_CMD_CODE_ASYNC_DIG_IN, 0, NULL, 0, din, 1, X502_BF_CMD_DEFAULT_TOUT, NULL); } else { err = X502_ERR_INVALID_MODE; } osspec_mutex_release(hnd->mutex_cfg); } return err; }