source: PlatformSupport/CustomPeripherals/pcores/w3_clock_controller_axi_v3_01_b/src/w3_clock_controller.c

Last change on this file was 3909, checked in by welsh, 10 years ago

Updating clock controller software.

File size: 18.7 KB
Line 
1/*****************************************************************
2* File: w3_clock_controller.c
3* Copyright (c) 2012 Mango Communications, all rights reseved
4* Released under the WARP License
5* See http://warp.rice.edu/license for details
6*****************************************************************/
7
8/** \file w3_clock_controller.c
9
10\mainpage
11This is the driver for the w3_clock_controller core, which implements an SPI master for controlling
12the AD9512 clock buffers on the WARP v3 board. Refer to the WARP v3 user guide for more details
13on the clock options and connections.
14
15@version 3.00.b
16@author Patrick Murphy
17@copyright (c) 2012 Mango Communications, Inc. All rights reserved.<br>
18Released under the WARP open source license (see http://warp.rice.edu/license)
19
20*/
21
22#include "w3_clock_controller.h"
23
24/**
25\defgroup user_functions Functions
26\brief Functions to call from user code
27\addtogroup user_functions
28
29Example:
30\code{.c}
31//Assumes user code sets CLK_BASEADDR to base address of w3_clock_controller core, as set in xparameters.h
32
33//Initialize the AD9512 clock buffers
34ad_init(CLK_BASEADDR, 3);
35
36//Enable clock outputs to FMC slot
37clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_ON, (CLK_SAMP_OUTSEL_FMC | CLK_RFREF_OUTSEL_FMC));
38
39//Disable clock outputs to clock module header
40clk_config_outputs(CLK_BASEADDR, CLK_OUTPUT_OFF, (CLK_SAMP_OUTSEL_CLKMODHDR | CLK_RFREF_OUTSEL_CLKMODHDR));
41
42//Set clock to AD chips to 40MHz (80MHz source divided by 2)
43clk_config_dividers(CLK_BASEADDR, 2, (CLK_SAMP_OUTSEL_AD_RFA | CLK_SAMP_OUTSEL_AD_RFB));
44
45\endcode
46
47@{
48*/
49
50/**
51\brief Initializes the clock controller. This function must be called once at boot before any AD or
52RF operations will work. Default config is:
53- On board 80MHz TCXO used as source for sampling and RF ref clock buffers
54- 80MHz clock driven to FPGA, RF A and RF B ADC/DACs
55- 40MHz clock driven to RF A and B transceivers
56- FMC and clock module header clocks disabled
57\param baseaddr Base memory address of w3_clock_controller pcore
58\param clkDiv Clock divider for SPI serial clock (set to 3 for 160MHz bus)
59*/
60int clk_init(u32 baseaddr, u8 clkDiv) {
61    u32 x;
62   
63    Xil_Out32(baseaddr + CLKCTRL_REG_CONFIG, (clkDiv & CLKCTRL_REG_CONFIG_MASK_CLKDIV));
64
65    //Toggle AD9512 resets (active low)
66    //Currently bypased-buffers auto-reset on power up, and resetting here can stop clock to FPGA (damn causality)
67    //Xil_Out32(CLKCTRL_REG_CONFIG, 0); //Also sets clk_div = 0
68    //Xil_Out32(CLKCTRL_REG_CONFIG, CLKCTRL_REG_CONFIG_MASK_SAMP_FUNC | CLKCTRL_REG_CONFIG_MASK_RFREF_FUNC);
69
70    //Confirm the SPI interfaces are working
71    x = clk_spi_read(baseaddr, (CLK_SAMP_CS|CLK_RFREF_CS), 0x0);
72    if(x != 0x1010) {
73        xil_printf("First CLK SPI readback was wrong: addr[0]=0x%04x (should be 0x1010)\n", x);
74        return -1;
75    }
76
77    /* Samping Clock Buffer Config
78    Samp clock AD9512 outputs on WARP v3 board:
79     OUT0: AD2 (LVPECL)
80     OUT1: Clock module header (LVPECL)
81     OUT2: AD1 (LVPECL)
82     OUT3: FPGA col2 SRCC (LVDS)
83     OUT4: FMC  (LVDS)
84
85    Default config:
86     -Select CLK1 as input
87     -Disable:
88       -Outputs OUT1, OUT4
89       -All output dividers
90       -CLK2 input
91    */
92   
93    /*
94    reg 0x45: CLK1/CLK2 config:
95     0: 1=Use CLK1 input
96     1: 0=Enable CLK1 circuits
97     2: 1=Disable CLK2 circuits
98    */
99    //Now hanlded by at-boot logic; C code shouldn't touch this register if the host processor
100    // is clocked by the sampling clock
101    //clk_spi_write(baseaddr, CLK_SAMP_CS, 0x45, 0x05);
102
103    //Enable OUT0, OUT2, OUT3; disable OUT1, OUT4; all outputs are on after powerup/reset
104    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x3E, 0x02); //OUT1 = off (PD2 mode, because OUT1 has load resistors)
105    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x41, 0x01); //OUT4 = off
106
107    //Power down divider logic- all active outputs at 80MHz
108    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4B, 0x80); //OUT0 divider off
109    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4D, 0x80); //OUT1 divider off
110    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4F, 0x80); //OUT2 divider off
111    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x51, 0x80); //OUT3 divider off
112    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x53, 0x80); //OUT4 divider off
113
114
115    //Alternate config: 40MHz clock for AD1, AD2
116//  clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4B, 0x00); //OUT0 divider on
117//  clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4A, 0x00); //OUT0 divide by 2
118//  clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4F, 0x00); //OUT2 divider on
119//  clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4E, 0x00); //OUT2 divide by 2
120
121    //Trigger register update
122    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x5A, 0x01); //Self-clearing register update flag
123
124
125    /* RF Reference Clock Buffer Config
126    RF ref clock AD9512 outputs on WARP v3 board:
127        OUT0: Clock module header (LVPECL)
128        OUT1: NC
129        OUT2: NC
130        OUT3: Both MAX2829 ref (RFA=CMOSp, RFB=CMOSn; must be 20 or 40 MHz)
131        OUT4: FMC (LVDS)
132
133        Default config:
134         -Select CLK1 as input
135         -Enable + and - CMOS outputs on OUT3
136         -Set OUT3 divider to 2 (produces 40MHz clock at OUT3)
137         -Disable:
138           -Outputs OUT0, OUT1, OUT2, OUT4
139           -Dividers for OUT0, OUT1, OUT2, OUT4
140           -CLK2 input
141    */
142    //Enable OUT3; Disable OUT0, OUT1, OUT2, OUT4; all outputs are on after reset
143    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x3D, 0x02); //OUT0 = off, has load resistors
144    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x3E, 0x03); //OUT1 = off, has no load resistors
145    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x3F, 0x03); //OUT2 = off, has no load resistors
146    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x41, 0x01); //OUT4 = off
147
148    //Enable inverted CMOS output on OUT3
149    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x40, 0x18); //OUT3 = CMOS, +/- both on
150
151    //Power down CLK2 input
152    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x45, 0x05); //CLK1 on, CLK2 off, CLK1 drives distribution
153
154    //Power down divider logic on disabled ports
155    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x4B, 0x80); //OUT0 divider off
156    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x4D, 0x80); //OUT1 divider off
157    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x4F, 0x80); //OUT2 divider off
158    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x53, 0x80); //OUT4 divider off
159
160    //Set divider to 2 on OUT3
161    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x50, 0x00); //OUT3 40MHz (1 cycle down)
162
163    //Alternate config: 20MHz RF reference clock, OUT3 divider=4
164//  clk_spi_write(baseaddr, CLK_RFREF_CS, 0x50, 0x11); //OUT3 20MHz (2 cycle down)
165
166    //Trigger register update
167    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x5A, 0x01); //Self-clearing register update flag
168   
169    return 0;
170}
171
172/**
173\brief Configures which outputs are en/disabled in both AD9512 clock buffers
174\param baseaddr Base memory address of w3_clock_controller pcore
175\param clkOutMode New mode for selected clock outputs; must be CLK_OUTPUT_ON or CLK_OUTPUT_OFF
176\param clkOutSel Masks to select which clock outputs to affect; must be OR'd combination of:
177 Mask | Selected Output
178 ---- | ----
179 CLK_SAMP_OUTSEL_FMC | Sampling clock buffer to FMC slot
180 CLK_SAMP_OUTSEL_CLKMODHDR | Sampling clock buffer to clock module header
181 CLK_SAMP_OUTSEL_FPGA | Sampling clock buffer to FPGA
182 CLK_SAMP_OUTSEL_AD_RFA | Sampling clock buffer to RF A AD9963 (ADC/DAC ref clock)
183 CLK_SAMP_OUTSEL_AD_RFB | Sampling clock buffer to RF B AD9963 (ADC/DAC ref clock)
184 CLK_RFREF_OUTSEL_FMC | RF ref clock buffer to FMC
185 CLK_RFREF_OUTSEL_CLKMODHDR | RF ref clock buffer to clock module header
186 CLK_RFREF_OUTSEL_RFAB | RF ref clock buffer to RF A and B transceivers
187\return Returns 0 on success, -1 for invalid parameters
188*/
189int clk_config_outputs(u32 baseaddr, u8 clkOutMode, u32 clkOutSel) {
190    if((clkOutMode != CLK_OUTPUT_ON) && (clkOutMode != CLK_OUTPUT_OFF))
191        return -1;
192/*
193    Samp clock AD9512 outputs on WARP v3 board:
194        OUT0: AD2 (LVPECL)
195        OUT1: Clock module header (LVPECL)
196        OUT2: AD1 (LVPECL)
197        OUT3: FPGA col2 SRCC (LVDS)
198        OUT4: FMC  (LVDS)
199
200    RF ref clock AD9512 outputs on WARP v3 board:
201        OUT0: Clock module header (LVPECL)
202        OUT1: NC
203        OUT2: NC
204        OUT3: Both MAX2829 ref (RFA=CMOSp, RFB=CMOSn; must be 20 or 40 MHz)
205        OUT4: FMC (LVDS)
206*/
207   
208    u8 lvpecl_cfg, lvds_cfg, cmos_cfg;
209
210    //Set the register values to write, based on output type and user ON/OFF param
211    if(clkOutMode == CLK_OUTPUT_ON) lvpecl_cfg = 0x8; //LVPECL output on, 805mV drive
212    else lvpecl_cfg = 0x2; //output off (for outputs w/ load resistors)
213
214    if(clkOutMode == CLK_OUTPUT_ON) lvds_cfg = 0x2; //output on, LVDS logic, 3.5mA drive
215    else lvds_cfg = 0x1; //output off
216
217    if(clkOutMode == CLK_OUTPUT_ON) cmos_cfg = 0x18; //+/- outputs on, CMOS logic
218    else cmos_cfg = 0x1; //output off
219   
220    /***** Sampling Clock Buffer Config ******/
221    //reg 0x3D, 0x3E, 0x3F: CLKOUT[0,1,2] config
222    // [1:0] LVPECL power down
223    //   (0x0=on, 0x2=PD2 (power down outputs w/ load resistors), 0x3=PD3 (power down outputs w/out load resistors)
224    // [3:2] LVPECL output drive (set to 0x2 for default 805mv)
225    if(clkOutSel & CLK_SAMP_OUTSEL_AD_RFB)      clk_spi_write(baseaddr, CLK_SAMP_CS, 0x3D, lvpecl_cfg); //CLKOUT0
226    if(clkOutSel & CLK_SAMP_OUTSEL_CLKMODHDR)   clk_spi_write(baseaddr, CLK_SAMP_CS, 0x3E, lvpecl_cfg); //CLKOUT1
227    if(clkOutSel & CLK_SAMP_OUTSEL_AD_RFA)      clk_spi_write(baseaddr, CLK_SAMP_CS, 0x3F, lvpecl_cfg); //CLKOUT2
228
229    //reg 0x40, 0x41: CLKOUT[3,4] config
230    // [0] 0=output on, 1=output off
231    // [2:1] LVDS output current (set to 0x1 for 3.5mA default)
232    // [3] Logic (0=LVDS, 1=CMOS)
233    // [4] CMOS- (0=Disable CMOS inverted output; 1=enable)
234    if(clkOutSel & CLK_SAMP_OUTSEL_FPGA)        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x40, lvds_cfg); //CLKOUT3 (LVDS)
235    if(clkOutSel & CLK_SAMP_OUTSEL_FMC)         clk_spi_write(baseaddr, CLK_SAMP_CS, 0x41, lvds_cfg); //CLKOUT4 (LVDS)
236
237    //Trigger register update
238    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x5A, 0x01); //Self-clearing register update flag
239
240    /***** RF Ref Clock Buffer Config ******/
241    //reg 0x3D: CLKOUT0 config
242    // [1:0] LVPECL power down
243    //   (0x0=on, 0x2=PD2 (power down outputs w/ load resistors), 0x3=PD3 (power down outputs w/out load resistors)
244    // [3:2] LVPECL output drive (set to 0x2 for default 805mv)
245    //CLKOUT1, CLKOUT2 are unused and are disabled in clk_init
246    if(clkOutSel & CLK_RFREF_OUTSEL_CLKMODHDR)  clk_spi_write(baseaddr, CLK_RFREF_CS, 0x3D, lvpecl_cfg); //CLKOUT0
247
248    //reg 0x40, 0x41: CLKOUT[3,4] config
249    // [0] 0=output on, 1=output off
250    // [2:1] LVDS output current (set to 0x1 for 3.5mA default)
251    // [3] Logic (0=LVDS, 1=CMOS)
252    // [4] CMOS- (0=Disable CMOS inverted output; 1=enable)
253    if(clkOutSel & CLK_RFREF_OUTSEL_RFAB)       clk_spi_write(baseaddr, CLK_RFREF_CS, 0x40, cmos_cfg); //CLKOUT3 (CMOS +/-)
254    if(clkOutSel & CLK_RFREF_OUTSEL_FMC)        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x41, lvds_cfg); //CLKOUT4 (LVDS)
255
256    //Trigger register update
257    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x5A, 0x01); //Self-clearing register update flag
258
259    return 0;
260}
261
262/**
263\brief Configures whether the RF Reference Buffer uses the on-board or off-board clock source
264\param baseaddr Base memory address of w3_clock_controller pcore
265\param clkInSel Clock source mask, must be either CLK_INSEL_ONBOARD (for on-board oscillator) or CLK_INSEL_CLKMOD (for off-board clock via clock module header)
266 Mask | Selected Input
267 ---- | ----
268 CLK_INSEL_ONBOARD | Selects on-board TCXO as RF Reference clock source (AD9512 CLK1/CLK1B port)
269 CLK_INSEL_CLKMOD | Selects off-board clock from clock module header as RF Reference clock source (AD9512 CLK2/CLK2B port)
270\return Returns 0 on success, -1 for invalid parameters
271*/
272int clk_config_input_rf_ref(u32 baseaddr, u8 clkInSel) {
273    if((clkInSel != CLK_INSEL_ONBOARD) && (clkInSel != CLK_INSEL_CLKMOD))
274        return -1;
275/*
276    Samp clock AD9512 inputs on WARP v3 board:
277        CLK1: On-board TCXO
278        CLK2: Clock module header
279*/
280   
281    /***** Sampling Clock Buffer Config ******/
282    //reg 0x45
283    // [0] Input sel (0=CLK2, 1=CLK1)
284    // [1] 1=Power down CLK1 input circuit
285    // [2] 1=Power down CLK2 input circuit
286    // [3:4] Reserved
287    // [5] Power down both input circuits
288    // [6:7] Reserved
289    if(clkInSel == CLK_INSEL_ONBOARD)   clk_spi_write(baseaddr, CLK_RFREF_CS, 0x45, 0x05); //Select CLK1, power down CLK2
290    if(clkInSel == CLK_INSEL_CLKMOD)    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x45, 0x02); //Select CLK2, power down CLK1
291
292    //Trigger register update
293    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x5A, 0x01); //Self-clearing register update flag
294
295    return 0;
296}
297
298/**
299\brief Reads the status pins of the currently installed clock module
300\param baseaddr Base memory address of w3_clock_controller pcore
301\return Returns a 16-bit value for the clock module status; the meaning of the status bits depends on the currently installed module
302*/
303u16 clk_config_read_clkmod_status(u32 baseaddr) {
304    u16 status;
305    status = (Xil_In32(baseaddr + CLKCTRL_REG_CONFIG)) >> 16;
306   
307    return status;
308}
309
310/**
311\brief Configures output dividers in both AD9512 clock buffers
312\param baseaddr Base memory address of w3_clock_controller pcore
313\param clkDiv Divider value to set; must be 1 or even integer in [2,32]
314\param clkOutSel Masks to select which clock outputs to affect; must be OR'd combination of:
315 Mask | Selected Output
316 ---- | ----
317 CLK_SAMP_OUTSEL_FMC | Sampling clock buffer to FMC slot
318 CLK_SAMP_OUTSEL_CLKMODHDR | Sampling clock buffer to clock module header
319 CLK_SAMP_OUTSEL_FPGA | Sampling clock buffer to FPGA
320 CLK_SAMP_OUTSEL_AD_RFA | Sampling clock buffer to RF A AD9963 (ADC/DAC ref clock)
321 CLK_SAMP_OUTSEL_AD_RFB | Sampling clock buffer to RF B AD9963 (ADC/DAC ref clock)
322 CLK_RFREF_OUTSEL_FMC | RF ref clock buffer to FMC
323 CLK_RFREF_OUTSEL_CLKMODHDR | RF ref clock buffer to clock module header
324 CLK_RFREF_OUTSEL_RFAB | RF ref clock buffer to RF A and B transceivers
325\return Returns 0 on success, -1 for invalid parameters
326*/
327int clk_config_dividers(u32 baseaddr, u8 clkDiv, u32 clkOutSel) {
328/*
329    AD9512 reg 0x[4A,4C,4E,50,52]: Divider config high/low for CLKOUT[0,1,2,3,4]
330     [3:0] Divider high cycles
331     [7:4] Divider low cycles
332     Clock freq divided by ((high+1)+(low+1))
333     50% duty cycle requkired; only possible with 1 or even division ratios (high==low)
334
335    AD9512 reg 0x[4B,4D,4F,51,53]: Divider power down & sync for CLKOUT[0,1,2,3,4]
336     [7] 1=disable and bypass divider logic, 0=use divider
337     [6:0] Divider sync setup (not currently used)
338    */
339   
340    u8 div_pd, div_cfg;
341
342    //Check for invalid clkDiv value (any odd value besides 1, greater than 32, or 0)
343    if( ((clkDiv != 1) && (clkDiv & 0x1)) || clkDiv > 32 || clkDiv == 0)
344        return -1;
345   
346    if(clkDiv == 1) {
347        div_pd = 0x80; //divide-by-1 requires bypassing divider entirely
348        div_cfg = 0x00;
349    } else {
350        div_pd = 0x00; //enable divider
351
352        //Calculate number of high/low cycles
353        div_cfg = (clkDiv>>1)-1;
354       
355        //Set high=low
356        div_cfg = (div_cfg<<4) | div_cfg;
357    }
358   
359   
360    //Sampling clock buffer
361    if(clkOutSel & CLK_SAMP_OUTSEL_AD_RFB) { //CLKOUT0
362        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4A, div_cfg);
363        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4B, div_pd);
364    }
365    if(clkOutSel & CLK_SAMP_OUTSEL_CLKMODHDR) { //CLKOUT1
366        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4C, div_cfg);
367        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4D, div_pd);
368    }
369    if(clkOutSel & CLK_SAMP_OUTSEL_AD_RFA) { //CLKOUT2
370        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4E, div_cfg);
371        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x4F, div_pd);
372    }
373    if(clkOutSel & CLK_SAMP_OUTSEL_FPGA) { //CLKOUT3
374        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x50, div_cfg);
375        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x51, div_pd);
376    }
377    if(clkOutSel & CLK_SAMP_OUTSEL_FMC) { //CLKOUT4
378        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x52, div_cfg);
379        clk_spi_write(baseaddr, CLK_SAMP_CS, 0x53, div_pd);
380    }
381   
382    //Trigger register update
383    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x5A, 0x01); //Self-clearing register update flag
384
385    // Sync outputs (High -> Low transition on bit 2 - Soft SYNC)
386    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x58, 0x04);
387    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x5A, 0x01); //Self-clearing register update flag
388    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x58, 0x00);
389    clk_spi_write(baseaddr, CLK_SAMP_CS, 0x5A, 0x01); //Self-clearing register update flag
390   
391    //RF reference clock buffer
392    if(clkOutSel & CLK_RFREF_OUTSEL_CLKMODHDR) { //CLKOUT0
393        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x4A, div_cfg);
394        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x4B, div_pd);
395    }
396    //CLKOUT1, CLKOUT2 are unused; dividers are disabled in clk_init
397    if(clkOutSel & CLK_RFREF_OUTSEL_RFAB) { //CLKOUT3
398        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x50, div_cfg);
399        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x51, div_pd);
400    }
401    if(clkOutSel & CLK_RFREF_OUTSEL_FMC) { //CLKOUT4
402        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x52, div_cfg);
403        clk_spi_write(baseaddr, CLK_RFREF_CS, 0x53, div_pd);
404    }
405   
406    //Trigger register update
407    clk_spi_write(baseaddr, CLK_RFREF_CS, 0x5A, 0x01); //Self-clearing register update flag
408
409    return 0;
410}
411
412/**
413\brief Reads the specified register from both AD9963s
414\param baseaddr Base memory address of w3_clock_controller pcore
415\param csMask OR'd combination of CLK_SAMP_CS and CLK_RFREF_CS
416\param regAddr Address of register to read, in [0x00, 0x5A]
417\return Returns concatenation of current values of the specified register for both AD9512s (if selected); samp clock buffer is LSB
418*/
419u32 clk_spi_read(u32 baseaddr,  u32 csMask, u8 regAddr) {
420    u32 txWord, rxWord;
421
422    //SPI Tx register is 4 bytes:
423    // [3]: chip selects (bitwise OR'd ADCTRL_REG_SPITX_ADx_CS)
424    // [2]: {rnw n1 n0 5'b0}, rnw=1 for SPI write, n1=n0=0 for 1 byte write
425    // [1]: reg addr[7:0]
426    // [0]: ignored for read (read value captured in Rx register)
427    txWord = (csMask & (CLK_SAMP_CS | CLK_RFREF_CS)) | //chip selects
428             (CLKCTRL_REG_SPITX_RNW) | //spi_tx_byte[2] = {rnw n1 n0 5'b0}
429             ((regAddr & 0x7F)<<8) | //spi_tx_byte[1] = addr[7:0]
430             (0x00); //spi_tx_byte[0] = ignored for read (AD drives data pin during this byte)
431
432    Xil_Out32(baseaddr + CLKCTRL_REG_SPITX, txWord);
433
434    rxWord = Xil_In32(baseaddr + CLKCTRL_REG_SPIRX);
435
436    return(rxWord);
437}
438
439/**
440\brief Writes the specified register value to the selected AD9512 clock buffers
441\param baseaddr Base memory address of w3_clock_controller pcore
442\param csMask OR'd combination of CLK_SAMP_CS and CLK_RFREF_CS
443\param regAddr Address of register to write, in [0x00, 0x5A]
444\param txByte 8-bit value to write
445*/
446void clk_spi_write(u32 baseaddr, u32 csMask, u8 regAddr, u8 txByte) {
447    u32 txWord;
448
449    //SPI read process:
450    // -Write full SPI word with RNW=1 and address of desired register
451    // -Capture register value in last byte of SPI write process (handled automatically in logic)
452   
453    //SPI Tx register is 4 bytes:
454    // [3]: chip selects (bitwise OR'd ADCTRL_REG_SPITX_ADx_CS)
455    // [2]: {rnw n1 n0 5'b0}, rnw=0 for SPI write, n1=n0=0 for 1 byte write
456    // [1]: reg addr[7:0]
457    // [0]: reg data[7:0]
458    txWord = (csMask & (CLK_SAMP_CS | CLK_RFREF_CS)) | //chip selects
459             (0x00) | //spi_tx_byte[2] = {rnw n1 n0 5'b0}
460             ((regAddr & 0xFF)<<8) | //spi_tx_byte[1] = addr[7:0]
461             (txByte & 0xFF); //spi_tx_byte[0] = data byte to write
462
463    Xil_Out32(baseaddr + CLKCTRL_REG_SPITX, txWord);
464   
465    return;
466}
467
468/** @}*/ //END group user_functions
Note: See TracBrowser for help on using the repository browser.