246 lines
9.0 KiB
C
246 lines
9.0 KiB
C
/**
|
|
* \file ad9528.h
|
|
* \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c
|
|
*/
|
|
|
|
/**
|
|
* \page Disclaimer Legal Disclaimer
|
|
* Copyright 2015-2017 Analog Devices Inc.
|
|
* Released under the AD9371 API license.
|
|
*
|
|
*/
|
|
|
|
#ifndef _AD9528_H_
|
|
#define _AD9528_H_
|
|
|
|
/******************************************************************************/
|
|
/***************************** Include Files **********************************/
|
|
/******************************************************************************/
|
|
#include <stdint.h>
|
|
#include "delay.h"
|
|
#include "spi.h"
|
|
#include "gpio.h"
|
|
|
|
/******************************************************************************/
|
|
/********************** Macros and Constants Definitions **********************/
|
|
/******************************************************************************/
|
|
|
|
/* AD9528 SPI Address defines */
|
|
#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000
|
|
#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001
|
|
#define AD9528_ADDR_IO_UPDATE 0x00F
|
|
|
|
#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100
|
|
#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101
|
|
#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102
|
|
#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103
|
|
#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104
|
|
#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105
|
|
#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106
|
|
#define AD9528_ADDR_PLL1_CP_CTRL2 0x107
|
|
#define AD9528_ADDR_INPUT_RECEIVERS1 0x108
|
|
#define AD9528_ADDR_INPUT_RECEIVERS2 0x109
|
|
#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A
|
|
#define AD9528_ADDR_PLL1_FASTLOCK 0x10B
|
|
|
|
#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200
|
|
#define AD9528_ADDR_PLL2_N_DIV 0x201
|
|
#define AD9528_ADDR_PLL2_CTRL 0x202
|
|
#define AD9528_ADDR_PLL2_VCO_CTRL 0x203
|
|
#define AD9528_ADDR_PLL2_VCO_DIV 0x204
|
|
#define AD9528_ADDR_PLL2_LF_CTRL1 0x205
|
|
#define AD9528_ADDR_PLL2_LF_CTRL2 0x206
|
|
#define AD9528_ADDR_PLL2_RDIV 0x207
|
|
#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208
|
|
#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209
|
|
|
|
#define AD9528_ADDR_CH_OUT0_CTRL1 0x300
|
|
#define AD9528_ADDR_CH_OUT0_CTRL2 0x301
|
|
#define AD9528_ADDR_CH_OUT0_CHDIV 0x302
|
|
#define AD9528_ADDR_OUTPUT_SYNC 0x32A
|
|
#define AD9528_ADDR_MASK_SYNC1 0x32B
|
|
#define AD9528_ADDR_MASK_SYNC2 0x32C
|
|
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D
|
|
#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E
|
|
|
|
#define AD9528_ADDR_SYSERF_DIV_LSB 0x400
|
|
#define AD9528_ADDR_SYSERF_DIV_MSB 0x401
|
|
#define AD9528_ADDR_SYSREF_CTRL3 0x402
|
|
#define AD9528_ADDR_SYSREF_CTRL4 0x403
|
|
#define AD9528_ADDR_SYSREF_CTRL5 0x404
|
|
|
|
#define AD9528_ADDR_POWERDOWN_CTRL 0x500
|
|
#define AD9528_ADDR_CH_POWERDOWN1 0x501
|
|
#define AD9528_ADDR_CH_POWERDOWN2 0x502
|
|
#define AD9528_ADDR_LDO_ENABLES1 0x503
|
|
#define AD9528_ADDR_LDO_ENABLES2 0x504
|
|
#define AD9528_ADDR_STATUS0_CTRL 0x505
|
|
#define AD9528_ADDR_STATUS1_CTRL 0x506
|
|
#define AD9528_ADDR_STATUS_OE 0x507
|
|
#define AD9528_ADDR_STATUS_READBACK0 0x508
|
|
#define AD9528_ADDR_STATUS_READBACK1 0x509
|
|
|
|
/******************************************************************************/
|
|
/*************************** Types Declarations *******************************/
|
|
/******************************************************************************/
|
|
|
|
///Enum to select what source outputs from each AD9528 output channel
|
|
typedef enum {
|
|
AD9528_CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency
|
|
SYSREF = 2,
|
|
INV_PLL1_OUTPUT = 5 //VCXO inverted
|
|
} ad9528outSourceSel_t;
|
|
|
|
///Enum to select what output buffer standard is used for the clock outputs
|
|
typedef enum {
|
|
AD9528_LVDS = 0, AD9528_LVDS_BOOST = 1, AD9528_HSTL = 2
|
|
} ad9528outBufferControl_t;
|
|
|
|
///Enum to select the clock input buffer mode.
|
|
typedef enum {
|
|
DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL
|
|
} ad9528RefBuffer_t;
|
|
|
|
/// Structure to hold AD9528 PLL1 settings
|
|
typedef struct {
|
|
uint32_t refA_Frequency_Hz;
|
|
uint16_t refA_Divider;
|
|
ad9528RefBuffer_t refA_bufferCtrl;
|
|
|
|
uint32_t refB_Frequency_Hz;
|
|
uint16_t refB_Divider;
|
|
ad9528RefBuffer_t refB_bufferCtrl;
|
|
|
|
uint32_t vcxo_Frequency_Hz;
|
|
ad9528RefBuffer_t vcxoBufferCtrl;
|
|
|
|
uint16_t nDivider;
|
|
uint8_t bypassPll1;
|
|
} ad9528pll1Settings_t;
|
|
|
|
/// Structure to hold AD9528 PLL2 settings
|
|
typedef struct {
|
|
uint8_t rfDivider; //VCO divider: Valid range (3,4,5)
|
|
uint8_t n2Divider; //PLL2 N2 Divider
|
|
uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3)
|
|
} ad9528pll2Settings_t;
|
|
|
|
/// Structure to hold AD9528 Output Clock settings
|
|
typedef struct {
|
|
uint16_t outPowerDown; //bit per output, if 1 power down that output.
|
|
ad9528outSourceSel_t
|
|
outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT
|
|
ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL
|
|
uint8_t outAnalogDelay[14]; //5 bits
|
|
uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency
|
|
uint8_t outChannelDiv[14]; //8 bit channel divider
|
|
uint32_t outFrequency_Hz[14]; //output clock frequency per clock output
|
|
} ad9528outputSettings_t;
|
|
|
|
///Enum to select the SYSREF output source
|
|
typedef enum {
|
|
EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2
|
|
} sysrefSourceSelection_t;
|
|
|
|
///Enum to choose the SYSREF pattern mode.
|
|
typedef enum {
|
|
NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3
|
|
} sysrefPatternMode_t;
|
|
|
|
///Enum to select the SYSREF input pin mode.
|
|
typedef enum {
|
|
LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3
|
|
} sysrefPinEdgeMode_t;
|
|
|
|
///Enum to select the SYSREF output # of pulses for NSHOT mode.
|
|
typedef enum {
|
|
ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5
|
|
} sysrefNshotMode_t;
|
|
|
|
//Enum to select how a SYSREF is requested.
|
|
typedef enum {
|
|
SPI = 0, PIN = 1
|
|
} sysrefRequestMethod_t;
|
|
|
|
/// Structure to hold AD9528 SYSREF output settings
|
|
typedef struct {
|
|
sysrefRequestMethod_t sysrefRequestMethod;
|
|
sysrefSourceSelection_t sysrefSource;
|
|
sysrefPinEdgeMode_t sysrefPinEdgeMode;
|
|
ad9528RefBuffer_t sysrefPinBufferMode;
|
|
sysrefPatternMode_t sysrefPatternMode;
|
|
sysrefNshotMode_t sysrefNshotMode;
|
|
uint16_t sysrefDivide;
|
|
|
|
} ad9528sysrefSettings_t;
|
|
|
|
/// Structure to hold AD9528 SPI settings
|
|
typedef struct {
|
|
uint8_t chipSelectIndex; ///< valid 1~8
|
|
uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation
|
|
uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word
|
|
uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst
|
|
uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1)
|
|
uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high
|
|
uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput.
|
|
uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1
|
|
uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode.
|
|
uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */
|
|
} ad9528spiSettings_t;
|
|
|
|
/// Structure to hold AD9528 settings
|
|
typedef struct {
|
|
struct gpio_desc *gpio_resetb;
|
|
struct gpio_desc *gpio_sysref_req;
|
|
struct spi_desc *spi_desc;
|
|
ad9528spiSettings_t *spiSettings;
|
|
ad9528pll1Settings_t *pll1Settings;
|
|
ad9528pll2Settings_t *pll2Settings;
|
|
ad9528outputSettings_t *outputSettings;
|
|
ad9528sysrefSettings_t *sysrefSettings;
|
|
} ad9528Device_t;
|
|
|
|
typedef struct {
|
|
struct gpio_init_param *gpio_init_resetb;
|
|
struct gpio_init_param *gpio_init_sysref_req;
|
|
struct spi_init_param *spi_init;
|
|
ad9528spiSettings_t *spiSettings;
|
|
ad9528pll1Settings_t *pll1Settings;
|
|
ad9528pll2Settings_t *pll2Settings;
|
|
ad9528outputSettings_t *outputSettings;
|
|
ad9528sysrefSettings_t *sysrefSettings;
|
|
} ad9528Init_t;
|
|
|
|
typedef enum {
|
|
SYSREF_CONT_ON,
|
|
SYSREF_CONT_OFF,
|
|
SYSREF_PULSE,
|
|
} ad9528SysrefReqMode_t;
|
|
|
|
/******************************************************************************/
|
|
/************************ Functions Declarations ******************************/
|
|
/******************************************************************************/
|
|
|
|
//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards
|
|
int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device,
|
|
uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz,
|
|
uint32_t outputDeviceClock_Hz);
|
|
int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr,
|
|
uint8_t *readdata);
|
|
|
|
//AD9528 API functions
|
|
int32_t AD9528_hasTimeoutExpired();
|
|
int32_t AD9528_resetDevice(ad9528Device_t *device);
|
|
int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device);
|
|
int32_t AD9528_config(ad9528Device_t
|
|
*device); //writes all registers to desired values, leaves clock outputs off.
|
|
int32_t AD9528_setupSYSREF(ad9528Device_t *device,
|
|
uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode,
|
|
sysrefNshotMode_t nShotPulses);
|
|
int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF);
|
|
int32_t AD9528_sysrefReq(ad9528Device_t *device,
|
|
ad9528SysrefReqMode_t mode);
|
|
int32_t AD9528_remove(ad9528Device_t *device);
|
|
|
|
#endif
|