LTC6954 - 低相位噪声、三路输出时钟分配分频器 / 驱动器

特点

  • 低噪声时钟分配:适合于高速 / 高分辨率 ADC 计时
  • 附加抖动 < 20fsRMS (12kHz 20MHz)
  • 附加抖动 < 85fsRMS (10Hz 至奈奎斯特频率)
  • 1.8GHz 最大输入频率 (LTC6954-1 - DELAY = 0 )
  • 1.4GHz 最大输入频率 (LTC6954-1 - DELAY > 0 LTC6954-234)
  • 可兼容 EZSync时钟同步
  • 三个独立的低噪声输出
  • 可提供 4 种输出组合
  • 三个独立的可编程分频器覆盖了从 1 至 63 的所有整数
  • 三种独立的可编程延迟覆盖了从 0 至 63 的所有整数
  • -40°C 至 105°C 的结温范围

典型应用

LTC6954 Typical Application
LTC6954 Typical Application

描述

LTC®6954 是一个非常低相位噪声时钟分配器件系列。每款器件具有三个输出,而且每个输出具有一个可个别编程的分频器和延迟。该系列包括以下 4 个具有不同输出逻辑信号类型的成员:

LTC6954-1三个 LVPECL 输出

LTC6954-2两个 LVPECL 和一个 LVDS/CMOS 输出

LTC6954-3一个 LVPECL 和两个 LVDS/CMOS 输出

LTC6954-4三个 LVDS/CMOS 输出

每个输出可个别地编程以利用从 1 至 63 的任何整数来对输入频率进行分频,并把每个输出延迟 0 至 63 个输入时钟周期。输出占空比始终为 50%,这与分频数无关。LVDS/CMOS 输出可由跳线通过 OUTxSEL 引脚进行选择,以提供一个 LVDS 逻辑输出或一个 CMOS 逻辑输出。

另外,LTC6954 还采用了凌力尔特的 EZSync 系统,以每次都能实现理想的时钟同步和对准。

所有的器件设置均通过一个 SPI 兼容型串行端口来控制。

封装

如需了解完整与最新的封装信息及图例,请查阅我们的封装网页

器件型号 封装 Code 温度 封装图 RoHS 数据
LTC6954IUFF-1#PBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-1#TRPBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-2#PBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-2#TRPBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-3#PBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-3#TRPBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-4#PBF 4x7 QFN-36 UFF I 05-08-1863 Yes
LTC6954IUFF-4#TRPBF 4x7 QFN-36 UFF I 05-08-1863 Yes


LTC6954 Package Drawing

订购信息

  • 以 PBF 结尾的器件型号表示这些是无铅型器件。如需了解有关含铅涂层器件的信息,请与凌力尔特公司联系。

  • 型号当中包含 TR 或 TRM 的器件分别采用卷带装500 片微型卷带装的形式进行装运。

  • 如需了解更多的细节,请查阅我们一般订购信息或产品数据手册。

各种封装型式和定价

器件型号 封装 温度 价格 (以 1 ~ 99 片为批量) 价格 (以 1000 片为批量) * RoHS 数据
LTC6954IUFF-1#PBF 4x7 QFN-36 I $11.79 $8.25 Yes
LTC6954IUFF-1#TRPBF 4x7 QFN-36 I $8.31 Yes
LTC6954IUFF-2#PBF 4x7 QFN-36 I $10.71 $7.50 Yes
LTC6954IUFF-2#TRPBF 4x7 QFN-36 I $7.56 Yes
LTC6954IUFF-3#PBF 4x7 QFN-36 I $10.71 $7.50 Yes
LTC6954IUFF-3#TRPBF 4x7 QFN-36 I $7.56 Yes
LTC6954IUFF-4#PBF 4x7 QFN-36 I $10.71 $7.50 Yes
LTC6954IUFF-4#TRPBF 4x7 QFN-36 I $7.56 Yes
购买要求提供样品

* 美国价目表所列之价格仅供预算之用,单位为美元 (针对规定批量的美国 FOB 单价),随时可能变更。国际销售价格有可能因为地方税额、费用和汇率而有所不同。如需了解特定批量的价格或货运报价,请您与凌力尔特当地的销售办事处或授权分销商联系

演示电路板

凌力尔特的演示电路板可免费提供给合资格的客户,请您与当地的销售办事处或分销商联系,申请获取演示电路板。另外,某些演示电路板也可通过信用卡在此网站上购买。演示电路板仅供评估之用。器件在实际终端应用中的正确与可靠运作的验证仍然是客户的责任。

器件型号 描述 价格 Documentation
DC1954A-A LTC6954-1 Demo Board | Low Phase Noise, Triple Output Clock Distribution Divider/Driver, 3 LVPECL Outputs (Req DC590 or DC2026) $125.00
DC1954A-B LTC6954-2 Demo Board | Low Phase Noise, Triple Output Clock Distribution Divider/Driver, 2 LVPECL and 1 LVDS/CMOS outputs (Req DC590 or DC2026) $125.00
DC1954A-C LTC6954-3 Demo Board | Low Phase Noise, Triple Output Clock Distribution Divider/Driver, 1 LVPECL and 2 LVDS/CMOS outputs (Req DC590 or DC2026) $125.00
DC1954A-D LTC6954-4 Demo Board | Low Phase Noise, Triple Output Clock Distribution Divider/Driver, 3 LVDS/CMOS outputs (Req DC590 or DC2026) $125.00
购买

Companion Boards

器件型号 描述 价格 Documentation
DC2430A DC2430A Linduino SPI 1:8 Expander Demonstration Board (DC2026 Included) 联系凌力尔特
DC2026C Linduino One Isolated USB Demo Board: An Arduino- and QuikEval-Compatible Code Development Platform $75.00
DC590B Isolated USB Serial Controller for Linear Technology QuikEval-Compatible Demo Boards $50.00
购买
点击这里查看我们的演示板完整列表

应用

  • 高速、高分辨率 ADC、DAC 和数据采集系统的计时
  • 低抖动时钟分配

产品通知

请登录您的 MyLinear 帐户,以获得数据表更新通知、新文档发布、以及针对您喜爱产品的 LTspice 模型通告。 如果您还没有 MyLinear 帐户,可以立即 注册

