This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Programming frequency on CDCE913

Other Parts Discussed in Thread: OMAP-L138, CDCE913

Hi,

I'm trying to change the sample frequency for an ADC example project in the OMAP-l138/C6748 EVM kit. This kit includes the CDCE913 clock to set the ADC sample frequency. There is one central function that changes the clock frequency, namely by the call

CDCE913_setOutput(cdce913_output_2, 6)     // set to 4.5 MHz

I'm trying to see how I can modify this call to set it to 20 MHz (the ADC in the kit has a max of 20 MSPS) but up to this point I've been unsuccessful. The cdce913 files (which I've studied but not fully understod) are attached below. I ran the code and tried to access the memory in CCS (e.g. regVal) but apperently I had no access. Is the memory in the CDCE913?

8270.evmc6748_cdce913.h

//-----------------------------------------------------------------------------
// \file    evmc6748_cdce913.c
// \brief   implementation of a TI cdce913 clock driver for the C6748 EVM.
//
//-----------------------------------------------------------------------------
#include "types.h"
#include "evmc6748.h"
#include "evmc6748_i2c.h"
#include "evmc6748_cdce913.h"

//-----------------------------------------------------------------------------
// Private Defines and Macros
//-----------------------------------------------------------------------------

// i2c defines.
#define I2C_PORT_CDCE913         (I2C0)
#define BYTE_READ_WRITE_BIT      (0x80)

//-----------------------------------------------------------------------------
// Private Function Prototypes
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Public Function Definitions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// \brief   initialize the clock synthesizer for use.
//          Y1 (camera) = 27MHz
//          Y2 (ADC) = 	user selectable
//          Y3 (VIDEO) =  27MHz
//
// \param   none.
//
// \return  uint32_t
//    ERR_NO_ERROR - everything is ok...clock is in default configuration.
//    ERR_INIT_FAIL - something happened during initialization.
//	  ERR_NO_UI_BOARD - the UI can not be found
//-----------------------------------------------------------------------------
uint32_t CDCE913_init(void)
{
   // make sure the ui board is connected before proceeding.
   if (!UTIL_isUIBoardAttached())
      return (ERR_NO_UI_BOARD);

   CDCE913_writeByte(0x14, 0xED);
   CDCE913_writeByte(0x18, 0x00);
   CDCE913_writeByte(0x19, 0x40);
   CDCE913_writeByte(0x1A, 0x02);
   CDCE913_writeByte(0x1B, 0x08);
  
   return (ERR_NO_ERROR);
}

//-----------------------------------------------------------------------------
// \brief	Read a register from the CDCE913.
//
// \param   uint8_t in_offset: address of register to be read
//
// \param 	uint8_t * dest_buffer: buffer for retrieved data t obe written to 
 
// \return  uint32_t
//    ERR_NO_ERROR - register read correctly.
//
//-----------------------------------------------------------------------------
uint32_t CDCE913_readByte(uint8_t in_offset, uint8_t *dest_buffer)
{
   uint32_t rtn;
   
   // set bit to indicate this is a byte read.
   SETBIT(in_offset, BYTE_READ_WRITE_BIT);

   // write the register address that we want to read.
   rtn = I2C_write(I2C_PORT_CDCE913, I2C_ADDR_CDCE913, &in_offset, 1, SKIP_STOP_BIT_AFTER_WRITE);
   if (rtn != ERR_NO_ERROR)
      return (rtn);

   // clock out the register data.
   rtn = I2C_read(I2C_PORT_CDCE913, I2C_ADDR_CDCE913, dest_buffer, 1, SKIP_BUSY_BIT_CHECK);
   
   return (rtn);
}

//-----------------------------------------------------------------------------
// \brief	Write a register to the CDCE913.
//
// \param   uint8_t in_offset: address of register to be written to
//
// \param 	uint8_t * data: data to be written to register 
 
// \return  uint32_t
//    ERR_NO_ERROR - register written to correctly.
//
//-----------------------------------------------------------------------------
uint32_t CDCE913_writeByte(uint8_t in_offset, uint8_t in_data)
{
   uint32_t rtn;
   uint8_t i2c_data[2];
   
   // set bit to indicate this is a byte write.
   i2c_data[0] = in_offset | BYTE_READ_WRITE_BIT;
   i2c_data[1] = in_data;

   // write the register that we want to read.
   rtn = I2C_write(I2C_PORT_CDCE913, I2C_ADDR_CDCE913, i2c_data, 2, SET_STOP_BIT_AFTER_WRITE);

   return (rtn);
}

//-----------------------------------------------------------------------------
// \brief	Set an output divider.
//
// \param   cdce913_output_e output: output divider to set
//
// \param 	uint16_t divide_by: value to divide by. Note that divider 1 is 10 bits and 
//				dividers 2/3 are 7 bits. The value of divide_by will be truncated accordingly  
//
// \return  uint32_t
//    ERR_NO_ERROR - output set correctly.
//	  ERR_FAIL	 - invalid output specified.
//
//-----------------------------------------------------------------------------
uint32_t CDCE913_setOutput(cdce913_output_e output, uint16_t divide_by)
{
	uint32_t retVal = 0;
	uint8_t regVal = 0; 
	
	switch(output)
	{
		case cdce913_output_1: 
				//the upper 5 bits of PDIV_1H are shared we need to make sure not to change 
				//the value of these bits when we write to the register.
				CDCE913_readByte(PDIV_1H, &regVal);
				regVal &= 0xF8;								//keep upper 5 bits of current value
				regVal |= (uint8_t)((divide_by>>8) & 0x07); 	//use lower 3 bits of msB of divide_by
				CDCE913_writeByte(PDIV_1H, regVal);
				//now write the lower byte
				regVal = (uint8_t)divide_by;
				CDCE913_writeByte(PDIV_1L, regVal);
				break;
				
		case cdce913_output_2:
				CDCE913_readByte(PDIV_2, &regVal);
				regVal &= 0x80; 							//keep bit 7
				regVal |= (uint8_t)(divide_by & 0x7F);		
				CDCE913_writeByte(PDIV_2, regVal);		
				break;
				
		case cdce913_output_3:
				regVal = (uint8_t)(divide_by & 0x7F);		//bit 7 reserved, allways write 0
				CDCE913_writeByte(PDIV_3, regVal);
				break;
				
		default:
			return ERR_FAIL;
		
	}
	return retVal;
}

Please help me modify the call to change the clock frequency to 20 MHz. Thank you in advance.

  • I tested the code for different parameters. From what I've understood, the divider variable ("6") is used to set the clock frequency in the registers. For different values of this variable I got different sampling frequencies from my ADC. However, one thing that really puzzled me was that for CDCE913_setOutput(cdce913_output_2, 1) I got a sample frequency of 27 MSPS (i.e. the clock must have been set to 27 MHz). This is really strange because my ADC (ADC901) is a max 20 MSPS device. How is this possible? I know this is not the ADC forum but you may have some ideas. Is the max 20 MSPS only a limit on what are "accurate" readings?

  • What I understand now is that the divider value in the function call is a divider (Pdiv) for 27 MHz. Therefore 27 MHz / 1 = 27 MHz etc. What I want to accieve is 27 MHz / 1.35 = 20 MHz. However, the divider is only 1-127. An equation from the datasheet for CDCE913 states that fout = (fin/Pdiv) * (N/M). Based on the current function call, I believe N=M=1.

    How can I set M and N to accieve my goal (e.g. Pdiv = 1, N = 100, M = 135)? I tried TIClockPro with the EVM connected but it couldn't connect to my device. I only got a message "The SPICON Bit is set to 1 in the device, please be sure that the Vddout pin is set to ground". Is there any other way of doing this?

  • Hello Frederik,

    please have a look at the CDCE913 datasheet table9, registersettings. or use the Ti Clock Pro software http://www.ti.com/litv/exe/scac119d to generate the setup and repister settings you need.

    To generate this outputs Y1=27MHz, Y2=20MHz, Y3=27MHz you can use this register settings:

    reg 0x02: 0x34

    reg 0x10: 0x00

    reg 0x11: 0x00

    reg 0x12: 0x00

    reg 0x13: 0x00

    reg 0x14: 0x4D

    reg 0x15: 0x02

    reg 0x16: 0x08

    reg 0x17: 0x00

    reg 0x18: 0xB4

    reg 0x19: 0x0A

    reg 0x1A: 0xB2

    reg 0x1B: 0xEA

    reg 0x1C: 0x00

    reg 0x1D: 0x40

    reg 0x1E: 0x02

    reg 0x1F: 0x08

    These settings will use the input frequency and buffer it directly to Y1 and Y3. The PLL will run at 200MHz and Pdiv2 is set to 10.

    You can write the bytes like in uint32_t CDCE913_init(void) with the Function CDCE913_writeByte(int registerAddress, int registerContent).

    Best regards,

    Julian

  • Thank you Julian! Didn't know I had a software solution all along in CDCE913_init(). I tested it and I got 20 MHz.