LTC2874 - Quad IO-Link Master Hot Swap Controller and PHY

Features

  • IO-Link® Compatible (COM1/COM2/COM3)
  • 8V to 34V Operation
  • Hot Swap™ Controller Protected Supply Outputs
  • Discrete Power MOSFETs for Ruggedness and Flexibility
  • Configurable 100mA (4-Port), 200mA (2-Port), or 400mA (1-Port) CQ Drive Capability
  • Automatic Wake-Up Pulse Generation
  • Automatic Cable Sensing
  • CQ Pins Protected to ±50V
  • Configurable L+ Current Limit with Foldback
  • Short Circuit, Input UV/OV and Thermal Protection
  • Optional Interrupt and Auto-Retry after Faults
  • 2.9V to 5.5V Logic Supply for Flexible Digital Interface
  • No Damage or Latchup to ±8kV HBM ESD
  • 38-Lead (5mm × 7mm) QFN and TSSOP Packages

Typical Application

LTC2874 Typical Application
LTC2874 Typical Application

Description

The LTC®2874 provides a rugged, 4-port IO-Link power and communications interface to remote devices connected by cables up to 20m in length.

Output supply voltage and inrush current are ramped up in a controlled manner using external N-channel MOSFETs, providing improved robustness compared to fully integrated solutions.

Wake-up pulse generation, line noise suppression, connection sensing and automatic restart after fault conditions are supported, along with signaling at 4.8kb/s, 38.4kb/s, and 230.4kb/s.

Configuration and fault reporting are exchanged using a SPI-compatible 4-wire interface that operates at clock rates up to 20MHz.

The LTC2874 implements an IO-Link master PHY. For IO-Link device designs, see the LT®3669.

Packaging

CAD Symbols and Footprints: The downloadable Zip file below contains the schematic symbol and PCB footprints.

For complete and up to date package information and drawings, please refer to our packaging page

Part Number Package Code Temp Package
Drawing
RoHS
LTC2874IFE#PBF TSSOP-38 FE I 05-08-1772 Yes
LTC2874IFE#TRPBF TSSOP-38 FE I 05-08-1772 Yes
LTC2874IUHF#PBF 5x7 QFN-38 UHF I 05-08-1701 Yes
LTC2874IUHF#TRPBF 5x7 QFN-38 UHF I 05-08-1701 Yes


LTC2874 Package Drawing
LTC2874 Package Drawing

Order Info

  • Part numbers ending in PBF are lead free. Solder plated terminal finish (SnPb) versions are non-standard and special terms and conditions and pricing applies if available. Please contact LTC marketing for information.
  • Part numbers containing TR or TRM are shipped in tape and reel or 500 unit mini tape and reel, respectively
  • Please refer to our general ordering information or the product datasheet for more details

Package Variations and Pricing

Part Number Package Temp Price
(1-99)
Price
(1k)*
RoHS
LTC2874IFE#PBF TSSOP-38 I $11.79 $8.25 Yes
LTC2874IFE#TRPBF TSSOP-38 I $11.85 $8.31 Yes
LTC2874IUHF#PBF 5x7 QFN-38 I $11.34 $7.94 Yes
LTC2874IUHF#TRPBF 5x7 QFN-38 I $11.40 $8.00 Yes
Buy NowRequest Samples
* The USA list pricing shown is for BUDGETARY USE ONLY, shown in United States dollars (FOB USA per unit for the stated volume), and is subject to change. International prices may differ due to local duties, taxes, fees and exchange rates. For volume-specific price or delivery quotes, please contact your local Linear Technology sales office or authorized distributor.

Demo Boards

Linear Technology offers many demo boards free of charge to qualified customers. Contact your local sales office or distributor to inquire about a demo board. Certain demo boards are also available for sale via credit card on this website. Demo boards are for evaluation purposes only. It remains the customer’s responsibility to verify proper and reliable operation in the actual end application.

Part Number Description Price Documentation
DC1880A LTC2874 Demo Board | Quad IO-Link Master Hot Swap Power Controller and PHY (req. DC2026) $125.00
DC2228A 8-Port IO-Link Master Reference Design. Includes LTC2874, LT4275A, IO-Link v1.1 Protocol Stack and Control Tool. Optionally powered by DC1814A-D PoE supply. $599.00
Buy Now

Companion Boards

Part Number Description Price Documentation
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
DC1814A-D LTC4274A-4 Demo Board | LTPoE++ (90W) PSE $100.00
DC2227A LT3669-2 Demo Board | I/O Link with 18V to 36V Input to 4V at 300mA and 3.3V at 150mA $299.00
Buy Now
Click here to view our complete list of demo boards

Applications

  • IO-Link Masters
  • Intelligent Sensors and Actuators
  • Factory Automation Networks

Product Notifications

Please login to your MyLinear account for notifications of datasheet updates, new document releases and LTspice model announcements for your favorite products. If you do not have a MyLinear account you may Sign Up Now.

Forgot your password? Click here.
Need help? Email mylinear@linear.com with questions and comments.

Design Tools

Linduino

Linduino is an Arduino compatible platform for developing and distributing firmware libraries and code for SPI and I²C-compatible integrated circuits. The Linduino One board interfaces to more than 300 QuikEval demonstration cards, supporting a variety of product types including analog-to-digital converters (ADCs)digital-to-analog converters (DACs)power monitors, and more. Firmware libraries for individual devices are written in C and designed to be portable to a wide variety of processors and microcontrollers. Each library has a demonstration program that can be uploaded to the Linduino One platform to allow the circuit and software to be quickly and easily verified.

Click here for more information on Linduino

Code

Linduino is Linear Technology's Arduino compatible system for developing and distributing firmware libraries and example code for Linear Technology’s integrated circuits. The code below can be downloaded or copied and pasted into your project. Please visit the Linduino Home Page for demo board, manual and setup information.

This part is Code Supported: There is example code available for this part. The code below may rely on other drivers available in the full library.

Download LTC2874 - DC1880A Linduino.INO File

/*!
Linear Technology DC1880A Demonstration Board

@verbatim

SETUP:
   Set the terminal baud rate to 115200 and select the newline terminator.
   External power supply is required.

USER INPUT DATA FORMAT:
 decimal : 14
 hex     : 0x0E (Data), 0xE (Reg)
  
@endverbatim
 
http://www.linear.com/product/LTC2874

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

REVISION HISTORY
$Revision: 0.1 $
$Date: 2013-12-18 $

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.

IO-Link is a registered trademark of PROFIBUS User Organization (PNO).
*/

/*! @file
    @ingroup LTC2874
*/

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


// Function Prototypes
void print_title();
void print_prompt();
uint8_t reg_test();
void print_warning_prompt();

// Menu selections from print_prompt
void menu_1_cq();
void menu_2_lplus();
void menu_3_wakeup_cq();
void menu_4_24v_mode();
void menu_5_sio_mode();
void menu_6_set_illm();
void menu_7_clear_event();
void menu_8_update_all();  
void menu_9_reset();
void menu_10_read_register();
void menu_11_write_register();
void menu_12_read_bit();  
void menu_13_write_bit_set();
void menu_14_write_bit_clr();


// Demo Board Name
char demo_name[] = "DC1880";            //!< Demo Board Name stored in QuikEval EEPROM

// ***Global Variables***

uint8_t demo_board_connected;           //!< Set to 1 if the board is connected

//******************************** Initialize Linduino *******************************
//! Initialize Linduino

void setup()
// Setup the Program
{
  quikeval_I2C_init();                    //! Initializes Linduino I2C port.
  
  output_high(LTC2874_CS);                //! Pulls LTC2874 Chip Select High
   
  quikeval_SPI_init();                    //! Configures the SPI port for 4Mhz SCK
  quikeval_SPI_connect();                 //! Connects SPI to QuikEval port
  Serial.begin(115200);                   //! Initializes the serial port to the PC
  print_title();                          //! Displays the title
  quikeval_I2C_connect(); 
  
  //! Checks if correct demo board is connected.
  demo_board_connected = discover_demo_board(demo_name); 
  quikeval_SPI_connect();
  //! Prints the prompt if the correct demo board is connected
  if (demo_board_connected)               
  {
    print_prompt();
  }
  else
  {
    print_warning_prompt();
    demo_board_connected = true;
  }
}


//*************************************** LOOP ***************************************
//! Repeats Linduino loop

