Пример #1
0
/***************************************************************************//**
 * @brief Waits for the AD9122 to sync.
 *
 * @return Returns negative error code or 0 in case of success.
*******************************************************************************/
int32_t ad9122_sync()
{
	int32_t ret, timeout;

	timeout = 255;
	do
	{
		delay_us(1000);
		ret = ad9122_read(AD9122_REG_FIFO_STATUS_1);
		if (ret < 0)
			return ret;

	} while (timeout-- && !(ret & AD9122_FIFO_STATUS_1_FIFO_SOFT_ALIGN_ACK));

	ad9122_write(AD9122_REG_FIFO_STATUS_1, 0x0);
	ad9122_write(AD9122_REG_SYNC_CTRL_1,
		     	 AD9122_SYNC_CTRL_1_SYNC_EN |
		     	 AD9122_SYNC_CTRL_1_RISING_EDGE_SYNC);

	timeout = 255;
	do
	{
		delay_us(1000);
		ret = ad9122_read(AD9122_REG_SYNC_STATUS_1);
		if (ret < 0)
			return ret;

	} while (timeout-- && !(ret & AD9122_SYNC_STATUS_1_SYNC_LOCKED));

	return 0;
}
Пример #2
0
/***************************************************************************//**
 * @brief Gets the AD9122 FIFO status.
 *
 * @return Returns negative error code in case of FIFO warning
 * 		   or 0 in case of success.
*******************************************************************************/
int32_t ad9122_get_fifo_status(struct cf_axi_converter *conv)
{
	uint32_t stat;

	stat = ad9122_read(AD9122_REG_SYNC_STATUS_1);
	if (!(stat & AD9122_SYNC_STATUS_1_SYNC_LOCKED))
		return -1;

	stat = ad9122_read(AD9122_REG_FIFO_STATUS_1);
	if (stat & (AD9122_FIFO_STATUS_1_FIFO_WARNING_1 |
				AD9122_FIFO_STATUS_1_FIFO_WARNING_2))
		return -1;

	return 0;
}
Пример #3
0
/***************************************************************************//**
 * @brief Writes interpolation data to the AD9122.
 *
 * @return Returns negative error code or the written data in case of success.
*******************************************************************************/
uint32_t ad9122_interpolation_store(uint32_t address, int32_t readin)
{
	struct cf_axi_converter *conv = &dds_conv;
	unsigned pwr;
	int32_t ret;

	pwr = ad9122_read(AD9122_REG_POWER_CTRL);
	ad9122_write(AD9122_REG_POWER_CTRL, pwr |
				 AD9122_POWER_CTRL_PD_I_DAC |
				 AD9122_POWER_CTRL_PD_Q_DAC);

	switch (address) {
	case 0:
		ret = ad9122_set_interpol_freq(conv, readin);
		break;
	case 1:
		ret = ad9122_set_interpol_fcent_freq(conv, readin);
		break;
	default:
		ret = -1;
	}

	if (conv->pcore_sync)
		conv->pcore_sync();
	ad9122_write(AD9122_REG_POWER_CTRL, pwr);

	return ret ? ret : readin;
}
Пример #4
0
/***************************************************************************//**
 * @brief Reads data from the AD9122.
 *
 * @return Returns negative error code or 0 in case of success.
*******************************************************************************/
uint32_t ad9122_show(uint32_t address, int32_t* val)
{
	int32_t ret = 0;

	ret = ad9122_read((uint32_t)address);
	if (ret < 0)
		goto out;
	*val = ret << 8;

	ret = ad9122_read((uint32_t)address - 1);
	if (ret < 0)
		goto out;
	*val |= ret & 0xFF;

	switch ((uint32_t)address) {
	case AD9122_REG_I_PHA_ADJ_MSB:
	case AD9122_REG_Q_PHA_ADJ_MSB:
		*val = sign_extend32(*val, 9);
		break;
	}

out:
	return ret;
}
Пример #5
0
/***************************************************************************//**
 * @brief Sets the full-scale current for I DAC.
 *
 * @param fs_adj - Full scale current value. If the value equals INT32_MAX then
 *                 the function returns the current set value.
 *
 * @return Returns the set full-scale current.
*******************************************************************************/
int32_t ad9122_fs_adj_I_DAC(int32_t fs_adj)
{
	uint8_t sleepBit	= 0;
	uint8_t regData1	= 0;
    uint8_t regData2	= 0;

	if(fs_adj != INT32_MAX)
	{
		/* Read the current state of the sleep bit */
		sleepBit = (ad9122_read(AD9122_REG_I_DAC_CTRL) &
					AD9122_I_DAC_CTRL_I_DAC_SLEEP);

        /* Set the full-scale value and keep the state of the sleep bit. */
		regData1 = AD9122_I_DAC_CTRL_I_DAC_FS_ADJ_9_8((fs_adj & 0x0300) >> 8);
		ad9122_write(AD9122_REG_I_DAC_CTRL, (sleepBit | regData1));
		regData2 = AD9122_I_DAC_FS_ADJ_I_DAC_FS_ADJ_7_0((fs_adj & 0x00FF) >> 0);
		ad9122_write(AD9122_REG_I_DAC_FS_ADJ, regData2);

        /* Compute the set full scale current */
        fs_adj = ((regData1 & 0x3) << 8) + (regData2 << 0);
	}
Пример #6
0
/***************************************************************************//**
 * @brief Sets the interpolation factor and the center shift frequency.
 *
 * @param conv - Pointer to a cf_axi_converter struct.
 * @param interp - Interpolation factor
 * @param fcent_shift - Center frequency shift as a multiplier of fData / 2. 
*               		The shift values should be in the range [0, 15]
 * @param data_rate - Data rate in Hz
 *
 * @return Returns negative error code or 0 in case of success.
*******************************************************************************/
static int32_t ad9122_set_interpol(struct cf_axi_converter *conv,
								   uint32_t interp,
								   uint32_t fcent_shift,
								   uint32_t data_rate)
{
	uint32_t hb1, hb2, hb3, tmp;
	int32_t ret, cached;

	hb1 = AD9122_HB1_CTRL_BYPASS_HB1;
	hb2 = AD9122_HB2_CTRL_BYPASS_HB2;
	hb3 = AD9122_HB3_CTRL_BYPASS_HB3;

	switch (interp) {
		case 1:
			break;
		case 2:
			if (fcent_shift > 3)
				return -1;
			hb1 = AD9122_HB1_INTERP(fcent_shift);
			break;
		case 4:
			if (fcent_shift > 7)
				return -1;
			hb1 = AD9122_HB1_INTERP(fcent_shift % 4);
			hb2 = AD9122_HB23_INTERP(fcent_shift);
			break;
		case 8:
			if (fcent_shift > 15)
				return -1;
			hb1 = AD9122_HB1_INTERP(fcent_shift % 4);
			hb2 = AD9122_HB23_INTERP(fcent_shift % 8);
			hb3 = AD9122_HB23_INTERP(fcent_shift / 2);
			break;
		default:
			return -1;
	}

	cached = conv->interp_factor;
	conv->interp_factor = interp;
	ret = ad9122_set_data_clk(conv, data_rate ?
				 data_rate : ad9122_get_data_clk(conv));

	if (ret < 0) {
		conv->interp_factor = cached;

		return ret;
	}

	tmp = ad9122_read(AD9122_REG_DATAPATH_CTRL);
	switch (hb1) {
		case AD9122_HB1_INTERP(1):
		case AD9122_HB1_INTERP(3):
			tmp &= ~AD9122_DATAPATH_CTRL_BYPASS_PREMOD;
			break;
		default:
			tmp |= AD9122_DATAPATH_CTRL_BYPASS_PREMOD;
	}

	ad9122_write(AD9122_REG_DATAPATH_CTRL, tmp);
	ad9122_write(AD9122_REG_HB1_CTRL, hb1);
	ad9122_write(AD9122_REG_HB2_CTRL, hb2);
	ad9122_write(AD9122_REG_HB3_CTRL, hb3);
	conv->fcenter_shift = fcent_shift;

	return 0;
}
Пример #7
0
/***************************************************************************//**
 * @brief Calibrates the AD9122 DCI.
 *
 * @return Returns negative error code or 0 in case of success.
*******************************************************************************/
int32_t ad9122_tune_dci(struct cf_axi_converter *conv)
{
	uint32_t reg;
	int32_t i = 0, dci;
	uint32_t err_bfield = 0;

	for (dci = 0; dci < 4; dci++) {
		ad9122_write(AD9122_REG_DCI_DELAY, dci);
		for (i = 0; i < ARRAY_SIZE(dac_sed_pattern); i++) {

			ad9122_write(AD9122_REG_SED_CTRL, 0);

			if(conv->pcore_set_sed_pattern)
			{
				conv->pcore_set_sed_pattern(0,
					dac_sed_pattern[i].i0, dac_sed_pattern[i].i1);
				conv->pcore_set_sed_pattern(1,
					dac_sed_pattern[i].q0, dac_sed_pattern[i].q1);
			}

			ad9122_write(AD9122_REG_COMPARE_I0_LSBS,
				dac_sed_pattern[i].i0 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_I0_MSBS,
				dac_sed_pattern[i].i0 >> 8);

			ad9122_write(AD9122_REG_COMPARE_Q0_LSBS,
				dac_sed_pattern[i].q0 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_Q0_MSBS,
				dac_sed_pattern[i].q0 >> 8);

			ad9122_write(AD9122_REG_COMPARE_I1_LSBS,
				dac_sed_pattern[i].i1 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_I1_MSBS,
				dac_sed_pattern[i].i1 >> 8);

			ad9122_write(AD9122_REG_COMPARE_Q1_LSBS,
				dac_sed_pattern[i].q1 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_Q1_MSBS,
				dac_sed_pattern[i].q1 >> 8);

			ad9122_write(AD9122_REG_SED_CTRL,
				    AD9122_SED_CTRL_SED_COMPARE_EN);

			ad9122_write(AD9122_REG_EVENT_FLAG_2,
 				    AD9122_EVENT_FLAG_2_AED_COMPARE_PASS |
				    AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL |
				    AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL);

			ad9122_write(AD9122_REG_SED_CTRL,
				    AD9122_SED_CTRL_SED_COMPARE_EN |
				    AD9122_SED_CTRL_AUTOCLEAR_EN);

			msleep(100);
			reg = ad9122_read(AD9122_REG_SED_CTRL);
			if(!(reg & (AD9122_SED_CTRL_SAMPLE_ERR_DETECTED | AD9122_SED_CTRL_COMPARE_PASS)))
			{
				return -1;
			}
			if (reg & AD9122_SED_CTRL_SAMPLE_ERR_DETECTED)
				set_bit(dci, &err_bfield);
		}
	}
	dci = ad9122_find_dci(&err_bfield, 4);
	if(dci < 0)
	{
		return -1;
	}
	ad9122_write(AD9122_REG_DCI_DELAY, dci);
	ad9122_write(AD9122_REG_SED_CTRL, 0);

	return 0;
}
Пример #8
0
/***************************************************************************//**
 * @brief Calibrates the AD9122 DCI.
 *
 * @return Returns negative error code or 0 in case of success.
*******************************************************************************/
int32_t ad9122_tune_dci(struct cf_axi_converter *conv)
{
	uint32_t reg, err_mask, pwr;
	int32_t i = 0, dci;
	uint32_t err_bfield = 0;

	pwr = ad9122_read(AD9122_REG_POWER_CTRL);
	ad9122_write(AD9122_REG_POWER_CTRL, pwr |
			AD9122_POWER_CTRL_PD_I_DAC |
			AD9122_POWER_CTRL_PD_Q_DAC);

	for (dci = 0; dci < 4; dci++) {
		ad9122_write(AD9122_REG_DCI_DELAY, dci);
		for (i = 0; i < ARRAY_SIZE(dac_sed_pattern); i++) {

			ad9122_write(AD9122_REG_SED_CTRL, 0);
#ifdef CF_AXI_DDS
			if(conv->pcore_set_sed_pattern)
			conv->pcore_set_sed_pattern(
				(dac_sed_pattern[i].i1 << 16) | dac_sed_pattern[i].i0,
				(dac_sed_pattern[i].q1 << 16) | dac_sed_pattern[i].q0);
#endif
			ad9122_write(AD9122_REG_COMPARE_I0_LSBS,
				dac_sed_pattern[i].i0 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_I0_MSBS,
				dac_sed_pattern[i].i0 >> 8);

			ad9122_write(AD9122_REG_COMPARE_Q0_LSBS,
				dac_sed_pattern[i].q0 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_Q0_MSBS,
				dac_sed_pattern[i].q0 >> 8);

			ad9122_write(AD9122_REG_COMPARE_I1_LSBS,
				dac_sed_pattern[i].i1 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_I1_MSBS,
				dac_sed_pattern[i].i1 >> 8);

			ad9122_write(AD9122_REG_COMPARE_Q1_LSBS,
				dac_sed_pattern[i].q1 & 0xFF);
			ad9122_write(AD9122_REG_COMPARE_Q1_MSBS,
				dac_sed_pattern[i].q1 >> 8);


			ad9122_write(AD9122_REG_SED_CTRL,
				    AD9122_SED_CTRL_SED_COMPARE_EN);

			ad9122_write(AD9122_REG_EVENT_FLAG_2,
 				    AD9122_EVENT_FLAG_2_AED_COMPARE_PASS |
				    AD9122_EVENT_FLAG_2_AED_COMPARE_FAIL |
				    AD9122_EVENT_FLAG_2_SED_COMPARE_FAIL);

			ad9122_write(AD9122_REG_SED_CTRL,
				    AD9122_SED_CTRL_SED_COMPARE_EN);

			msleep(100);
			reg = ad9122_read(AD9122_REG_SED_CTRL);
			err_mask = ad9122_read(AD9122_REG_SED_I_LSBS);
			err_mask |= ad9122_read(AD9122_REG_SED_I_MSBS);
			err_mask |= ad9122_read(AD9122_REG_SED_Q_LSBS);
			err_mask |= ad9122_read(AD9122_REG_SED_Q_MSBS);

			if (err_mask || (reg & AD9122_SED_CTRL_SAMPLE_ERR_DETECTED))
				set_bit(dci, &err_bfield);
		}
	}

	ad9122_write(AD9122_REG_DCI_DELAY,
		    ad9122_find_dci(&err_bfield, 4));
	ad9122_write(AD9122_REG_SED_CTRL, 0);
	ad9122_write(AD9122_REG_POWER_CTRL, pwr);

	return 0;
}