#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include "adi_ad9081.h"
#include "adi_ad9081_hal.h"
#include "adi_cms_api_common.h"
typedef struct {
int fd;
const char *node;
uint32_t speed_hz;
uint8_t mode;
uint8_t bits;
} ad9081_spidev_ctx_t;
void ad9081_linux_hal_attach(adi_ad9081_device_t *dev, ad9081_spidev_ctx_t *ctx);
static int die_if_err(const char *tag, int32_t rc)
{
if (rc != API_CMS_ERROR_OK) {
printf("FAIL %s rc=%d\n", tag, (int)rc);
return -1;
}
return 0;
}
static void fill_jtx_conv_sel_straight(adi_ad9081_jtx_conv_sel_t *s)
{
s->virtual_converter0_index = AD9081_FDDC_0_I;
s->virtual_converter1_index = AD9081_FDDC_0_Q;
s->virtual_converter2_index = AD9081_FDDC_1_I;
s->virtual_converter3_index = AD9081_FDDC_1_Q;
s->virtual_converter4_index = AD9081_FDDC_2_I;
s->virtual_converter5_index = AD9081_FDDC_2_Q;
s->virtual_converter6_index = AD9081_FDDC_3_I;
s->virtual_converter7_index = AD9081_FDDC_3_Q;
s->virtual_converter8_index = AD9081_FDDC_4_I;
s->virtual_converter9_index = AD9081_FDDC_4_Q;
s->virtual_convertera_index = AD9081_FDDC_5_I;
s->virtual_converterb_index = AD9081_FDDC_5_Q;
s->virtual_converterc_index = AD9081_FDDC_6_I;
s->virtual_converterd_index = AD9081_FDDC_6_Q;
s->virtual_convertere_index = AD9081_FDDC_7_I;
s->virtual_converterf_index = AD9081_FDDC_7_Q;
}
static void fill_jtx_link0_param_mode12(adi_cms_jesd_param_t *p)
{
memset(p, 0, sizeof(*p));
p->jesd_l = 4;
p->jesd_f = 8;
p->jesd_m = 16;
p->jesd_s = 1;
p->jesd_hd = 0;
p->jesd_k = 32;
p->jesd_n = 16;
p->jesd_np = 16;
p->jesd_cs = 0;
p->jesd_subclass = JESD_SUBCLASS_1;
p->jesd_scr = 0;
p->jesd_duallink = 0;
p->jesd_jesdv = 1; /* JESD204B */
p->jesd_mode_id = 12; /* mode12.0 */
p->jesd_mode_s_sel = 0;
p->jesd_mode_c2r_en = 0;
p->jesd_did = 0;
p->jesd_bid = 0;
p->jesd_lid0 = 0;
}
int main(void)
{
adi_ad9081_device_t dev;
ad9081_spidev_ctx_t ctx = {
.fd = -1,
.node = "/dev/spidev0.0",
.speed_hz = 1000000,
.mode = (SPI_MODE_0 | SPI_CS_HIGH),
.bits = 8
};
ad9081_linux_hal_attach(&dev, &ctx);
if (die_if_err("hal_hw_open", adi_ad9081_hal_hw_open(&dev)) < 0) return 1;
if (die_if_err("soft_reset", adi_ad9081_device_reset(&dev, AD9081_SOFT_RESET)) < 0) return 1;
if (die_if_err("4wire", adi_ad9081_hal_reg_set(&dev, 0x0000, 0x18)) < 0) return 1;
if (die_if_err("dev_init", adi_ad9081_device_init(&dev)) < 0) return 1;
{
uint64_t dac_clk_hz = 4800000000ULL;
uint64_t adc_clk_hz = 1600000000ULL;
uint64_t ref_clk_hz = 4800000000ULL;
if (die_if_err("clk_cfg",
adi_ad9081_device_clk_config_set(&dev, dac_clk_hz, adc_clk_hz, ref_clk_hz)) < 0)
return 1;
}
{
uint8_t cddcs = AD9081_ADC_CDDC_ALL;
uint8_t fddcs = AD9081_ADC_FDDC_ALL;
int64_t cddc_shift[4] = {0, 0, 0, 0};
int64_t fddc_shift[8] = {1000000LL, 2000000LL, 3000000LL, 4000000LL, 5000000LL, 6000000LL, 7000000LL, 8000000LL};
uint8_t cddc_dcm[4] = {
AD9081_CDDC_DCM_2, AD9081_CDDC_DCM_2,
AD9081_CDDC_DCM_2, AD9081_CDDC_DCM_2
};
uint8_t fddc_dcm[8] = {
AD9081_FDDC_DCM_8, AD9081_FDDC_DCM_8,
AD9081_FDDC_DCM_8, AD9081_FDDC_DCM_8,
AD9081_FDDC_DCM_8, AD9081_FDDC_DCM_8,
AD9081_FDDC_DCM_8, AD9081_FDDC_DCM_8
};
uint8_t cc2r_en[4] = {0, 0, 0, 0};
uint8_t fc2r_en[8] = {0, 0, 0, 0, 0, 0, 0, 0};
adi_cms_jesd_param_t jtx_param[2];
memset(jtx_param, 0, sizeof(jtx_param));
fill_jtx_link0_param_mode12(&jtx_param[0]);
adi_ad9081_jtx_conv_sel_t jesd_conv_sel[2];
memset(jesd_conv_sel, 0, sizeof(jesd_conv_sel));
fill_jtx_conv_sel_straight(&jesd_conv_sel[0]);
int32_t rc = adi_ad9081_device_startup_rx(&dev,
cddcs, fddcs,
cddc_shift, fddc_shift,
cddc_dcm, fddc_dcm,
cc2r_en, fc2r_en,
jtx_param,
jesd_conv_sel);
printf("startup_rx rc=%d\n", (int)rc);
if (die_if_err("startup_rx", rc) < 0) return 1;
}
if (die_if_err("coarse_nco_mode_set",
adi_ad9081_adc_ddc_coarse_nco_mode_set(&dev, AD9081_ADC_CDDC_ALL, AD9081_ADC_NCO_ZIF)) < 0)
return 1;
{
uint8_t adc_cddc_xbar = (uint8_t)AD9081_ADC_4_ADC_COMP_MODE;
uint8_t cddc_fddc_xbar = 0;
cddc_fddc_xbar =
AD9081_ADC_CDDC0_TO_FDDC0 |
AD9081_ADC_CDDC0_TO_FDDC1 |
AD9081_ADC_CDDC1_TO_FDDC2 |
AD9081_ADC_CDDC1_TO_FDDC3;
cddc_fddc_xbar |=
AD9081_ADC_CDDC2_TO_FDDC4 |
AD9081_ADC_CDDC2_TO_FDDC5 |
AD9081_ADC_CDDC3_TO_FDDC6 |
AD9081_ADC_CDDC3_TO_FDDC7;
int32_t rc = adi_ad9081_adc_xbar_set(&dev, adc_cddc_xbar, cddc_fddc_xbar);
printf("adc_xbar_set rc=%d\n", (int)rc);
if (die_if_err("adc_xbar_set", rc) < 0) return 1;
}
{
uint8_t tx_lane_map[8] = { 3, 2, 4, 5, 6, 7, 0, 1 };
if (die_if_err("jtx_lanes_xbar",
adi_ad9081_jesd_tx_lanes_xbar_set(&dev, AD9081_LINK_0, tx_lane_map)) < 0)
return 1;
}
{
int32_t rc = adi_ad9081_jesd_oneshot_sync(&dev, JESD_SUBCLASS_1);
if (rc == API_CMS_ERROR_OK) printf("oneshot:OK\n");
else printf("oneshot:FAIL rc=%d\n", (int)rc);
}
if (die_if_err("jtx_en", adi_ad9081_jesd_tx_link_enable_set(&dev, AD9081_LINK_0, 1)) < 0) return 1;
(void)adi_ad9081_hal_hw_close(&dev);
return 0;
}