void loop()
{
    // The main control loop
  if (demo_board_connected)       //! Does nothing if the demo board is not connected.
  {
    if (Serial.available())       //! Checks if user input is available.
    {
      int16_t user_command;       // User input command

      user_command = read_int();  //! Reads the user command (if available).
      Serial.println(user_command);
      Serial.flush();
      switch (user_command)
      {
        case 1:
          menu_1_cq();  
          break;

        case 2:
          menu_2_lplus(); 
          break;

        case 3:
          menu_3_wakeup_cq();
          break;

        case 4:
          menu_4_24v_mode();
          break;

        case 5:
          menu_5_sio_mode();
          break;

        case 6:
          menu_6_set_illm(); 
          break;

        case 7:
          menu_7_clear_event();
          break;

        case 8:
          menu_8_update_all();
          break;

        case 9:
          menu_9_reset();  
          break;
        
        case 10: 
          menu_10_read_register();
          break;

        case 11:
          menu_11_write_register();
          break;
        
        case 12:
           menu_12_read_bit();
          break;

        case 13:
          menu_13_write_bit_set();
          break;

        case 14:
          menu_14_write_bit_clr();
          break;

        default:
          Serial.println("Incorrect Option");
          break;
      }

      Serial.println("");
      Serial.println("*************************");
      print_prompt();
    }
  }
}

//************************************************************************************
//! Menu 1: Enable/Disable CQ output for specified port
//************************************************************************************
void menu_1_cq(void)
{
  uint8_t port, value = 0;

  Serial.println(F("Select CQ output (1,2,3,4, 5=ALL)"));  //get port 
  port = read_int();
  if (port == 5)
  {
   Serial.println("All"); 
  }
    else
    {
      Serial.println(port);
    }
  
  if ((port < 1) || (port > 5))                            //check limits
  {
    Serial.println(F("Selection out of range"));
    return;
  }

  Serial.println(F("Select 1 to Enable or 0 to Disable"));    //get value
  value = read_int();
  Serial.println(value);

  if ((value < 0) || (value > 1))                          //check limits for bit
  {
    Serial.println(F("Selection out of range"));  
    return;
  }
  
  LTC2874_cq_output(port, value);                        //write to register

  Serial.print(F("CQ output"));
  if (port ==5)
  {
    Serial.print("s are ");
  }
   else
   {
     Serial.print(" ");
     Serial.print(port);
     Serial.print(F(" is "));
   }
  Serial.println(value);
}

//************************************************************************************
//! Menu 2: Enable/Disable L+ output for specified port
//************************************************************************************
void menu_2_lplus(void)
{
  uint8_t port, value = 0;

  Serial.println(F("Select L+ output (1,2,3,4, 5=ALL)"));
  port = read_int();
  if (port == 5)
  {
    Serial.println("All"); 
  }
    else
    {
      Serial.println(port);
    }
  
  if ((port < 1) || (port > 5))                            //check limits
  {
    Serial.println(F("Selection out of range"));
    return;
  }

  Serial.println(F("Select 1 to Enable or 0 to Disable"));
  value = read_int();
  Serial.println(value);

  if ((value < 0) || (value > 1))                          //check limits for bit
  {
    Serial.println(F("Selection out of range"));  
    return;
  }

  LTC2874_lplus_output(port, value);

  Serial.print(F("L+ output"));
  if (port ==5)
  {
    Serial.print("s are ");
  }
   else
   {
     Serial.print(" ");
     Serial.print(port);
     Serial.print(F(" is "));
   }
   Serial.println(value);
}

//************************************************************************************
//! Menu 3: Generate Wake-Up Request (WURQ) on CQ output
//************************************************************************************
void menu_3_wakeup_cq(void)
{
  uint8_t data, port = 0;

  Serial.println(F("Generate Wakeup for CQ output (1,2,3,4)"));
  port = read_int();
  Serial.println(port);
  
  if ((port < 1) || (port > 4))                            //check limits
  {
    Serial.println(F("Selection out of range"));
    return;
  }
  LTC2874_wakeup_request(port);
  Serial.print("Wake-Up Request generated for CQ");
  Serial.print(port);
  }

//************************************************************************************
//! Menu 4: Change value of 24VMODE bit
//************************************************************************************
void menu_4_24v_mode(void)
{
  uint8_t value = 0;
  Serial.println(F("Enable (1) or Disable (0) 24V Mode"));
  value = read_int();

  if ((value < 0) || (value > 1))                          //check limits 
   {
     Serial.println(F("Selection out of range"));  
     return;
   }

  LTC2874_24v_mode(value);
  Serial.print(F("24VMODE = "));
  Serial.println(value);
}

//************************************************************************************
//! Menu 5: Change SIO_MODE setting for specified port.
//************************************************************************************
void menu_5_sio_mode(void) //!< 
{
  uint8_t port = 0;

  Serial.println(F("Enable SIO mode for CQ output (1,2,3,4, 5=ALL)"));
  port = read_int();
  if (port == 5)
  {
    Serial.println("All"); 
  }
    else
    {
      Serial.println(port);
    }
    
  if ((port < 1) || (port > 5))                            //check limits
  {
    Serial.println(F("Selection out of range"));
    return;
  }
  Serial.print(F("SIO mode set for "));
  if (port ==5)
  {
    Serial.print("ALL");
  }
   else
   {
     Serial.print("port ");
     Serial.print(port);
   }
  LTC2874_sio_mode(port);
}

//************************************************************************************
//! Menu 6: Change ILLM setting for specified port.
//************************************************************************************
void menu_6_set_illm(void)
{
  uint8_t port, value = 0;
  
  Serial.println(F("Select port for ILLM (1,2,3,4, 5=All)"));
  port = read_int();
  
  if ((port < 1) || (port > 5))                            //check limits
  {
    Serial.println(F("Selection out of range"));
    return;
  }  
  if (port == 5)
  {
    Serial.println("All"); 
  }
    else
    {
      Serial.println(port);
    }
  
  Serial.println(F("Enter value to write (0x0-0x3); use Hex 0xn format."));
  value = read_int();
  Serial.print("0x");
  Serial.println(value, HEX);
  
  if ((value < 0x0) || (value > 0x3))                      //check limits
  {
    Serial.println(F("Value out of range"));
    return;
  }
  //! Update internal register
  LTC2874_write_ILLM_value(port, value);

  return;
}

//************************************************************************************
//! Menu 7: Clear all Event registers
//************************************************************************************
void menu_7_clear_event(void)
{
  Serial.println(F("Event registers cleared"));
  LTC2874_write_register( LTC2874_EVENT1_REG2, 0x00);
  LTC2874_write_register( LTC2874_EVENT2_REG3, 0x00);
  LTC2874_write_register( LTC2874_EVENT3_REG4, 0x00);
  LTC2874_write_register_update_all( LTC2874_EVENT4_REG5, 0x00);
}
//************************************************************************************
//! Menu 8: Update all registers
//************************************************************************************
void menu_8_update_all(void)
{
  Serial.println(F("All registers updated"));
  LTC2874_update_all();
  return;
}

//************************************************************************************
//! Menu 9: Reset LTC2874
//************************************************************************************
void menu_9_reset(void)
{
  Serial.println(F("LTC2874 has been reset"));
  LTC2874_reset();
  return;
}

//************************************************************************************
//! Menu 10: Read byte of data from a register
//************************************************************************************
void menu_10_read_register(void)
{
  uint8_t address, data = 0;

  Serial.println(F("Select Register to be read (0x0-0xE); use Hex 0xn format."));
  address = read_int();      
  if ((address > 0xE ) || (address < 0x0))        //If user enters an invalid option
   {
     Serial.println("No registers in this range");
     return;
   }

  data = LTC2874_read_reg(address);

  Serial.print("Register 0x");
  Serial.print(address, HEX);
  Serial.print(" reads 0x");
  Serial.println (data, HEX);
  return;  
}

//************************************************************************************
//! Menu 11: Write byte of data to a register
//************************************************************************************
void menu_11_write_register(void)
{
  uint8_t data, address = 0;  

  address = reg_test();
  if (address == 0) 
  {
    return;
  }

  Serial.print("Selected Register is 0x");
  Serial.println(address, HEX);

  Serial.println(F("Enter data to load in register; use Hex 0xnn format."));
  data = read_int();

  Serial.print("Data loaded is 0x");
  Serial.println(data, HEX);

  LTC2874_write_register_update_all(address, data);
  return;
}

//************************************************************************************
//! Menu 12: Read one bit from a register
//************************************************************************************
void menu_12_read_bit(void)
{
  uint8_t value, address = 0;

  Serial.println(F("Select Register that contains bit to read (0x0-0xE); use Hex 0xn format."));
  Serial.println();
  address = read_int();    

  if ((address > 0xE ) || (address < 0x0))        //If user enters an invalid option
  {
    Serial.println("No registers in this range");
    return;
  }

  Serial.print("Selected Register is 0x");
  Serial.println(address, HEX);

  Serial.println(F("Enter bit position (0-7) for bit to read"));
  value = read_int();
  Serial.print("Bit position ");
  Serial.print(value);
  value = 0x01 << value;
  
  value = LTC2874_read_bit(address, value ); 
  Serial.print(" = ");
  Serial.println(value);
  return;
}