忘记密码吗? 请单击这里
需要帮助吗? 如果有任何问题或意见,请发送电子邮件至 mylinear@linear.com

设计工具

LTC6954_GUI

凌力尔特 LTC6954_GUI 用于和 LTC6954 时钟分频器进行通信。它采用 DC590 以在 USB 和 SPI 兼容型串行通信格式之间实现转换。

点击这里以下载 LTC6954_GUI。

Linduino

Linduino 是一款可兼容 Arduino 的平台,其用于开发和分配用于 SPI 和 I2C 兼容型集成电路的固件库和代码。Linduino One 电路板可连接 300 多款 QuikEval 演示板卡并支持多种产品类型,包括模数转换器 (ADC)数模转换器 (DAC)功率监视器等等。用于个别器件的固件库采用 C 语言编写并专为可移植到众多的处理器和微控制器而设计。每个固件库具有一种演示程序,此演示程序可上载至 Linduino One 平台以简便快捷地完成电路和软件的验证。

点击这里以了解 Linduino 的更多相关信息

 

代码

Linduino 是凌力尔特的 Arduino 兼容型系统,适用于开发和分发针对凌力尔特集成电路的固件库和代码范例。下面的代码程序可以下载或者“拷贝并粘贴”到您的设计方案之中。请访问 Linduino 主页以获取演示板、手册和设置信息。

该器件得到了代码支持: 提供了可用于该器件的代码示例。下面的代码有可能依存于完整库中提供的其他驱动程序。

Download LTC6954 - DC1954A.INO

/*!
DC1954A
LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver

@verbatim

  Setup:
    Set the terminal baud rate to 115200 and select the newline terminator.
    Refer to Demo Manual DC1954A.
    Ensure all jumpers are installed in the factory default positions.
    One 3.3V power supplies ia needed for this demo board
    An input signal is also needed for this demo board, refer to the
    DC1954 Demo Manual for details.


Command Description:

                             *****Main Menu*****
    1-  Load Default Settings- Loads the SPI map that is identical to file
        LTC6954.6954set that is supplied with the LTC6954_GUI and mentioned
        in the DC1954A user's manual.

    2-  READ/WRITE to Registers Addresses- Selecting this option will cause all the registers to
        be read, stored to variables, and displayed.  The user will then have the option
        to write to one register address at a time.

    3-  READ/WRITE to Registers Fields- Selecting this option will allow the user
        to read or write to one register field name at a time.

    4-  This function stores the current SPI settings in the demo boards EEPROM

    5-  This function loads SPI settings from the demo boards EEPROM to the device


USER INPUT DATA FORMAT:
 decimal : 1024
 hex     : 0x400
 octal   : 02000  (leading 0 "zero")
 binary  : B10000000000
 float   : 1024.0

@endverbatim

http://www.linear.com/product/LTC6954

http://www.linear.com/product/LTC6954#demoboards

REVISION HISTORY
$Revision: 3659 $
$Date: 2015-07-01 10:19:20 -0700 (Wed, 01 Jul 2015) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/

/*! @file
    @ingroup LTC6954
*/

#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include "UserInterface.h"
#include "LT_I2C.h"
#include "QuikEval_EEPROM.h"
#include "LTC6954.h"
#include <SPI.h>
#include <Wire.h>

// Function Declaration
void print_title();             // Print the title block
void print_prompt();            // Print the main menu
void menu_1_load_default_settings();  // Sub-menus
void menu_2_RW_to_reg_addresss();
void menu_3_RW_to_reg_field();
void menu_4_store_settings();
void menu_5_restore_settings();

// Global Variables
static uint8_t ref_out = 0;            //!< Used to keep track of reference out status
static int8_t demo_board_connected;    //!< Demo Board Name stored in QuikEval EEPROM
uint8_t First_Run=0;                   //!< if first time through loop = 0, otherwise=1


/* ------------------------------------------------------------------------- */
//! Initialize Linduino
//! @return void
void setup()
{
  char demo_name[] = "DC1954";    // Demo Board Name stored in QuikEval EEPROM
  uint8_t data;

  quikeval_SPI_init();      //! Configure the spi port for 4MHz SCK
  quikeval_SPI_connect();   //! Connect SPI to main data port
  quikeval_I2C_init();      //! Configure the EEPROM I2C port for 100kHz
  Serial.begin(115200);     //! Initialize the serial port to the PC
  LTC6954_init();
  print_title();

  demo_board_connected = discover_demo_board(demo_name);  //! Checks if correct demo board is connected.

  if (!demo_board_connected)
    while (1);                  //! Does nothing if the demo board is not connected

  Serial.print(demo_board.name);
  Serial.println(F(" was found"));

  print_prompt();
} // end of setup()


/* ------------------------------------------------------------------------- */
//! Repeats Linduino loop
//! @return void
void loop()
{
  uint16_t user_command;          // User input command

  if (Serial.available())          // Check for user input
  {
    if (First_Run==0)
    {
      First_Run=1;
    }

    user_command = read_int();  //! Reads the user command
    if (user_command != 'm')
      Serial.println(user_command);

    switch (user_command)       //! Prints the appropriate submenu
    {
      case 1:
        menu_1_load_default_settings();
        break;

      case 2:
        menu_2_RW_to_reg_addresss();
        break;

      case 3:
        menu_3_RW_to_reg_field();
        break;

      case 4:
        menu_4_store_settings();
        break;

      case 5:
        menu_5_restore_settings();
        break;
      default:
        Serial.println(F("Incorrect Option"));
        break;
    } // end of switch statement
    Serial.println(F("\n*****************************************************************"));
    print_prompt();
  } // end of if statement
} // end of loop()