//************************************************************************************
//! Menu 13: Set one bit in writable register
//************************************************************************************
void menu_13_write_bit_set(void)
{
  uint8_t data, address = 0;

  address = reg_test();
  if (address == 0) 
  {
    return;
  }

  Serial.print("Selected Register is 0x");
  Serial.println(address, HEX);

  Serial.println(F("Enter bit position (0-7) to Set"));
  data = read_int();
  
  Serial.print("Bit position ");
  Serial.print(data);
  data = 0x01 << data;
  LTC2874_write_bit_set_update_all(address, data);         //! Update
  Serial.print(" has been Set");
  return;
}

//************************************************************************************
//! Menu 14: Clear one bit in writable register
//************************************************************************************
void menu_14_write_bit_clr(void)
{
  uint8_t data, address = 0;

  address = reg_test();
  if (address == 0) 
  {
    return;
  }

  Serial.print("Selected Register is 0x");
  Serial.println(address, HEX);

  Serial.println(F("Enter bit position (0-7) to Clear"));
  data = read_int();
  
  Serial.print("Bit position ");
  Serial.print(data);
  data = 0x01 << data;
  LTC2874_write_bit_clr_update_all(address, data);         //! Update
  Serial.print(" has been Cleared");
  return;
}

//************************************************************************************
//! Print the title block
//************************************************************************************
void print_title()
{
  Serial.println("*****************************************************************");
  Serial.println("* DC1880A Demonstration Program                                 *");
  Serial.println("*                                                               *");
  Serial.println("* This program demonstrates communication with the LTC2874      *");
  Serial.println("* Quad IO-Link Master Hot Swap Controller and PHY               *");
  Serial.println("*                                                               *");
  Serial.println("*                                                               *");
  Serial.println("*                                                               *");
  Serial.println("* Set the baud rate to 115200 select the newline terminator.    *");
  Serial.println("*****************************************************************");
}

//************************************************************************************
//! Print main menu and prompt user for an input command
//************************************************************************************
void print_prompt() 
{
  Serial.println("\nLTC2874 Demo Menu:");

  Serial.println("  1-CQ Output Enable/Disable");
  Serial.println("  2-L+ Output Enable/Disable");
  Serial.println("  3-Generate Wake-Up Request (WURQ)");
  Serial.println("  4-24V IO-Link Mode");
  Serial.println("  5-SIO Mode");
  Serial.println("  6-Select ILLM Sinking Current");
  Serial.println("  7-Clear Event Registers");
  Serial.println("  8-Update All");
  Serial.println("  9-Reset");
  Serial.println(" 10-Read Register");
  Serial.println(" 11-Write Register");
  Serial.println(" 12-Read Bit");
  Serial.println(" 13-Set Bit");
  Serial.println(" 14-Clear Bit");

  Serial.println();

  Serial.print("Enter a command: ");
}

//************************************************************************************
//! Test register number against valid range for Write
//************************************************************************************
uint8_t reg_test()
{
  uint8_t address;

  Serial.println(F("Select Register to write to; use Hex 0xn format."));
  Serial.println(F("NOTE: 0x0,0x6 and 0x7 are read only."));
  Serial.println();
  address = read_int();

  if ((address > 0xF ) || (address < 0x0))        //If user enters an invalid option
  {
    Serial.println("Error: Invalid register");
    return(0);
  }
  else if (address == 0)
  {
    Serial.println("Error: Register 0x0 is read only");
    return(0);
  }
  else if (address == 5)
  {
    Serial.println("Error: Only lower nibble of 0x5 is writable");
  }
  else if (address == 6)
  {
    Serial.println("Error: Register 0x6 is read only");
    return(0);
  }
  else if (address == 7) 
  {
    Serial.println("Error: Register 0x7 is read only");
    return(0);
  }

 return(address); 
}

//************************************************************************************
//! Print warning prompt
//************************************************************************************
void print_warning_prompt()
{
 Serial.println(F("No demo board connected."));
 Serial.println(F("However, the Linduino will attempt to proceed..."));
}

Download LTC2874 Linduino Header File

/*!
LTC2874: Quad IO-Link Master Hot Swap Power Controller and PHY


@verbatim

The LTC2874 provides a rugged, 4-port IO-Link power and communications 
interface to remote devices connected by cables up to 20m in length.

Output supply voltage and inrush current are ramped up in a controlled  
manner  using  external N-channel MOSFETs, providing improved robustness 
compared to fully integrated solutions.

Wake-up pulse generation, line noise suppression, connection sensing and 
automatic restart after fault conditions are supported, along with 
signalling at rates up to 4.8kb/s, 38.4kb/s, and 230.4kb/s.

Configuration and fault reporting are exchanged using a SPI-compatible 
4-wire interface that operates at clock rates up to 20MHz.

 SPI DATA FORMAT (MSB First):

 Byte #1                  Byte #2
 C2 C1 C0 A3 A2 A1 A0 X   D7 D6 D5 D4 D3 D2 D1 D0

 Cx   : Command     (0-Read Reg, 1-Write (no update), 2-Update all Reg, 
                     3-Write one Reg and Update,      7-Reset) 
 Ax   : REG Address (0-Reg0, 1-Reg1, 2-Reg2, ..., E-RegE)
 Dx   : REG Data
 X    : Don't care

@endverbatim

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

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

REVISION HISTORY
$Revision: 0.1 $
$Date: 2013-12-18 $

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.

IO-Link is a registered trademark of PROFIBUS User Organization (PNO).
*/

/*! @file
    @ingroup LTC2874
*/

#ifndef LTC2874_H
#define LTC2874_H

// Define the CS pin
#ifndef LTC2874_CS
#define LTC2874_CS QUIKEVAL_CS
#endif

/*!
OR'd together with the register address to form the command byte
| LTC2874 Command String   | Value |
| :------------------------| :---: |
| LTC2874_READ             | 0x00  |
| LTC2874_WRITE_NO_UPDATE  | 0x20  |
| LTC2874_UPDATE_ALL       | 0x40  |
| LTC2874_WRITE_UPDATE_ALL | 0x60  |
| LTC2874_RESET            | 0xE0  |
*/
/*! @name Command Codes
@{ */

// Command Codes
#define   LTC2874_READ               0x00  //! READ REGISTER
#define   LTC2874_WRITE_NO_UPDATE    0x20  //! WRITE REGISTER (NO UPDATE)
#define   LTC2874_UPDATE_ALL         0x40  //! UPDATE ALL REGISTERS
#define   LTC2874_WRITE_UPDATE_ALL   0x60  //! WRITE ONE REGISTER AND UPDATE
#define   LTC2874_RESET              0xE0  //! RESET
//! @}


/*!
| Register             | Address |
| :--------------------| :-----: |
| LTC2874_IRQREG_REG0  | 0x00    |
| LTC2874_IRQMASK_REG1 | 0x01    |
| LTC2874_EVENT1_REG2  | 0x02    |
| LTC2874_EVENT2_REG3  | 0x03    |
| LTC2874_EVENT3_REG4  | 0x04    |
| LTC2874_EVENT4_REG5  | 0x05    |
| LTC2874_STATUS1_REG6 | 0x06    |
| LTC2874_STATUS2_REG7 | 0x07    |
| LTC2874_MODE1_REG8   | 0x08    |
| LTC2874_MODE2_REG9   | 0x09    |
| LTC2874_NSF_REGA     | 0x0A    |
| LTC2874_ILLM_REGB    | 0x0B    |
| LTC2874_TMRCTRL_REGC | 0x0C    |
| LTC2874_CTRL1_REGD   | 0x0D    |
| LTC2874_CTRL2_REGE   | 0x0E    |
*/
/*! @name Register Addresses
@{ */

// Register Addresses
#define   LTC2874_IRQREG_REG0    0x00
#define   LTC2874_IRQMASK_REG1   0x01
#define   LTC2874_EVENT1_REG2    0x02
#define   LTC2874_EVENT2_REG3    0x03
#define   LTC2874_EVENT3_REG4    0x04
#define   LTC2874_EVENT4_REG5    0x05
#define   LTC2874_STATUS1_REG6   0x06
#define   LTC2874_STATUS2_REG7   0x07
#define   LTC2874_MODE1_REG8     0x08
#define   LTC2874_MODE2_REG9     0x09
#define   LTC2874_NSF_REGA       0x0A
#define   LTC2874_ILLM_REGB      0x0B
#define   LTC2874_TMRCTRL_REGC   0x0C
#define   LTC2874_CTRL1_REGD     0x0D
#define   LTC2874_CTRL2_REGE     0x0E
//! @}

/*! @name Register Bit and Mask Definitions
@{ */

// register bit definitions / masks
#define    LTC2874_OT             (0x1<<7)      // REGISTER IRQREG
#define    LTC2874_SUPPLY         (0x1<<6)      // REGISTER IRQREG
#define    LTC2874_WU             (0x1<<5)      // REGISTER IRQREG
#define    LTC2874_TOC_LP         (0x1<<4)      // REGISTER IRQREG
#define    LTC2874_PWRCHNG        (0x1<<3)      // REGISTER IRQREG
#define    LTC2874_TOC_CQ         (0x1<<2)      // REGISTER IRQREG
#define    LTC2874_CSENSE         (0x1<<1)      // REGISTER IRQREG

#define    LTC2874_OT_MASK        (0x1<<7)      // REGISTER IRQMASK
#define    LTC2874_SUPPLY_MASK    (0x1<<6)      // REGISTER IRQMASK
#define    LTC2874_WU_MASK        (0x1<<5)      // REGISTER IRQMASK
#define    LTC2874_TOC_LP_MASK    (0x1<<4)      // REGISTER IRQMASK
#define    LTC2874_PWRCHNG_MASK   (0x1<<3)      // REGISTER IRQMASK
#define    LTC2874_TOC_CQ_MASK    (0x1<<2)      // REGISTER IRQMASK
#define    LTC2874_CSENSE_MASK    (0x1<<1)      // REGISTER IRQMASK

#define    LTC2874_OT_SD          (0x1<<7)      // REGISTER EVENT1
#define    LTC2874_OT_WARN        (0x1<<6)      // REGISTER EVENT1
#define    LTC2874_UVLO_VL        (0x1<<4)      // REGISTER EVENT1
#define    LTC2874_UVLO_VDD       (0x1<<3)      // REGISTER EVENT1
#define    LTC2874_UV_VDD         (0x1<<2)      // REGISTER EVENT1
#define    LTC2874_OV_VDD         (0x1<<1)      // REGISTER EVENT1

#define    LTC2874_WU4            (0x1<<7)      // REGISTER EVENT2
#define    LTC2874_WU3            (0x1<<6)      // REGISTER EVENT2
#define    LTC2874_WU2            (0x1<<5)      // REGISTER EVENT2
#define    LTC2874_WU1            (0x1<<4)      // REGISTER EVENT2
#define    LTC2874_TOC_LP4        (0x1<<3)      // REGISTER EVENT2
#define    LTC2874_TOC_LP3        (0x1<<2)      // REGISTER EVENT2
#define    LTC2874_TOC_LP2        (0x1<<1)      // REGISTER EVENT2
#define    LTC2874_TOC_LP1         0x1          // REGISTER EVENT2
 
#define    LTC2874_PWRCHNG4       (0x1<<7)      // REGISTER EVENT3
#define    LTC2874_PWRCHNG3       (0x1<<6)      // REGISTER EVENT3
#define    LTC2874_PWRCHNG2       (0x1<<5)      // REGISTER EVENT3
#define    LTC2874_PWRCHNG1       (0x1<<4)      // REGISTER EVENT3
#define    LTC2874_TOC_CQ4        (0x1<<3)      // REGISTER EVENT3
#define    LTC2874_TOC_CQ3        (0x1<<2)      // REGISTER EVENT3
#define    LTC2874_TOC_CQ2        (0x1<<1)      // REGISTER EVENT3
#define    LTC2874_TOC_CQ1         0x1          // REGISTER EVENT3

#define    LTC2874_CQ_SNS4        (0x1<<7)      // REGISTER EVENT4
#define    LTC2874_CQ_SNS3        (0x1<<6)      // REGISTER EVENT4
#define    LTC2874_CQ_SNS2        (0x1<<5)      // REGISTER EVENT4
#define    LTC2874_CQ_SNS1        (0x1<<4)      // REGISTER EVENT4
#define    LTC2874_CSENSE4        (0x1<<3)      // REGISTER EVENT4
#define    LTC2874_CSENSE3        (0x1<<2)      // REGISTER EVENT4
#define    LTC2874_CSENSE2        (0x1<<1)      // REGISTER EVENT4
#define    LTC2874_CSENSE1         0x1          // REGISTER EVENT4

#define    LTC2874_OT_STAT        (0x1<<7)      // REGISTER STATUS1
#define    LTC2874_WU_COOL_STAT   (0x1<<6)      // REGISTER STATUS1
#define    LTC2874_UVLO_VDD_STAT  (0x1<<5)      // REGISTER STATUS1
#define    LTC2874_OV_VDD_STAT    (0x1<<4)      // REGISTER STATUS1
#define    LTC2874_OC_LP4_STAT    (0x1<<3)      // REGISTER STATUS1
#define    LTC2874_OC_LP3_STAT    (0x1<<2)      // REGISTER STATUS1
#define    LTC2874_OC_LP2_STAT    (0x1<<1)      // REGISTER STATUS1
#define    LTC2874_OC_LP1_STAT     0x1          // REGISTER STATUS1

#define    LTC2874_PWRGD4         (0x1<<7)      // REGISTER STATUS2
#define    LTC2874_PWRGD3         (0x1<<6)      // REGISTER STATUS2
#define    LTC2874_PWRGD2         (0x1<<5)      // REGISTER STATUS2
#define    LTC2874_PWRGD1         (0x1<<4)      // REGISTER STATUS2
#define    LTC2874_OC_CQ4         (0x1<<3)      // REGISTER STATUS2
#define    LTC2874_OC_CQ3         (0x1<<2)      // REGISTER STATUS2
#define    LTC2874_OC_CQ2         (0x1<<1)      // REGISTER STATUS2
#define    LTC2874_OC_OQ1          0x1          // REGISTER STATUS2

#define    LTC2874_24VMODE        (0x1<<7)      // REGISTER MODE1
#define    LTC2874_CSENSE_MODE    (0x1<<6)      // REGISTER MODE1
// multibit definition
#define    LTC2874_2XPTC_pos         4          // REGISTER MODE1
#define    LTC2874_2XPTC_msk      (0x3<<4)      // REGISTER MODE1
#define    LTC2874_2XPTC(value)   (LTC2874_2XPTC_msk & ((value) << LTC2874_2XPTC_pos))

#define    LTC2874_FLDBK_MODE     (0x1<<3)      // REGISTER MODE1
#define    LTC2874_RETRY_OV       (0x1<<2)      // REGISTER MODE1
#define    LTC2874_RETRY_LP       (0x1<<1)      // REGISTER MODE1
#define    LTC2874_RETRY_CQ        0x1          // REGISTER MODE1

#define    LTC2874_SLEW4          (0x1<<7)      // REGISTER MODE2
#define    LTC2874_SLEW3          (0x1<<6)      // REGISTER MODE2
#define    LTC2874_SLEW2          (0x1<<5)      // REGISTER MODE2
#define    LTC2874_SLEW1          (0x1<<4)      // REGISTER MODE2
// multibit definition
#define    LTC2874_OV_TH_pos         2          // REGISTER MODE2
#define    LTC2874_OV_TH_msk      (0x3<<2)      // REGISTER MODE2
#define    LTC2874_OV_TH(value)   (LTC2874_OV_TH_msk & ((value) << LTC2874_OV_TH_pos))

#define    LTC2874_OV_ALLOW       (0x1<<1)      // REGISTER MODE2
#define    LTC2874_CQ_SNS_MODE     0x1          // REGISTER MODE2

// multibit definitions
#define    LTC2874_NSF4_pos          6          // REGISTER NSF
#define    LTC2874_NSF4_msk       (0x3<<6)      // REGISTER NSF
#define    LTC2874_NSF4(value)    (LTC2874_NSF4_msk & ((value) << LTC2874_NSF4_pos))
#define    LTC2874_NSF3_pos          4          // REGISTER NSF
#define    LTC2874_NSF3_msk       (0x3<<4)      // REGISTER NSF
#define    LTC2874_NSF3(value)     LTC2874_NSF3_msk & ((value) << LTC2874_NSF3_pos))
#define    LTC2874_NSF2_pos          2          // REGISTER NSF
#define    LTC2874_NSF2_msk       (0x3<<2)      // REGISTER NSF
#define    LTC2874_NSF2(value)    (LTC2874_NSF2_msk & ((value) << LTC2874_NSF2_pos))
#define    LTC2874_NSF1_pos          0          // REGISTER NSF
#define    LTC2874_NSF1_msk         0x3         // REGISTER NSF
#define    LTC2874_NSF1(value)     (LTC2874_NSF1_msk & ((value) << LTC2874_NSF1_pos))