// Function Definitions
/* ------------------------------------------------------------------------- */
//! Menu 1: Load Default SPI Register Settings
//!  This function identifies which of the 4 LTC6954 frequency versions are connected.
//!  Based on the version connected, this function loads the register settings referenced
//!  in the DC1954A demo manual's quick start section.
//!  The register settings loaded are the same as the LTC6954_GUI 6954set files
//!  LTC6954.6954set.
//!  The setting loaded with this function assume the DC1954A's loop filter has
//!  not been modified.
//! @return void
void menu_1_load_default_settings()
{

// select which default register setting to load based on part number
  if (demo_board.product_name[8]=='1')   // if this is a LTC6954-1
    set_LTC6954_ALLREGS(LTC6954_CS,0x00,0x80,0x04,0x80,0x04,0x80,0x04);
  else if (demo_board.product_name[8]=='2')  // if this is a LTC6954-2
    set_LTC6954_ALLREGS(LTC6954_CS,0x00,0x80,0x04,0x80,0x04,0x80,0x04);
  else if (demo_board.product_name[8]=='3')  // if this is a LTC6954-3
    set_LTC6954_ALLREGS(LTC6954_CS,0x00,0x80,0x04,0x80,0x04,0x80,0x04);
  else if (demo_board.product_name[8]=='4')  // if this is a LTC6954-4
    set_LTC6954_ALLREGS(LTC6954_CS,0x00,0x80,0x04,0x80,0x04,0x80,0x04);
  else
  {
    Serial.print("No default file for this board:  ");
    Serial.println(demo_board.product_name);
  }  // end if-then-else statement

  Serial.println(F("Registers Have Been Written"));
} // end menu_1_load_default_settings function


/* ------------------------------------------------------------------------- */
//! Menu 2: Reads and/or Writes the SPI register address
//!  This function reads and displays all SPI register address settings in HEX format.
//!  It then provides an option to modify(write to) individual registers one at time
//!
//!  EXAMPLE:
//!  - 0- ADDR00 = 0x00
//!  - 1- ADDR01 = 0x08
//!  - ....
//!  - 6- ADDR06 = 0x04
//!  - 7- ADDR07 = 0x21 (read only)
//!  - -1 - Return to Main Menu
//!  - Enter a command (0-6 to modify register, or '-1' to return to Main Menu):
//! @return void
void menu_2_RW_to_reg_addresss()
{
  uint8_t i, regval, user_regval, num_regs;
  uint16_t user_address;          // User input command

  num_regs = get_LTC6954_REGSIZE();
// Read/Write loop, can exit loop by choosing '0'
  user_address=99;
  while  (user_address != -1)
  {
    Serial.println(F("\n*****************************************************************"));
    // Read All Registers and display results
    for (i=0; i<num_regs; i++)
    {
      regval = LTC6954_read(LTC6954_CS,i);
      Serial.print(i);
      if (i<16)
        Serial.print(F("- ADDR0"));
      else
        Serial.print(F("- ADDR"));
      Serial.print(i, HEX);
      Serial.print(F(" = 0x"));
      if (regval<16) Serial.print(F("0"));
      Serial.print(regval, HEX);
      if (i==(num_regs-1)) Serial.print(" (read only) ");
      Serial.println("");
    }  // end for loop
    Serial.print("-1 - Return to Main Menu\n\n");
    // User input: Select which register to modify, or return to main menu
    Serial.print("Enter a command (0-6 to modify register, or '-1' to return to Main Menu): ");
    user_address = read_int();  //! Reads the user command
    Serial.println(user_address);

    // User input: enter new setting for selected register
    if (user_address >=0 && user_address<(num_regs-1))
    {
      Serial.print("What value should ADDR");
      Serial.print(user_address);
      Serial.print(" be set to (ex: HEX format 0xff): ");
      user_regval = read_int();  //! Reads the user command
      Serial.println(user_regval);

      // writes new setting to part
      LTC6954_write(LTC6954_CS, (uint8_t)user_address, user_regval);
    } // end if statement
  } // end while loop
}  // end menu_2_RW_to_reg_addresss


/* ------------------------------------------------------------------------- */
//! Support function for function menu_3_RW_to_reg_field
//!  displays current state of select field
//!  provides user the option to write to that field or return to menu
//!  @return field value (user input) that will be written to part
long field_menu_RW(long field_val,       //!< current state of the selected field
                   char field_name[],    //!< SPI Field name selected
                   uint8_t f             //!< SPI field identifier identifies selected fields information in SPI MAP arrays
                  )
{
  long usr_field_val;
  uint8_t field_size, i;
  long max_num=1, pow2=1;

  Serial.print("CURRENT STATE (HEX): ");
  Serial.print(field_name);
  Serial.print("= 0x");
  Serial.println(field_val, HEX);

  if (get_LTC6954_SPI_FIELD_RW(f)==0)
  {
    field_size=get_LTC6954_SPI_FIELD_NUMBITS(f);
    for (i=1; i<field_size; i++)
    {
      pow2=pow2*2;
      max_num=max_num + pow2;
    }

    Serial.print("What value should ");
    Serial.print(field_name);
    Serial.print(" be set to or type '-1' to exit: (ex: HEX format 0x00 to 0x");
    Serial.print(max_num, HEX);
    Serial.print(")");
    usr_field_val = read_int();  //! Reads the user command

    if (usr_field_val>=0 && usr_field_val<=max_num)
    {
      Serial.println(usr_field_val);
      return usr_field_val;
    }
    else
    {
      return field_val;
    } // end of if statement
  } // end of if statement
} // end of field_menu_RW