#define    LTC2874_ILLM4_pos         6          // REGISTER ILLM
#define    LTC2874_ILLM4_msk       (0x3<<6)     // REGISTER ILLM
#define    LTC2874_ILLM4(value)    (LTC2874_ILLM4_msk & ((value) << LTC2874_ILLM4_pos))
#define    LTC2874_ILLM3_pos        4           // REGISTER ILLM
#define    LTC2874_ILLM3_msk       (0x3<<4)     // REGISTER ILLM
#define    LTC2874_ILLM3(value)    (LTC2874_ILLM3_msk & ((value) << LTC2874_ILLM3_pos))
#define    LTC2874_ILLM2_pos        2           // REGISTER ILLM
#define    LTC2874_ILLM2_msk       (0x3<<2)     // REGISTER ILLM
#define    LTC2874_ILLM2(value)    (LTC2874_ILLM2_msk & ((value) << LTC2874_ILLM2_pos))
#define    LTC2874_ILLM1_pos        0           // REGISTER ILLM
#define    LTC2874_ILLM1_msk        0x3         // REGISTER ILLM
#define    LTC2874_ILLM1(value)    (LTC2874_ILLM1_msk & ((value) << LTC2874_ILLM1_pos))

#define    LTC2874_LPTC_pos         4           // REGISTER TMRCTRL
#define    LTC2874_LPTC_msk        (0xF<<4)     // REGISTER TMRCTRL
#define    LTC2874_LPTC(value)     (LTC2874_LPTC_msk & ((value) << LTC2874_LPTC_pos))

#define    LTC2874_RETRYTC_pos     0            // REGISTER TMRCTRL
#define    LTC2874_RETRYTC_msk     0x07         // REGISTER TMRCTRL
#define    LTC2874_RETRYTC(value) (LTC2874_RETRYTC_msk & (value))

#define    LTC2874_WKUP4          (0x1<<7)      // REGISTER CTRL1
#define    LTC2874_WKUP3          (0x1<<6)      // REGISTER CTRL1
#define    LTC2874_WKUP2          (0x1<<5)      // REGISTER CTRL1
#define    LTC2874_WKUP1          (0x1<<4)      // REGISTER CTRL1
#define    LTC2874_DRVEN4         (0x1<<3)      // REGISTER CTRL1
#define    LTC2874_DRVEN3         (0x1<<2)      // REGISTER CTRL1
#define    LTC2874_DRVEN2         (0x1<<1)      // REGISTER CTRL1
#define    LTC2874_DRVEN1          0x1          // REGISTER CTRL1

#define    LTC2874_ENLP4          (0x1<<7)      // REGISTER CTRL2
#define    LTC2874_ENLP3          (0x1<<6)      // REGISTER CTRL2
#define    LTC2874_ENLP2          (0x1<<5)      // REGISTER CTRL2
#define    LTC2874_ENLP1          (0x1<<4)      // REGISTER CTRL2
#define    LTC2874_SIO_MODE4      (0x1<<3)      // REGISTER CTRL2
#define    LTC2874_SIO_MODE3      (0x1<<2)      // REGISTER CTRL2
#define    LTC2874_SIO_MODE2      (0x1<<1)      // REGISTER CTRL2
#define    LTC2874_SIO_MODE1       0x1          // REGISTER CTRL2

#define    LTC2874_CQ1     0x01
#define    LTC2874_CQ2     0x02
#define    LTC2874_CQ3     0x04
#define    LTC2874_CQ4     0x08
#define    LTC2874_CQ_ALL  0x0F

#define    LTC2874_LP1     0x10
#define    LTC2874_LP2     0x20
#define    LTC2874_LP3     0x40
#define    LTC2874_LP4     0x80
#define    LTC2874_LP_ALL  0xF0

//! @}

//************************************************************************************
//! Enables or Disables CQ output for specified port, then Updates.
//! @return void
//************************************************************************************
void LTC2874_cq_output(uint8_t port,             //!< Port number (1-4 or 5=ALL)
                        uint8_t value             //!< Enable (=1) or Disable (=0)
                      );

//************************************************************************************
//! Enables or Disables L+ output for specified port, then Updates.
//! @return void
//************************************************************************************
void LTC2874_lplus_output(uint8_t port,                  //!< Port number (1-4 or 5=ALL)
                           uint8_t value                  //!< Enable (=1) or Disable (=0)
                         );

//************************************************************************************
//! Sets SIO_MODE bit (and also Clears SLEW bit) for specified port, then Updates.
//! @return void
//************************************************************************************
void LTC2874_sio_mode(uint8_t port               //!< Port number (1-4 or 5=ALL)
                     );

//************************************************************************************
//! Changes value of the 24VMODE bit, then Updates.
//! @return void
//************************************************************************************
void LTC2874_24v_mode(uint8_t value              //!< 24VMODE setting (0 or 1)
                     );

//************************************************************************************
//! Changes NSF (Noise Suppression Filter) setting for specified port
//! without Updating.
//! value definitions: 0x0=disabled, 0x1=20.3us, 0x2=2.8us, 0x3=0.6us (default)
//! @return void
//************************************************************************************
void LTC2874_write_NSF_value(uint8_t port,          //!< Port number (1-4)
                             uint8_t value          //!< NSF setting (0x0-0x3)
                            );

//************************************************************************************
//! Changes ILLM (Sinking current) setting for specified port without Updating.
//! value definitions: 0x0=500kohm, 0x1=2.5mA, 0x2=3.7mA, 0x3=6.2mA (default) 
//! @return void
//************************************************************************************
void LTC2874_write_ILLM_value(uint8_t port,         //!< Port number (1-4 or 5=ALL)
                              uint8_t value         //!< ILLM setting (0x0-0x3)
                             );

//************************************************************************************
//! Change L+ Overcurrent Timer Control (LPTC) setting without Updating.
//! value definitions: 0x0=17us, 0x1=30us, 0x2=60us, 0x3=120us, 0x4=0.25ms, 0x5=0.5ms, 
//!                    0x6=1ms, 0x7=2ms, 0x8=3.9ms, 0x9=7.8ms, 0xA=16ms, 0xB=30ms, 
//!                    0xC=0.60ms, 0xD=0.13s, 0xE=0.25s, 0xF=0.25s
//! @return void
//************************************************************************************
void LTC2874_write_LPTC_value(uint8_t value     //!< LPTC setting (0x0-0xF)
                             );

//************************************************************************************
//! Changes Auto-Retry Timer Control (RETRYTC) setting without Updating.
//! value definitions: 0x0=0.12s, 0x1=0.24s, 0x2=0.49s, 0x3=0.98s, 0x4=2.0s,
//!                    0x5=3.9s, 0x6=7.9s, 0x7=15.7s
//! @return void
//************************************************************************************
void LTC2874_write_RETRYTC_value(uint8_t value    //!< RETRYTC setting (0x0-0x7)
                                );

//************************************************************************************
//! Changes 2X Current Pulse Timer Control (2XPTC) setting without Updating.
//! value definitions: 0x0=60ms (default), 0x1=disabled, 0x2=30ms, 0x3=120ms
//! @return void
//************************************************************************************
void LTC2874_write_2XPTC_value(uint8_t value      //!< 2XPTC setting (0x0-0x3)
                              );

//************************************************************************************
//! Changes VDD Overvoltage Threshold (OV_TH) setting without Updating.
//! value definitions: 0x0=18V, 0x1=32V (default), 0x2=34V, 0x3=36V
//! @return void
//************************************************************************************
void LTC2874_write_OV_TH_value(uint8_t value      //!< OV_TH setting (0x0-0x3)
                              ); 

//************************************************************************************
//! Sends WURQ (Wake-up Request) on specified port.
//! @return void
//************************************************************************************
void LTC2874_wakeup_request(uint8_t port          //!< Port number (1-4)
                           );

//************************************************************************************
//! Updates all registers.
//! @return void
//************************************************************************************
void LTC2874_update_all(void                      //!< void
                       ); 

//************************************************************************************
//! Writes byte of data to a register, then Updates.
//! @return void
//************************************************************************************
void LTC2874_write_register_update_all(uint8_t LTC2874_register,  //!< Register address (0x0-0xE) 
                                       uint8_t value              //!< Data to be written into register
                                      );

//************************************************************************************
//! Changes value of a register bit, then Updates.
//! @return void
//************************************************************************************
void LTC2874_write_bit_value_update_all(uint8_t LTC2874_register, //!< Register address (0x0-0xE)
                                        uint8_t LTC2874_bit,      //!< Mask of bit to be written (e.g. 0x40)
                                        uint8_t value             //!< Bit value to be written (0 or 1)
                                       );