/* ------------------------------------------------------------------------- */
//! Menu 3: Reads and/or Writes individual SPI fields
//!  This function provides the user with a list of all SPI fields.
//!  The user can select a SPI field to read its current value.
//!  Then the user will be provided with an option to write to that field
//!  or return to the selection menu.
//!
//!  EXAMPLE:
//!  - 1-CMSINV0      9-LVCS2        17-PD_DIV2
//!  - 2-CMSINV1      10-M0          18-PD_OUT0
//!  - ....
//!  - 7-LVCS0        15-PD_DIV0     23-SYNC_EN1
//!  - 8-LVCS1        16-PD_DIV1     24-SYNC_EN2
//!  - 0 - Return to Main Menu
//!  - * = READ ONLY FIELD
//!  - Enter a command (1-24 to modify register, or '0' to return to Main Menu):
//! @return void
void menu_3_RW_to_reg_field()
{
  uint8_t  field_num;
  long field_val;

// Read/Write loop, can exit loop by choosing 'm'
  field_num=1;
  while  (field_num != 0)
  {
    Serial.println(F("\n*****************************************************************"));
    // Select Fields to read and write to
    Serial.print(F("1-CMSINV0     9-LVCS2        17-PD_DIV2\n"));
    Serial.print(F("2-CMSINV1     10-M0          18-PD_OUT0\n"));
    Serial.print(F("3-CMSINV2     11-M1          19-PD_OUT1\n"));
    Serial.print(F("4-DEL0        12-M2          20-PD_OUT2\n"));
    Serial.print(F("5-DEL1        13-PART *      21-REV *\n"));
    Serial.print(F("6-DEL2        14-PDALL       22-SYNC_EN0\n"));
    Serial.print(F("7-LVCS0       15-PD_DIV0     23-SYNC_EN1\n"));
    Serial.print(F("8-LVCS1       16-PD_DIV1     24-SYNC_EN2\n"));
    Serial.print("0 - Return to Main Menu\n");
    Serial.print("* = READ ONLY FIELD\n\n");

    Serial.print("Enter a command (1-24 to modify register, or '0' to return to Main Menu): ");
    field_num = read_int();  //! Reads the user command
    Serial.println(field_num);

    // User input: enter new setting for selected register
    if (field_num > 0)
    {
      switch (field_num)        //! Prints the appropriate submenu
      {
        case LTC6954_CMSINV0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_CMSINV0);    // reads selected field
          field_val=field_menu_RW(field_val,"CMSINV0",LTC6954_CMSINV0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_CMSINV0, field_val); // updates selected field
          }
          break;

        case LTC6954_CMSINV1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_CMSINV1);    // reads selected field
          field_val=field_menu_RW(field_val,"CMSINV1",LTC6954_CMSINV1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_CMSINV1, field_val); // updates selected field
          }
          break;

        case LTC6954_CMSINV2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_CMSINV2);    // reads selected field
          field_val=field_menu_RW(field_val,"CMSINV2",LTC6954_CMSINV2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_CMSINV2, field_val); // updates selected field
          }
          break;

        case LTC6954_DEL0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_DEL0);    // reads selected field
          field_val=field_menu_RW(field_val,"DEL0",LTC6954_DEL0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_DEL0, field_val); // updates selected field
          }
          break;

        case LTC6954_DEL1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_DEL1);    // reads selected field
          field_val=field_menu_RW(field_val,"DEL1",LTC6954_DEL1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_DEL1, field_val); // updates selected field
          }
          break;

        case LTC6954_DEL2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_DEL2);    // reads selected field
          field_val=field_menu_RW(field_val,"DEL2",LTC6954_DEL2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_DEL2, field_val); // updates selected field
          }
          break;

        case LTC6954_LVCS0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_LVCS0);    // reads selected field
          field_val=field_menu_RW(field_val,"LVCS0",LTC6954_LVCS0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_LVCS0, field_val); // updates selected field
          }
          break;

        case LTC6954_LVCS1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_LVCS1);    // reads selected field
          field_val=field_menu_RW(field_val,"LVCS1",LTC6954_LVCS1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_LVCS1, field_val); // updates selected field
          }
          break;

        case LTC6954_LVCS2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_LVCS2);    // reads selected field
          field_val=field_menu_RW(field_val,"LVCS2",LTC6954_LVCS2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_LVCS2, field_val); // updates selected field
          }
          break;

        case LTC6954_M0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_M0);    // reads selected field
          field_val=field_menu_RW(field_val,"M0",LTC6954_M0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_M0, field_val); // updates selected field
          }
          break;

        case LTC6954_M1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_M1);    // reads selected field
          field_val=field_menu_RW(field_val,"M1",LTC6954_M1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_M1, field_val); // updates selected field
          }
          break;

        case LTC6954_M2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_M2);    // reads selected field
          field_val=field_menu_RW(field_val,"M2",LTC6954_M2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_M2, field_val); // updates selected field
          }
          break;

        case LTC6954_PART:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PART);    // reads selected field
          field_val=field_menu_RW(field_val,"PART",LTC6954_PART);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PART, field_val); // updates selected field
          }
          break;

        case LTC6954_PDALL:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PDALL);    // reads selected field
          field_val=field_menu_RW(field_val,"PDALL",LTC6954_PDALL);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PDALL, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_DIV0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_DIV0);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_DIV0",LTC6954_PD_DIV0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_DIV0, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_DIV1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_DIV1);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_DIV1",LTC6954_PD_DIV1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_DIV1, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_DIV2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_DIV2);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_DIV2",LTC6954_PD_DIV2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_DIV2, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_OUT0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_OUT0);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_OUT0",LTC6954_PD_OUT0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_OUT0, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_OUT1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_OUT1);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_OUT1",LTC6954_PD_OUT1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_OUT1, field_val); // updates selected field
          }
          break;

        case LTC6954_PD_OUT2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_PD_OUT2);    // reads selected field
          field_val=field_menu_RW(field_val,"PD_OUT2",LTC6954_PD_OUT2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_PD_OUT2, field_val); // updates selected field
          }
          break;

        case LTC6954_REV:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_REV);    // reads selected field
          field_val=field_menu_RW(field_val,"REV",LTC6954_REV);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_REV, field_val); // updates selected field
          }
          break;

        case LTC6954_SYNC_EN0:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_SYNC_EN0);    // reads selected field
          field_val=field_menu_RW(field_val,"SYNC_EN0",LTC6954_SYNC_EN0);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_SYNC_EN0, field_val); // updates selected field
          }
          break;

        case LTC6954_SYNC_EN1:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_SYNC_EN1);    // reads selected field
          field_val=field_menu_RW(field_val,"SYNC_EN1",LTC6954_SYNC_EN1);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_SYNC_EN1, field_val); // updates selected field
          }
          break;

        case LTC6954_SYNC_EN2:
          field_val=get_LTC6954_SPI_FIELD(LTC6954_CS,LTC6954_SYNC_EN2);    // reads selected field
          field_val=field_menu_RW(field_val,"SYNC_EN2",LTC6954_SYNC_EN2);      // user interface control and printout
          if (field_val>-1)
          {
            set_LTC6954_SPI_FIELD(LTC6954_CS, LTC6954_SYNC_EN2, field_val); // updates selected field
          }
          break;
      }  // end of switch statement
    } // end if user_command != 0 statement
  } // end while loop
}  // end menu_3_RW_to_reg_field function

/* ------------------------------------------------------------------------- */
//! Store PLL settings to nonvolatile EEPROM on demo board
//! @return void
void menu_4_store_settings()
{
// Store the PLL Settings to the EEPROM
  uint8_t regval;

  uint8_t addr_offset;
  uint8_t num_reg;

  addr_offset=2;
  num_reg = get_LTC6954_REGSIZE();

  eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS);         // Cal key

  for (uint8_t i = 0; i <= num_reg ; i++)
  {
    regval = LTC6954_read(LTC6954_CS,i);
    eeprom_write_byte(EEPROM_I2C_ADDRESS,(char) regval, EEPROM_CAL_STATUS_ADDRESS+ i+addr_offset);
  }
  Serial.println(F("PLL Settings Stored to EEPROM"));

}


/* ------------------------------------------------------------------------- */
//! Read stored PLL settings from nonvolatile EEPROM on demo board
//! @return void
void menu_5_restore_settings()
{
// Read the PLL settings from EEPROM
  int16_t cal_key;
  uint8_t regval;
  uint8_t user_address;

  uint8_t addr_offset;
  uint8_t num_reg;

  addr_offset=2;
  num_reg = get_LTC6954_REGSIZE();

// read the cal key from the EEPROM
  eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
  if (cal_key == EEPROM_CAL_KEY)
  {
    // PLL Settings has been stored, read PLL Settings
    user_address=2;
    for (uint8_t i = 0; i <= num_reg ; i++)
    {
      eeprom_read_byte(EEPROM_I2C_ADDRESS,(char *) &regval, EEPROM_CAL_STATUS_ADDRESS + i+addr_offset);
      LTC6954_write(LTC6954_CS, (uint8_t)i, regval);
      user_address++;
    }
    Serial.println(F("PLL Settings Restored"));
  }
  else
  {
    Serial.println(F("PLL Settings not found"));
  }

}