//************************************************************************************
//! Sets a register bit, then Updates.
//! @return void
//************************************************************************************
void LTC2874_write_bit_set_update_all(uint8_t LTC2874_register,   //!< Register address (0x0-0xE)
                                      uint8_t LTC2874_bit         //!< Mask of bit to be set (e.g. 0x40)
                                     );

//************************************************************************************
//! Clears a register bit, then Updates.
//! @return void
//************************************************************************************
void LTC2874_write_bit_clr_update_all(uint8_t LTC2874_register,   //!< Register address (0x0-0xE)
                                      uint8_t LTC2874_bit         //!< Mask of bit to be cleared (e.g. 0x40) 
                                     );

//************************************************************************************
//! Resets LTC2874, returning default values to registers.
//! @return void
//************************************************************************************
void LTC2874_reset(void //!< void
                  );

//************************************************************************************
//! Reads data byte from specified register.
//! @return value of byte read
//************************************************************************************
uint8_t LTC2874_read_reg(uint8_t LTC2874_register      //!< Register address (0x0-0xE)
                        );

//************************************************************************************
//! Reads a data BIT from specified register.
//! @return value of bit read
//************************************************************************************
uint8_t LTC2874_read_bit(uint8_t LTC2874_register,     //!< Register address (0x0-0xE)
                         uint8_t LTC2874_bit           //!< Mask of bit to be read (e.g. 0x40) 
                        );

//************************************************************************************
//! Writes byte of data to a register without Updating.
//! @return void
//************************************************************************************
void LTC2874_write_register(uint8_t LTC2874_register,  //!< Register address (0x0-0xE)
                            uint8_t value              //!< Data to be written into register
                           );

//************************************************************************************
//! Sets a register bit without Updating.
//! @return void
//************************************************************************************
void LTC2874_write_bit_set(uint8_t LTC2874_register,   //!< Register address (0x0-0xE)
                           uint8_t LTC2874_bit         //!< Mask of bit to be set (e.g. 0x40)
                          );
                           
//************************************************************************************
//! Clears a register bit without Updating.
//! @return void
//************************************************************************************
void LTC2874_write_bit_clr(uint8_t LTC2874_register,   //!< Register address (0x0-0xE)
                           uint8_t LTC2874_bit         //!< Mask of bit to be set (e.g. 0x40)
                          );

//************************************************************************************
//! Changes value of a register bit without Updating.
//! @return void
//************************************************************************************
void LTC2874_write_bit_value(uint8_t LTC2874_register, //!< Register address (0x0-0xE)
                             uint8_t LTC2874_bit,      //!< Mask of bit to be written (e.g. 0x40)
                             uint8_t value             //!< Bit value to be written (0 or 1)
                            );

#endif  // LTC2874_H

Download LTC2874 Linduino.CPP

/*!
LTC2874: Quad IO-Link Master Hot Swap Power Controller and PHY

@verbatim

The LTC2874 provides a rugged, 4-port IO-Link power and communications 
interface to remote devices connected by cables up to 20m in length.

Output supply voltage and inrush current are ramped up in a controlled  
manner  using  external N-channel MOSFETs, providing improved robustness 
compared to fully integrated solutions.

Wake-up pulse generation, line noise suppression, connection sensing and 
automatic restart after fault conditions are supported, along with 
signalling at rates up to 4.8kb/s, 38.4kb/s, and 230.4kb/s.

Configuration and fault reporting are exchanged using a SPI-compatible 
4-wire interface that operates at clock rates up to 20MHz.

@endverbatim

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

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

REVISION HISTORY
$Revision: 0.1 $
$Date: 2013-12-18 $

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.

IO-Link is a registered trademark of PROFIBUS User Organization (PNO).
*/

//! @defgroup LTC2874 LTC2874: Quad IO-Link Master Hot Swap Power Controller and PHY

/*! @file
    @ingroup LTC2874
    Library for LTC2874: Quad IO-Link Master Hot Swap Power Controller and PHY
*/

#include <stdint.h>
#include <math.h>
#include <Arduino.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include "LTC2874.h"



//************************************************************************************
//  Enables or Disables CQ output for specified port, then Updates.
//  parameters: port (1-4, or 5=ALL), value (0=Disable, 1=Enable)
//  returns: nothing
//************************************************************************************
void LTC2874_cq_output(uint8_t port, uint8_t value)
{
  uint8_t data_byte, command_byte;
  
  command_byte = LTC2874_READ | (LTC2874_CTRL1_REGD << 1);
    
  output_low(LTC2874_CS);               //! 1) Pull CS low
  spi_write(command_byte);              //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);           //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);          
  
  if (port == 5)
  {
    port = 0xF;
  }
  else
    {
      port = 0x01 << (port - 1);      // make mask
    }

  if (value)
  {
    data_byte |= port;                // bitwise OR
  }
   else
   {
     data_byte &= ~port;
   }
  
  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_CTRL1_REGD << 1);

  output_low(LTC2874_CS);              //! 1) Pull CS low to start transaction
  spi_write(command_byte);             //! 2) Write the command and address
  spi_write(data_byte);                //! 3) Write the data
  output_high(LTC2874_CS);             //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Enables or Disables L+ output for specified port, then Updates.