/* ------------------------------------------------------------------------- */
//!    Prints the title block when program first starts.
void print_title()
{

  Serial.println(F("*****************************************************************"));
  Serial.println(F("* DC1954 Demonstration Program                                  *"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("* This program demonstrates how to send data to the LTC6954     *"));
  Serial.println(F("* Low Phase Noise, Triple Output Clock Distribution             *"));
  Serial.println(F("* Divider/Driver.                                               *"));
  Serial.println(F("* Set the baud rate to 115200 and select the newline terminator.*"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("*****************************************************************"));
  Serial.println();
} // end of print_title


/* ------------------------------------------------------------------------- */
//!    Prints main menu.
void print_prompt()
{

  Serial.println(F("\nCommand Summary:"));
  Serial.println(F("  1-Load Default Settings (same as the LTC6954 GUI's LTC6954.6954set settings)"));
  Serial.println(F("  2-READ/WRITE to Registers Addresses"));
  Serial.println(F("  3-READ/WRITE to Registers Fields"));
  Serial.println(F("  4-Store LTC6954 SPI settings to the DC1954's EEPROM"));
  Serial.println(F("  5-Restore LTC6954 SPI settings from the DC1954's EEPROM"));
  Serial.println("");
  Serial.print(F("Enter a command: "));
} // end of print_prompt


Download LTC6954 - Linduino Header File

/*!
 LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver

@verbatim
 SPI DATA FORMAT (MSB First):

 Write Sequence:
       Byte #1                    Byte #2
 MOSI: A6 A5 A4 A3 A2 A1 A0 W   D7 D6 D5 D4 D3 D2 D1 D0
 MISO: X  X  X  X  X  X  X  X   X  X  X  X  X  X  X  X

 Read Sequence:
       Byte #1                    Byte #2
 MOSI: A6 A5 A4 A3 A2 A1 A0 R   X  X  X  X  X  X  X  X
 MISO: X  X  X  X  X  X  X  X   D7 D6 D5 D4 D3 D2 D1 D0

 W    : SPI Write (0)
 R    : SPI Read  (1)
 Ax   : Address
 Dx   : Data Bits
 X    : Don't care

@endverbatim

http://www.linear.com/product/LTC6954

http://www.linear.com/product/LTC6954#demoboards

REVISION HISTORY
$Revision: 3659 $
$Date: 2015-07-01 10:19:20 -0700 (Wed, 01 Jul 2015) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/

/*! @file
    @ingroup LTC6954
    Header for LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver
*/

#ifndef LTC6954_H

#define LTC6954_H


//! Define the SPI CS pin
#ifndef LTC6954_CS
#define LTC6954_CS QUIKEVAL_CS  //! SPI Chip Select Pin
#endif


/*! @name LTC6954 Registers Fields in Alphabetical Order */
#define LTC6954_CMSINV0 1   //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_CMSINV1 2   //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_CMSINV2 3   //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_DEL0 4      //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_DEL1 5      //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_DEL2 6      //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_LVCS0 7     //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_LVCS1 8     //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_LVCS2 9     //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_M0 10       //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_M1 11       //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_M2 12       //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PART 13     //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PDALL 14    //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_DIV0 15  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_DIV1 16  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_DIV2 17  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_OUT0 18  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_OUT1 19  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_PD_OUT2 20  //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_REV 21      //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_SYNC_EN0 22 //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_SYNC_EN1 23 //!<  for spi_map array, defines location for field specific information used to create the spi map
#define LTC6954_SYNC_EN2 24 //!<  for spi_map array, defines location for field specific information used to create the spi map

#define LTC6954_NUM_REGADDR 8  //!< Defines number of LTC6954 SPI registers, used in spi_map array
#define LTC6954_NUM_REGFIELD 24 //!< Defines number of LTC6954 SPI fields, used in spi_map array

#define ADDRx 0                 //!< used for 2nd dim of 2d spi_map array
#define DxMSB 1                 //!< used for 2nd dim of 2d spi_map array
#define NUMBITS 2               //!< used for 2nd dim of 2d spi_map array
#define R_ONLY 3                //!< used for 2nd dim of 2d spi_map array


//! @} */

/* ------------------------------------------------------------------------- */
//! LTC6954 Read Single Address
//!  reads 8 bit Data field to LTC6954.
//!  has to shift data by one bit to account for RW bit
//! @return data that was read from address
uint8_t LTC6954_read(uint8_t cs,    //!< Chip Select Pin
                     int8_t address //!< Register address for the LTC6954.
                    );


/* ------------------------------------------------------------------------- */
//! LTC6954 Read Single Field
//! For SPI FIELDS located in 1 or multiple address locations
//!  reads specific address locations
//!  identifies and returns specific field in question
//!  can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
//! @return data that was read from field
long LTC6954_read_field(uint8_t cs,       //!< Chip Select Pin
                        uint8_t address,  //!< Register address for the LTC6954.
                        uint8_t MSB_loc,  //!< MSB bit location of field
                        uint8_t numbits   //!< length of field (i.e. number of bits in field)
                       );


/* ------------------------------------------------------------------------- */
//! Gets the LTC6954 SPI field value
//! calls function LTC6954_read_field, which
//!  reads specific address locations
//!  identifies and returns specific field in question
//!  can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
//! @return data that was read from field
long get_LTC6954_SPI_FIELD(uint8_t cs,          //!< Chip Select Pin
                           uint8_t f            //!< SPI field number
                          );


/* ------------------------------------------------------------------------- */
//! LTC6954 Write Single Address
//!  writes 8 bit Data field to LTC6954.
//!  has to shift data by one bit to account for RW bit
//! @return void
void LTC6954_write(uint8_t cs,                  //!< Chip Select Pin
                   uint8_t address,             //!< Register address for the LTC6954.
                   uint8_t Data                 //!< 8-bit data to be written to register
                  );


/* ------------------------------------------------------------------------- */
//! LTC6954 Write Single Field
//!  For SPI FIELDS in 1 or multiple address locations
//!  reads specific address/field location then writes to specific field
//!  can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
//! @return void
uint8_t LTC6954_write_field(uint8_t cs,        //!< Chip Select Pin
                            long field_data,   //!< Value field value to be set to
                            uint8_t address,   //!< Register address for the LTC6954.
                            uint8_t MSB_loc,   //!< MSB bit location of field
                            uint8_t numbits   //!< length of field (i.e. number of bits in field)
                           );


/* ------------------------------------------------------------------------- */
//! Sets the LTC6954 SPI field value
//! calls function LTC6954_read_field, which
//!  reads specific address/field location then writes to specific field
//!  can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
//! @return void
void set_LTC6954_SPI_FIELD(uint8_t cs,          //!< Chip Select Pin
                           uint8_t f,           //!< SPI field number
                           long field_data      //!< Value field value to be set to
                          );


/* ------------------------------------------------------------------------- */
//! Writes values to ALL LTC6954 RW address
//! @return void
void set_LTC6954_ALLREGS(uint8_t cs,            //!< Chip Select Pin
                         uint8_t reg00,         //!< LTC6954 register 0
                         uint8_t reg01,         //!< LTC6954 register 1
                         uint8_t reg02,         //!< LTC6954 register 2
                         uint8_t reg03,         //!< LTC6954 register 3
                         uint8_t reg04,         //!< LTC6954 register 4
                         uint8_t reg05,         //!< LTC6954 register 5
                         uint8_t reg06         //!< LTC6954 register 6
                        );

/* ------------------------------------------------------------------------- */
//! Initializes the SPI MAP arrays
//! The values set in initialization are used all the LTC6954 SPI/WRITE and
//! read functions (set_LTC6954_SPI_FIELD, get_LTC6954_SPI_FIELD,
//! LTC6954_read, LTC6954_write, etc, etc)
//! @return void
void LTC6954_init();


/* ------------------------------------------------------------------------- */
//! returns # of addresses in parts register map (array size)
//! @return # of addresses in parts register map
uint8_t get_LTC6954_REGSIZE();


/* ------------------------------------------------------------------------- */
//! returns the number of bits for a given field name in the SPI map
//! @return the number of bits for a given field name in the SPI map
uint8_t get_LTC6954_SPI_FIELD_NUMBITS(uint8_t f //!< SPI field number
                                     );


/* ------------------------------------------------------------------------- */
//! returns if the given field name is (0)read/write or (1)read_only field
//! @return if the given field is a (0)read/write or (1)read_only field
uint8_t get_LTC6954_SPI_FIELD_RW(uint8_t f   //!< SPI field number
                                ) ;



#endif  // LTC6954_H

Download LTC6954 - Linduino.CPP File

/*!
    LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver

@verbatim

The LTC®6954 is a family of very low phase noise clock
distribution parts. Each part has three outputs and each
output has an individually programmable frequency
divider and delay.

There are four members of the family, differing in their output logic signal type:
LTC6954-1: Three LVPECL outputs
LTC6954-2: Two LVPECL and one LVDS/CMOS outputs
LTC6954-3: One LVPECL and two LVDS/CMOS outputs
LTC6954-4: Three LVDS/CMOS outputs

Each output is individually programmable to divide the
input frequency by any integer from 1 to 63, and to delay
each output by 0 to 63 input clock cycles. The output duty
cycle is always 50%, regardless of the divide number.

The LVDS/CMOS outputs are jumper selectable via the
OUTSEL pins to provide either an LVDS logic output or a
CMOS logic output.

The LTC6954 also features Linear Technology’s EZSync
system for perfect clock synchronization and alignment
every time.

The LTC6954 is available in a 36-lead, 4mm × 7mm QFN
package.

All device settings are controlled through an SPI-compatible
serial port.

@endverbatim


http://www.linear.com/product/LTC6954

http://www.linear.com/product/LTC6954#demoboards

REVISION HISTORY
$Revision: 3659 $
$Date: 2015-07-01 10:19:20 -0700 (Wed, 01 Jul 2015) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/

//! @defgroup LTC6954 LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver

/*! @file
    @ingroup LTC6954
    Library for LTC6954: Low Phase Noise, Triple Output Clock Distribution Divider/Driver
*/

#include <stdint.h>
#include <Arduino.h>
#include "Linduino.h"
#include "UserInterface.h"
#include "LT_SPI.h"
#include "LTC6954.h"
#include <SPI.h>

uint8_t LTC6954_reg[LTC6954_NUM_REGADDR];             //!< number of LTC6954 spi addresses
uint8_t LTC6954_spi_map[(LTC6954_NUM_REGFIELD+1)][4]; //!< LTC6954 spi map, stores MSB address location, MSB bit location, field length in bits, and R or RW capability


/* -------------------------------------------------------------------------
  FUNCTION: LTC6954_read
  - reads 8 bit Data field to LTC6954.
  - has to shift data by one bit to account for RW bit
 -------------------------------------------------------------------------- */
uint8_t LTC6954_read(uint8_t cs, int8_t address)
{
  int8_t address_shift;
  LT_union_int16_2bytes rx;

  address_shift =(address << 1) | 0x01; // shift to left to account for R/W bit, set bit high for read
  spi_transfer_word(cs, address_shift<<8 , &rx.LT_uint16);

  LTC6954_reg[address]=rx.LT_byte[0];
  return(rx.LT_byte[0]);
}


/* -------------------------------------------------------------------------
  FUNCTION: LTC6954_read_field
  For SPI FIELDS located in 1 or multiple address location
  - reads specific address locations
  - identifies and returns specific field in question
    - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
--------------------------------------------------------------------------- */
long LTC6954_read_field(uint8_t cs, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
{
  int bit_shift, i, num_reg;
  long field_val, maskbits, pow2;

  num_reg=0;
  field_val=0;
// determines how many register are used
  do
  {
    bit_shift = (MSB_loc+1)- (numbits-num_reg*8);   // determines bit_shift for last register location
    field_val=LTC6954_read(cs, (address+num_reg))+(field_val<<8);  // reads current address locations, shifts previous address location 8 bits
    num_reg++;
  }
  while ((bit_shift<0) && (num_reg<4));

// creates a bit mask for complete word,
  maskbits = 1;
  pow2=1;
  for (i=1, maskbits=1; i<numbits; i++)
  {
    pow2=pow2*2;
    maskbits = maskbits+pow2;
  }

  field_val=(field_val >>bit_shift) &maskbits;
  return field_val;
}

/* -------------------------------------------------------------------------
  FUNCTION: get_LTC6954_SPI_FIELD
  For SPI FIELDS
  - reads specific address locations
  - identifies and returns specific field in question
    - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
--------------------------------------------------------------------------- */
long get_LTC6954_SPI_FIELD(uint8_t cs, uint8_t f)
{

  return LTC6954_read_field(cs, LTC6954_spi_map[f][ADDRx], LTC6954_spi_map[f][DxMSB], LTC6954_spi_map[f][NUMBITS]);
}

/* -------------------------------------------------------------------------
  FUNCTION: LTC6954_write
  - writes 8 bit Data field to LTC6954.
  - has to shift data by one bit to account for RW bit
--------------------------------------------------------------------------- */
void LTC6954_write(uint8_t cs, uint8_t address, uint8_t Data)
{
  LT_union_int16_2bytes rx;

  address=address << 1; // shift to left to account for R/W bit
  spi_transfer_word(cs, (address<<8) | Data, &rx.LT_uint16);
}


/* -------------------------------------------------------------------------
 FUNCTION: LTC6954_write_field
 For SPI FIELDS
 - reads specific address location
 - identifies and returns specific field in question
   - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
---------------------------------------------------------------------------- */
uint8_t LTC6954_write_field(uint8_t cs, long field_data, uint8_t address, uint8_t MSB_loc, uint8_t numbits)
{
  long current_content, desired_content, reg_val;
  int LSB_loc, i, j, num_reg, bit_shift;
  long temp_arr[32];

  for (i=0; i<32 ; i++) temp_arr[i]=0;  // init temp_arr

// read data in current address location and put in a bit array
  num_reg=0;
  current_content=0;
  do
  {
    bit_shift=(MSB_loc+1)-(numbits-num_reg*8);
    current_content=LTC6954_read(cs, (address+num_reg)) + (current_content<<8);

    num_reg++;
  }
  while ((bit_shift<0) && (num_reg<4));
  for (i=0; i<(8*num_reg); i++)
  {
    temp_arr[i]=(current_content>>i) & 1;
  }

// exchange current bits with desired bits
  LSB_loc = 8*(num_reg-1)+MSB_loc-numbits+1;
  for (i=LSB_loc, j=0; i<=(MSB_loc+(num_reg-1)*8); i++, j++)
  {
    temp_arr[i] = (field_data>>j) &1;
  } // end of for loop

// reconstruct bits into an integer
  desired_content = 0;
  for (i=0; i<(8*num_reg); i++)
  {
    desired_content = desired_content | (temp_arr[i]<<i);
  } // end of for loop

// write new field value to part
  for (i=0; i<num_reg; i++)
  {
    reg_val = (desired_content >> 8*(num_reg-1-i)) & 0xff;
    LTC6954_write(cs, (address+i), reg_val);
  } // end of for loop
} // end of LTC6954_write_field


/* -------------------------------------------------------------------------
   FUNCTION: get_LTC6954_REGSIZE
   - returns # of addresses in parts register map (array size)
---------------------------------------------------------------------------- */
uint8_t get_LTC6954_REGSIZE()
{
  return sizeof(LTC6954_reg);
}


/* -------------------------------------------------------------------------
   FUNCTION: get_LTC6954_SPI_FIELD_NUMBITS
   - returns the number of bits for a given field name in the SPI map
---------------------------------------------------------------------------- */
uint8_t get_LTC6954_SPI_FIELD_NUMBITS(uint8_t f)
{
  return LTC6954_spi_map[f][NUMBITS];
}


/* -------------------------------------------------------------------------
   FUNCTION: get_LTC6954_SPI_FIELD_RW
   - returns if the given field name is (0)read/write or (1)read_only field
---------------------------------------------------------------------------- */
uint8_t get_LTC6954_SPI_FIELD_RW(uint8_t f)
{
  return LTC6954_spi_map[f][R_ONLY];
}


/* -------------------------------------------------------------------------
   FUNCTION: set_LTC6954_SPI_FIELD
   For SPI FIELDS
   - reads specific address location
   - identifies and returns specific field in question
   - can handle SPI fields in multiple addresses, if MSB bit is in the lower number address
---------------------------------------------------------------------------- */
void set_LTC6954_SPI_FIELD(uint8_t cs, uint8_t f, long field_data)
{
  LTC6954_write_field(cs, field_data, LTC6954_spi_map[f][ADDRx], LTC6954_spi_map[f][DxMSB], LTC6954_spi_map[f][NUMBITS]);
}


/* -------------------------------------------------------------------------
   FUNCTION: set_LTC6954_ALLREGS
   - writes data to all registers at once
--------------------------------------------------------------------------- */
void set_LTC6954_ALLREGS(uint8_t cs, uint8_t reg00, uint8_t reg01, uint8_t reg02, uint8_t reg03, uint8_t reg04, uint8_t reg05, uint8_t reg06)
{
  uint8_t i;

  LTC6954_reg[0] = reg00;
  LTC6954_reg[1] = reg01;
  LTC6954_reg[2] = reg02;
  LTC6954_reg[3] = reg03;
  LTC6954_reg[4] = reg04;
  LTC6954_reg[5] = reg05;
  LTC6954_reg[6] = reg06;


  for (i=0; i<get_LTC6954_REGSIZE(); i++)  LTC6954_write(cs, i, LTC6954_reg[i]);
} // end of set_LTC6954_ALLREGS


/* -------------------------------------------------------------------------
   FUNCTION: LTC6954_init
   - initializes the SPI MAP
   - for ease of programming there is spreadsheet that automates this some.
----------------------------------------------------------------------------*/
void LTC6954_init()
{

// spi map
  LTC6954_spi_map[LTC6954_CMSINV0][ADDRx]=0x01;
  LTC6954_spi_map[LTC6954_CMSINV0][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_CMSINV0][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_CMSINV1][ADDRx]=0x03;
  LTC6954_spi_map[LTC6954_CMSINV1][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_CMSINV1][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_CMSINV2][ADDRx]=0x05;
  LTC6954_spi_map[LTC6954_CMSINV2][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_CMSINV2][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_DEL0][ADDRx]=0x01;
  LTC6954_spi_map[LTC6954_DEL0][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_DEL0][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_DEL1][ADDRx]=0x03;
  LTC6954_spi_map[LTC6954_DEL1][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_DEL1][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_DEL2][ADDRx]=0x05;
  LTC6954_spi_map[LTC6954_DEL2][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_DEL2][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_LVCS0][ADDRx]=0x02;
  LTC6954_spi_map[LTC6954_LVCS0][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_LVCS0][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_LVCS1][ADDRx]=0x04;
  LTC6954_spi_map[LTC6954_LVCS1][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_LVCS1][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_LVCS2][ADDRx]=0x06;
  LTC6954_spi_map[LTC6954_LVCS2][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_LVCS2][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_M0][ADDRx]=0x02;
  LTC6954_spi_map[LTC6954_M0][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_M0][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_M1][ADDRx]=0x04;
  LTC6954_spi_map[LTC6954_M1][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_M1][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_M2][ADDRx]=0x06;
  LTC6954_spi_map[LTC6954_M2][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_M2][NUMBITS]= 6;
  LTC6954_spi_map[LTC6954_PART][ADDRx]=0x07;
  LTC6954_spi_map[LTC6954_PART][DxMSB]= 4;
  LTC6954_spi_map[LTC6954_PART][NUMBITS]= 5;
  LTC6954_spi_map[LTC6954_PDALL][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PDALL][DxMSB]= 6;
  LTC6954_spi_map[LTC6954_PDALL][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_DIV0][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_DIV0][DxMSB]= 0;
  LTC6954_spi_map[LTC6954_PD_DIV0][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_DIV1][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_DIV1][DxMSB]= 2;
  LTC6954_spi_map[LTC6954_PD_DIV1][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_DIV2][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_DIV2][DxMSB]= 4;
  LTC6954_spi_map[LTC6954_PD_DIV2][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_OUT0][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_OUT0][DxMSB]= 1;
  LTC6954_spi_map[LTC6954_PD_OUT0][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_OUT1][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_OUT1][DxMSB]= 3;
  LTC6954_spi_map[LTC6954_PD_OUT1][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_PD_OUT2][ADDRx]=0x00;
  LTC6954_spi_map[LTC6954_PD_OUT2][DxMSB]= 5;
  LTC6954_spi_map[LTC6954_PD_OUT2][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_REV][ADDRx]=0x07;
  LTC6954_spi_map[LTC6954_REV][DxMSB]= 7;
  LTC6954_spi_map[LTC6954_REV][NUMBITS]= 3;
  LTC6954_spi_map[LTC6954_SYNC_EN0][ADDRx]=0x01;
  LTC6954_spi_map[LTC6954_SYNC_EN0][DxMSB]= 7;
  LTC6954_spi_map[LTC6954_SYNC_EN0][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_SYNC_EN1][ADDRx]=0x03;
  LTC6954_spi_map[LTC6954_SYNC_EN1][DxMSB]= 7;
  LTC6954_spi_map[LTC6954_SYNC_EN1][NUMBITS]= 1;
  LTC6954_spi_map[LTC6954_SYNC_EN2][ADDRx]=0x05;
  LTC6954_spi_map[LTC6954_SYNC_EN2][DxMSB]= 7;
  LTC6954_spi_map[LTC6954_SYNC_EN2][NUMBITS]= 1;


  LTC6954_spi_map[LTC6954_CMSINV0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_CMSINV1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_CMSINV2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_DEL0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_DEL1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_DEL2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_LVCS0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_LVCS1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_LVCS2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_M0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_M1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_M2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PART][R_ONLY]= 1;
  LTC6954_spi_map[LTC6954_PDALL][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_DIV0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_DIV1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_DIV2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_OUT0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_OUT1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_PD_OUT2][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_REV][R_ONLY]= 1;
  LTC6954_spi_map[LTC6954_SYNC_EN0][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_SYNC_EN1][R_ONLY]= 0;
  LTC6954_spi_map[LTC6954_SYNC_EN2][R_ONLY]= 0;


} // end of LTC6954_init

技术支持