//  parameters: port (1-4, or 5=ALL), value (0=Disable, 1=Enable)
//  returns: nothing
//************************************************************************************
void LTC2874_lplus_output(uint8_t port, uint8_t value)
{
  uint8_t data_byte, command_byte;
  
  command_byte = LTC2874_READ | (LTC2874_CTRL2_REGE << 1);

  output_low(LTC2874_CS);            //! 1) Pull CS low
  spi_write(command_byte);           //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);        //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);          
  
  if (port == 5)
  {
    port = 0xF0;
  }
  else
    {
      port = 0x01 << (port + 3);         //make mask
    }

  if (value)
  {
    data_byte |= port;                   //bitwise OR
  }
   else
   {
     data_byte &= ~port;
   }
   
  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_CTRL2_REGE << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low to start transaction
  spi_write(command_byte);               //! 2) Write the command and address
  spi_write(data_byte);                  //! 3) Write the data
  output_high(LTC2874_CS);               //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Sets SIO_MODE bit (and also Clears SLEW bit) for specified port, then Updates.
//  parameter: port (1-4, or 5=ALL)
//  returns: nothing
//************************************************************************************
void LTC2874_sio_mode(uint8_t port)
{
  uint8_t data_byte_9, data_byte_E, command_byte_9, command_byte_E, position_9, position_E;

    if (port == 5)                       // If 5 set to 0x0F
    {
      position_E = 0x0f;
    }
    else
      {
        position_E = (0x01 << (port - 1));  // convert port number to position
      }

  position_9 = position_E << 4;          // move position for slew bits

  command_byte_9 = LTC2874_READ | (LTC2874_MODE2_REG9 << 1);
  command_byte_E = LTC2874_READ | (LTC2874_CTRL2_REGE << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low
  spi_write(command_byte_9);             //! 2) Write first byte and send command1 | address
  data_byte_9 = spi_read(0x00);          //! 3) Read last byte (while sending null data)
  spi_write(command_byte_E);             //! 4) Write first byte and send command2 | address
  data_byte_E = spi_read(0x00);          //! 5) Read last byte (while sending null data)
  output_high(LTC2874_CS);               //! 6) Pull CS high to finish transaction

  data_byte_9 &= ~position_9;            // SLEW=0
  data_byte_E |= position_E;             // SIO_MODE=1

  command_byte_9 = LTC2874_WRITE_NO_UPDATE | (LTC2874_MODE2_REG9 << 1);
  command_byte_E = LTC2874_WRITE_UPDATE_ALL | (LTC2874_CTRL2_REGE << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low to start transaction
  spi_write(command_byte_9);             //! 2) Write the command and address
  spi_write(data_byte_9);                //! 3) Write the data  
  spi_write(command_byte_E);             //! 4) Write the command and address
  spi_write(data_byte_E);                //! 5) Write the data
  output_high(LTC2874_CS);               //! 6) Pull CS high to finish transaction
}

//************************************************************************************
//  Changes value of the 24VMODE bit, then Updates.
//  parameter: value (0=Disable, 1=Enable)
//  returns: nothing
//************************************************************************************
void LTC2874_24v_mode(uint8_t value)
{
  uint8_t command_byte, data_byte;
  command_byte = LTC2874_READ | (LTC2874_MODE1_REG8 << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low
  spi_write(command_byte);               //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);            //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);               //! 4) Pull CS high to finish transaction  

  if (value)
  {
    data_byte |= LTC2874_24VMODE;        // set bit
  }
    else
    {
      data_byte &= ~LTC2874_24VMODE;     // clr bit
    }

  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_MODE1_REG8 << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low to start transaction
  spi_write(command_byte);               //! 2) Write the command and address
  spi_write(data_byte);                  //! 3) Write the data
  output_high(LTC2874_CS);               //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes NSF (Noise Suppression Filter) setting for specified port.
//  parameters: port#, value
//    port#: [1,2,3, or 4]
//    value: 0x0=disabled, 0x1=20.3us, 0x2=2.8us, 0x3=0.6us (default)
//  Higher bits are ignored. No update. Returns: nothing.
//************************************************************************************
void LTC2874_write_NSF_value(uint8_t port, uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  command_byte = LTC2874_READ | (LTC2874_NSF_REGA << 1);    // Create command and address byte

  output_low(LTC2874_CS);               //! 1) Pull CS low
  spi_write(command_byte);              //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);           //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction  

  position = ((port - 1) << 1);         // convert port number to position,Equivalent to multiply by 2
  data_byte &= ~(0x3<<position);        // clear NSF bits with inverse mask
  data_byte |= ((value) << position);   // bitwise OR value into NSF port position

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_NSF_REGA << 1);

  output_low(LTC2874_CS);               //! 1) Pull CS low to start transaction
  spi_write(command_byte);              //! 2) Write the command and address
  spi_write(data_byte);                 //! 3) Write the data
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes ILLM (Sinking current) setting for specified port.
//  parameters: port#, value
//    port#: (1-4, or 5=ALL)
//    value: 0x0=500kohm, 0x1=2.5mA, 0x2=3.7mA, 0x3=6.2mA (default) 
//  Higher bits are ignored. No update. Returns: nothing. 
//************************************************************************************
void LTC2874_write_ILLM_value(uint8_t port, uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  // Create command and address byte
  command_byte = LTC2874_READ | (LTC2874_ILLM_REGB << 1);

  output_low(LTC2874_CS);                    //! 1) Pull CS low
  spi_write(command_byte);                   //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);                //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                   //! 4) Pull CS high to finish transaction  
  
    if (port == 5)                           // If 5 load each port same value
    {
      data_byte = value + (value << 2) + (value << 4) + (value << 6);
    }
    else
      {
        position = ((port - 1) << 1);          // convert port number to position
        data_byte &= ~(0x3<<position);         // clear ILLM bits with inverse mask
        data_byte |= ((value) << position);    // bitwise OR value into ILLM port position
      }

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_ILLM_REGB << 1);

  output_low(LTC2874_CS);                    //! 1) Pull CS low to start transaction
  spi_write(command_byte);                   //! 2) Write the command and address
  spi_write(data_byte);                      //! 3) Write the data
  output_high(LTC2874_CS);                   //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Change L+ Overcurrent Timer Control (LPTC) setting.
//  parameter: value (4 bits, 0x0-0xF)
//    0x0=17us, 0x1=30us, 0x2=60us, 0x3=120us, 0x4=0.25ms, 0x5=0.5ms, 0x6=1ms, 0x7=2ms
//    0x8=3.9ms, 0x9=7.8ms, 0xA=16ms, 0xB=30ms, 0xC=0.60ms, 0xD=0.13s, 0xE/0xF=0.25s
//  Higher bits are ignored. No update. Returns: nothing.
//************************************************************************************
void LTC2874_write_LPTC_value(uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  // Create command and address byte
  command_byte = LTC2874_READ | (LTC2874_TMRCTRL_REGC << 1);

  output_low(LTC2874_CS);                  //! 1) Pull CS low
  spi_write(command_byte);                 //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);              //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                 //! 4) Pull CS high to finish transaction  

  data_byte &= ~(LTC2874_LPTC_msk);        // clear LPTC bits with inverse mask
  data_byte |= (LTC2874_LPTC(value));      // bitwise OR value into LPTC bits

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_TMRCTRL_REGC << 1);

  output_low(LTC2874_CS);                  //! 1) Pull CS low to start transaction
  spi_write(command_byte);                 //! 2) Write the command and address
  spi_write(data_byte);                    //! 3) Write the data
  output_high(LTC2874_CS);                 //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes Auto-Retry Timer Control (RETRYTC) setting.
//  parameter: value (0x0=0.12s, 0x1=0.24s, 0x2=0.49s, 0x3=0.98s, 0x4=2.0s, 0x5=3.9s, 0x6=7.9s, 0x7=15.7s)
//  Higher bits are ignored. No update. Returns: nothing.
//************************************************************************************
void LTC2874_write_RETRYTC_value(uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  // Create command and address byte
  command_byte = LTC2874_READ | (LTC2874_TMRCTRL_REGC << 1);

  output_low(LTC2874_CS);                   //! 1) Pull CS low
  spi_write(command_byte);                  //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);               //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                  //! 4) Pull CS high to finish transaction  

  data_byte &= ~(LTC2874_RETRYTC_msk);      // clear RETRYTC bits with inverse mask
  data_byte |= (LTC2874_RETRYTC(value));    // bitwise OR value into RETRYTC bits

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_TMRCTRL_REGC << 1);

  output_low(LTC2874_CS);                   //! 1) Pull CS low to start transaction
  spi_write(command_byte);                  //! 2) Write the command and address
  spi_write(data_byte);                     //! 3) Write the data
  output_high(LTC2874_CS);                  //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes 2X Current Pulse Timer Control (2XPTC) setting.
//  parameter: value (0x0=60ms (default), 0x1=disabled, 0x2=30ms, 0x3=120ms)
//  Higher bits are ignored. No update. Returns: nothing.
//************************************************************************************
void LTC2874_write_2XPTC_value(uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  // Create command and address byte
  command_byte = LTC2874_READ | (LTC2874_MODE1_REG8 << 1);

  output_low(LTC2874_CS);                   //! 1) Pull CS low
  spi_write(command_byte);                  //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);               //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                  //! 4) Pull CS high to finish transaction  

  data_byte &= ~(LTC2874_2XPTC_msk);        // clear 2XPTC bits with inverse mask
  data_byte |= (LTC2874_2XPTC(value));      // bitwise OR value into 2XPTC bits

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_MODE1_REG8 << 1);

  output_low(LTC2874_CS);                   //! 1) Pull CS low to start transaction
  spi_write(command_byte);                  //! 2) Write the command and address
  spi_write(data_byte);                     //! 3) Write the data
  output_high(LTC2874_CS);                  //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes VDD Overvoltage Threshold (OV_TH) setting.
//  parameter: value (0x0=18V, 0x1=32V (default), 0x2=34V, 0x3=36V)
//  Higher bits are ignored. No update. Returns: nothing.
//************************************************************************************
void LTC2874_write_OV_TH_value(uint8_t value)
{
  uint8_t command_byte , data_byte, position;
  // Create command and address byte
  command_byte = LTC2874_READ | (LTC2874_MODE2_REG9 << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low
  spi_write(command_byte);                //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);             //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction  

  data_byte &= ~(LTC2874_OV_TH_msk);      // clear OV_TH bits with inverse mask
  data_byte |= (LTC2874_OV_TH(value));    // bitwise OR value into OV_TH bits

  command_byte = LTC2874_WRITE_NO_UPDATE | (LTC2874_MODE2_REG9 << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low to start transaction
  spi_write(command_byte);                //! 2) Write the command and address
  spi_write(data_byte);                   //! 3) Write the data
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction
}


//************************************************************************************
// Sends WURQ (Wake-up Request) on specified port.
// parameter: port# [1,2,3, or 4; only one at a time]
// returns: nothing.
//************************************************************************************
void LTC2874_wakeup_request(uint8_t port)
{
  uint8_t data_byte, command_byte;
  port = 0x01 << (port + 3);         //move to MS of byte, make mask

  command_byte = LTC2874_READ | (LTC2874_CTRL1_REGD << 1);

  output_low(LTC2874_CS);            //! 1) Pull CS low
  spi_write(command_byte);           //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);        //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);          

  data_byte |= port;                 // bitwise OR

  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_CTRL1_REGD << 1);

  output_low(LTC2874_CS);              //! 1) Pull CS low to start transaction
  spi_write(command_byte);             //! 2) Write the command and address
  spi_write(data_byte);                //! 3) Write the data
  output_high(LTC2874_CS);             //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Updates all registers.
//  parameters: none
//  returns: nothing
//************************************************************************************
void LTC2874_update_all(void)
{
  uint8_t command_byte;
  command_byte = LTC2874_UPDATE_ALL;

  output_low(LTC2874_CS);                 //! 1) Pull CS low to start transaction
  spi_write(command_byte);                //! 2) Write the command and address
  spi_write(0x00);                        //! 3) Write null data
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Writes byte of data to a register, then Updates.
//  parameters: register, data
//  returns: nothing
//************************************************************************************
void LTC2874_write_register_update_all(uint8_t LTC2874_register, uint8_t LTC2874_data)
{
  uint8_t command_byte;
  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low to start transaction
  spi_write(command_byte);                //! 2) Write the command and address
  spi_write(LTC2874_data);                //! 3) Write the data
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction
}

//************************************************************************************
//  Changes value of a register bit, then Updates.
//    NOTE: multi-bit handled by specific functions such as LTC2874_2XPTC_value()
//  parameters: register, bit, value
//    port#: [1,2,3, or 4]
//    value: 0 or 1
//  returns: nothing
//************************************************************************************
void LTC2874_write_bit_value_update_all(uint8_t LTC2874_register, uint8_t LTC2874_bit, uint8_t value)
{
  uint8_t command_byte , data_byte;
  command_byte = LTC2874_READ | (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low
  spi_write(command_byte);                //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);             //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction  

  if (value)
   {
     data_byte |= LTC2874_bit;            //bitwise or
   }
   else
    {
      data_byte &= ~LTC2874_bit;
    }

  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low to start transaction
  spi_write(command_byte);                //! 2) Write the command and address
  spi_write(data_byte);                   //! 3) Write the data
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction

}

//************************************************************************************
//  Sets a register bit, then Updates.
//  parameters: register, bit
//  returns: nothing
//************************************************************************************
void LTC2874_write_bit_set_update_all(uint8_t LTC2874_register, uint8_t LTC2874_bit)
{
  uint8_t command_byte , mask, data_byte;
  command_byte = LTC2874_READ | (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low
  spi_write(command_byte);                //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);             //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction  

  data_byte |= LTC2874_bit;               // compound bitwise OR

  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low to start transaction
  spi_write(command_byte);                //! 2) Write the command and address
  spi_write(data_byte);                   //! 3) Write the data
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Clears a register bit, then Updates.
//  parameters: register, bit
//  returns: nothing
//************************************************************************************
void LTC2874_write_bit_clr_update_all(uint8_t LTC2874_register, uint8_t LTC2874_bit)
{
  uint8_t command_byte , mask, data_byte;
  command_byte = LTC2874_READ | (LTC2874_register << 1);

  output_low(LTC2874_CS);            //! 1) Pull CS low
  spi_write(command_byte);           //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);        //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);           //! 4) Pull CS high to finish transaction  

  mask = ~LTC2874_bit;               // bitwise NOT
  data_byte &= mask;                 // clears the bit, leaves the rest unchanged

  command_byte = LTC2874_WRITE_UPDATE_ALL | (LTC2874_register << 1);

  output_low(LTC2874_CS);            //! 1) Pull CS low to start transaction
  spi_write(command_byte);           //! 2) Write the command and address
  spi_write(data_byte);              //! 3) Write the data
  output_high(LTC2874_CS);           //! 4) Pull CS high to finish transaction
}

//************************************************************************************
//  Resets LTC2874, returning default values to registers.
//  parameter: none
//  returns: nothing
//************************************************************************************
void LTC2874_reset(void)
{
  uint8_t command_byte;
  command_byte = LTC2874_RESET;

  output_low(LTC2874_CS);             //! 1) Pull CS low to start transaction
  spi_write(command_byte);            //! 2) Write the command and address
  spi_write(0x00);                    //! 3) Write null data
  output_high(LTC2874_CS);            //! 4) Pull CS high to finish transaction
}

//************************************************************************************
//  Reads data byte from specified register.
//  parameter: register address
//  returns: data byte
//************************************************************************************
uint8_t LTC2874_read_reg(uint8_t LTC2874_register)
{
  uint8_t command_byte, data_byte;
  //!  Build the reg command byte
  command_byte = LTC2874_READ |  (LTC2874_register << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low
  spi_write(command_byte);               //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);            //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);               //! 4) Pull CS high to finish transaction  

  return data_byte;
}


//************************************************************************************
//  Reads a data BIT from specified register.
//  parameters: register address, bit mask
//  returns: bit value.
//************************************************************************************
uint8_t LTC2874_read_bit(uint8_t LTC2874_register, uint8_t LTC2874_bit)
{
  uint8_t command_byte, data_byte;

  command_byte = LTC2874_READ |  (LTC2874_register << 1);

  output_low(LTC2874_CS);                 //! 1) Pull CS low
  spi_write(command_byte);                //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);             //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                //! 4) Pull CS high to finish transaction  

  data_byte &= LTC2874_bit;
  data_byte = data_byte != 0;             //! 5) If the bit is not zero set data_byte to 1

return data_byte;
}


//************************************************************************************
//  Writes byte of data to a register without Updating.
//  parameters: register, data
//  returns: nothing
//************************************************************************************
void LTC2874_write_register(uint8_t LTC2874_register, uint8_t LTC2874_data)
{
  uint8_t command_byte;
  command_byte = LTC2874_WRITE_NO_UPDATE |  (LTC2874_register << 1);

  output_low(LTC2874_CS);               //! 1) Pull CS low to start transaction
  spi_write(command_byte);              //! 2) Write the command and address
  spi_write(LTC2874_data);              //! 3) Write the data
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Sets a register bit without Updating.
//  parameters: register, bit
//  returns: nothing
//************************************************************************************
void LTC2874_write_bit_set(uint8_t LTC2874_register, uint8_t LTC2874_bit)
{
  uint8_t command_byte , mask, data_byte;
  command_byte = LTC2874_READ | (LTC2874_register << 1);

  output_low(LTC2874_CS);               //! 1) Pull CS low
  spi_write(command_byte);              //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);           //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction  

  data_byte |= LTC2874_bit;             // compound bitwise OR

  command_byte = LTC2874_WRITE_NO_UPDATE |  (LTC2874_register << 1);

  output_low(LTC2874_CS);                //! 1) Pull CS low to start transaction
  spi_write(command_byte);               //! 2) Write the command and address
  spi_write(data_byte);                  //! 3) Write the data
  output_high(LTC2874_CS);               //! 4) Pull CS high to finish transaction
}

//************************************************************************************
//  Clears a register bit without Updating.
//  parameters: register, bit
//  returns: nothing.
//************************************************************************************
void LTC2874_write_bit_clr(uint8_t LTC2874_register, uint8_t LTC2874_bit)
{
  uint8_t command_byte , mask, data_byte;
  command_byte = LTC2874_READ |  (LTC2874_register << 1);

  spi_write(command_byte);              //! 2) Write first byte and send command | address
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction  

  mask = ~LTC2874_bit;                  // bitwise NOT
  data_byte &= mask;                    // clears the bit, leaves the rest unchanged

  command_byte = LTC2874_WRITE_NO_UPDATE |  (LTC2874_register << 1);

  output_low(LTC2874_CS);               //! 1) Pull CS low to start transaction
  spi_write(command_byte);              //! 2) Write the command and address
  spi_write(data_byte);                 //! 3) Write the data
  output_high(LTC2874_CS);              //! 4) Pull CS high to finish transaction
}


//************************************************************************************
//  Changes value of a register bit without Updating.
//    NOTE: multi-bit handled by specific functions such as LTC2874_NSF_value()
//  parameters: register, bit, value
//    port#: [1,2,3, or 4]
//    value: 0 or 1
//  returns: nothing
//************************************************************************************
void LTC2874_write_bit_value(uint8_t LTC2874_register, uint8_t LTC2874_bit, uint8_t value)
{
  uint8_t command_byte , data_byte;
  command_byte = LTC2874_READ |  (LTC2874_register << 1);

  output_low(LTC2874_CS);                   //! 1) Pull CS low
  spi_write(command_byte);                  //! 2) Write first byte and send command | address
  data_byte = spi_read(0x00);               //! 3) Read last byte (while sending null data)
  output_high(LTC2874_CS);                  //! 4) Pull CS high to finish transaction  

  if (value)
  {
    data_byte |= LTC2874_bit;
  }
   else
   {
     data_byte &= ~LTC2874_bit;
   }

command_byte = LTC2874_WRITE_NO_UPDATE |  (LTC2874_register << 1);

output_low(LTC2874_CS);                     //! 1) Pull CS low to start transaction
spi_write(command_byte);                    //! 2) Write the command and address
spi_write(data_byte);                       //! 3) Write the data
output_high(LTC2874_CS);                    //! 4) Pull CS high to finish transaction
}

Technical Support