LTC3589/LTC3589-1/ LTC3589-2 - 8-Output Regulator with Sequencing and I2C

Features

  • Triple I2C Adjustable High Efficiency Step-Down DC/DC Converters: 1.6A, 1A/1.2A, 1A/1.2A
  • High Efficiency 1.2A Buck-Boost DC/DC Converter
  • Triple 250mA LDO Regulators
  • Pushbutton ON/OFF Control with System Reset
  • Flexible Pin-Strap Sequencing Operation
  • I2C and Independent Enable Control Pins
  • Power Good and Reset Outputs
  • Dynamic Voltage Scaling and Slew Rate Control
  • Selectable 2.25MHz or 1.12MHz Switching Frequency
  • Always-Alive 25mA LDO Regulator
  • 8μA Standby Current
  • 40-Pin 6mm × 6mm × 0.75mm QFN
  • Click here for Freescale i.MX53 reference design and driver support information

Typical Application

LTC3589 Typical Application
LTC3589 Typical Application

Description

The LTC®3589 is a complete power management solution for ARM and ARM-based processors and advanced portable microprocessor systems. The device contains three step-down DC/DC converters for core, memory and SoC rails, a buck-boost regulator for I/O at 1.8V to 5V and three 250mA LDO regulators for low noise analog supplies. An I2C serial port is used to control enables, output voltage levels, dynamic voltage scaling, operating modes and status reporting. Differences between the LTC3589, LTC3589-1, and LTC3589-2 are summarized in Table 1.

Regulator start-up is sequenced by connecting outputs to enable pins in the desired order or programmed via the I2C port. System power-on, power-off, and reset functions are controlled by pushbutton interface, pin inputs, or I2C interface.

The LTC3589 supports i.MX53/51, PXA and OMAP processors with eight independent rails at appropriate power levels. Other features include interface signals such as the VSTB pin that simultaneously toggle up to four rails between programmed run and standby output voltages. The device is available in a low profile 40-pin 6mm × 6mm exposed pad QFN package.

LTC3589LTC3589-1LTC3589-2
Power-On Inhibit Enable Delay 1 second 2ms 2ms
Buck 2 & 3 Current Output 1A 1.2A 1.2A
PGOOD Fault Timeout Enabled Default, I2C Disable Disabled by Default, I2C Enable Disabled by Default, I2C Enable
PWR_ON to WAKE Delay 50ms 2ms 2ms
LDO3 Vout 1.8V 2.8V 2.8V
LDO4 Vout 1.8V, 2.5V, 2.8V, 3.3V 1.2V, 1.8V, 2.5V, 3.2V 1.2V, 1.8V, 2.5V, 3.2V
LDO4 Vout 1.8V, 2.5V, 2.8V, 3.3V 1.2V, 1.8V, 2.5V, 3.2V 1.2V, 1.8V, 2.5V, 3.2V
Default LDO4 Enable LDO34_EN (Pin) or I2C I2C Only I2C Only
Wait to Enable Until Output < 300mV Yes. Change with I2C Yes. Change with I2C No. Change with I2C
Insert 2.5K Discharge Resistor When Disabled Yes when Wait to Enable Until Output < 300mV Yes when Wait to Enable Until Output < 300mV Always inserted when regulator disabled

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
LTC3589EUJ-1#PBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589EUJ-1#TRPBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589EUJ-2#PBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589EUJ-2#TRPBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589EUJ#PBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589EUJ#TRPBF 6x6 QFN-40 UJ E 05-08-1728 Yes
LTC3589HUJ-1#PBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589HUJ-1#TRPBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589HUJ-2#PBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589HUJ-2#TRPBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589HUJ#PBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589HUJ#TRPBF 6x6 QFN-40 UJ H 05-08-1728 Yes
LTC3589IUJ-1#PBF 6x6 QFN-40 UJ I 05-08-1728 Yes
LTC3589IUJ-1#TRPBF 6x6 QFN-40 UJ I 05-08-1728 Yes
LTC3589IUJ-2#PBF 6x6 QFN-40 UJ I 05-08-1728 Yes
LTC3589IUJ-2#TRPBF 6x6 QFN-40 UJ I 05-08-1728 Yes
LTC3589IUJ#PBF 6x6 QFN-40 UJ I 05-08-1728 Yes
LTC3589IUJ#TRPBF 6x6 QFN-40 UJ I 05-08-1728 Yes


LTC3589 Package Drawing
LTC3589 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
LTC3589EUJ-1#PBF 6x6 QFN-40 E $6.64 $4.65 Yes
LTC3589EUJ-1#TRPBF 6x6 QFN-40 E $4.71 Yes
LTC3589EUJ-2#PBF 6x6 QFN-40 E $6.64 $4.65 Yes
LTC3589EUJ-2#TRPBF 6x6 QFN-40 E $4.71 Yes
LTC3589EUJ#PBF 6x6 QFN-40 E $6.64 $4.65 Yes
LTC3589EUJ#TRPBF 6x6 QFN-40 E $4.71 Yes
LTC3589HUJ-1#PBF 6x6 QFN-40 H $8.14 $5.70 Yes
LTC3589HUJ-1#TRPBF 6x6 QFN-40 H $5.76 Yes
LTC3589HUJ-2#PBF 6x6 QFN-40 H $8.14 $5.70 Yes
LTC3589HUJ-2#TRPBF 6x6 QFN-40 H $5.76 Yes
LTC3589HUJ#PBF 6x6 QFN-40 H $8.14 $5.70 Yes
LTC3589HUJ#TRPBF 6x6 QFN-40 H $5.76 Yes
LTC3589IUJ-1#PBF 6x6 QFN-40 I $7.64 $5.35 Yes
LTC3589IUJ-1#TRPBF 6x6 QFN-40 I $5.41 Yes
LTC3589IUJ-2#PBF 6x6 QFN-40 I $7.64 $5.35 Yes
LTC3589IUJ-2#TRPBF 6x6 QFN-40 I $5.41 Yes
LTC3589IUJ#PBF 6x6 QFN-40 I $7.64 $5.35 Yes
LTC3589IUJ#TRPBF 6x6 QFN-40 I $5.41 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
DC1558A LTC3589EUJ Demo Board | 8-Output Regulator with Sequencing & I2C, 2.7V ≤ VIN ≤ 5.5V, Vout1-8 = 1.2V to 3.3V @ 25mA to 1.6A $250.00
DC1808B-A LTC3589EUJ-1 Demo Board | 8-Output Regulator with Sequencing & I2C, 2.7V ≤ VIN ≤ 5.5V, Vout1-8 = 1.2V to 3.3V @ 25mA to 1.6A $250.00
DC1808B-B LTC3589EUJ-2 Demo Board | 8-Output Regulator with Sequencing & I2C, 2.7V ≤ VIN ≤ 5.5V, Vout1-8 = 1.2V to 3.3V @ 25mA to 1.6A $250.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
Buy Now
Click here to view our complete list of demo boards

Applications

  • Handheld Instruments and Scanners
  • Portable Industrial Devices
  • Automotive Infotainment
  • Medical Devices
  • High End Consumer Devices
  • Multirail Systems
  • Supports Freescale i.MX53/51, Marvell PXA and Other Application Processors

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

LTspice

LTspice® software is a powerful, fast and free simulation tool, schematic capture and waveform viewer with enhancements and models for improving the simulation of switching regulators. Click here to download LTspice

Models for the following parts are available in LTspice:
LTC3589

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

For resources and information on drivers for the LTC3589 in Windows, Linux and Android operating systems, download the LTC3589 Driver Software support documentation.

For more information on using the LTC3589 in conjunction with Freescale development tools and reference designs, please refer to:

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 LTC3589 - DC1558_DC1808.ino

/*!
Linear Technology DC1558 and DC1808 Demonstration Boards.
LTC3589: 8-Output Regulator with Sequencing and I2C

@verbatim

SETUP:
   Set the terminal baud rate to 115200 and select the newline terminator.
   Set all switches in SW1 to their default position.
   Tie PWR_ON high by connecting it to VIN.
   Power VIN from an external power supply.

NOTE:
   For proper IRQ LED behavior, move resistor R39 to the optional R38 position
   on the DC2026B.

@endverbatim

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

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

REVISION HISTORY
$Revision: 5045 $
$Date: 2015-03-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.
*/

/*! @file
    @ingroup LTC3589
*/

#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "UserInterface.h"
#include "LT_I2C.h"
#include "QuikEval_EEPROM.h"
#include "LTC3589.h"

// Global variables
static uint8_t demo_board_connected;     //!< Set to 1 if the board is connected
static uint8_t i2c_address;              //!< I2C address set for all LTC3589 options
static char board_option;                //!< Demo board option of the attached demo board
char demo_name_1[] = "DC1558";           //!< Demo Board Name stored in QuikEval EEPROM
char demo_name_2[] = "DC1808";           //!< Demo Board Name stored in QuikEval EEPROM
uint8_t reg_phase[7] = {1,1,1,1,1,1,1};  //!< Power-up sequence phases for every regulator output
float delay_ms = 0;                      //!< Delay between power-up phases
uint8_t reg_read_list[15] = {0x07,0x010,0x12,0x20,0x23,0x24,0x25,0x26,0x27,0x29,0x2A,0x32,0x33,0x02,0x13};
uint8_t reg_write_list[14] = {0x07,0x010,0x12,0x20,0x21,0x23,0x24,0x25,0x26,0x27,0x29,0x2A,0x32,0x33};

void setup()
//  Setup the program
{
  quikeval_I2C_init();          //! Initializes Linduino I2C port.
  quikeval_I2C_connect();       //! Connects I2C port to the QuikEval connector
  Serial.begin(115200);         //! Initialize the serial port to the PC
  print_title();
  demo_board_connected = discover_demo_boards(demo_name_1, demo_name_2);        //! Checks if correct demo board is connected.
  if (demo_board_connected)
  {
    i2c_address = LTC3589_I2C_ADDRESS;
    print_prompt();
  }
  else
  {
    print_warning_prompt();
    demo_board_connected = true;
    i2c_address = LTC3589_I2C_ADDRESS;
  }
}

//! Repeats Linduino loop
void loop()
{
  int8_t ack=0;
  uint8_t user_command;
  if (demo_board_connected)                          //! Does nothing if the demo board is not connected
  {
    if (Serial.available())                          //! Checks for user input
    {
      user_command = read_int();                     //! Reads the user command
      if (user_command != 'm')
        Serial.println(user_command);
      ack = 0;
      switch (user_command)                               //! Prints the appropriate submenu
      {
        case 1:
          ack |= menu_1_read_write_registers();          // Print single-ended voltage menu
          break;
        case 2:
          ack |= menu_2_regulator_settings();            // Differential voltage menu
          break;
        case 3:
          ack |= menu_3_sequencing(reg_phase);           // Sequencing menu
          break;
        default:
          Serial.println("Incorrect Option");
          break;
      }
      if (ack != 0)
      {
        Serial.print(F("Error: No Acknowledge. \n"));
      }
      print_prompt();
    }
  }
}

// Function Definitions

//! Prints the Read/Write Registers menu and handles the user response.
//! @return State of the acknowledge bit after menu selection. 0=valid selection, 1=invalid selection.
int8_t menu_1_read_write_registers()
{
  int8_t ack=0;
  uint8_t user_command;
  uint8_t data;
  uint8_t user_register;
  uint8_t user_bit;
  do
  {
    //! Displays the Read/Write Registers menu
    Serial.print(F("\nRead/Write Registers\n\n"));
    Serial.print(F("  1-Read All Registers\n"));
    Serial.print(F("  2-Read Single Register\n"));
    Serial.print(F("  3-Write Single Register\n"));
    Serial.print(F("  4-Set Bit\n"));
    Serial.print(F("  5-Clear Bit\n"));
    Serial.print(F("  6-Clear IRQ\n"));
    Serial.print(F("  m-Main Menu\n"));
    Serial.print(F("\nEnter a command: "));

    user_command = read_int();                              //! Reads the user command
    if (user_command == 'm')                                // Print m if it is entered
    {
      Serial.print(F("m\n"));
    }
    else
      Serial.println(user_command);                         // Print user command

    //! Reads or writes to a LTC3589 and prints result.
    switch (user_command)
    {
      case 1:
        // Read every register and print it's data.
        ack |= LTC3589_print_all_registers(i2c_address);
        break;
      case 2:
        // Read a single register and print it's data.
        Serial.print(F("\nAddress (in hex with '0x' prefix) of register to read: "));
        user_register = read_int();
        Serial.print("0x");
        Serial.println(user_register, HEX);
        if (!valid_register(user_register, reg_read_list, sizeof(reg_read_list)))
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.print("Register data: 0x");
        Serial.println(data, HEX);
        break;
      case 3:
        // Write a byte to a chosen register.
        Serial.print(F("\nAddress (in hex with '0x' prefix) of register to write: "));
        user_register = read_int();
        Serial.print("0x");
        Serial.println(user_register, HEX);
        if (user_register == 0x21)
        {
          Serial.println(F("  Clear IRQ command sent."));
          ack |= LTC3589_register_write(i2c_address, user_register, 0x01);
          break;
        }
        else if (!valid_register(user_register, reg_write_list, sizeof(reg_write_list)))
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Data (in hex with '0x' prefix) to write: "));
        data = read_int();
        Serial.println(data, HEX);
        ack |= LTC3589_register_write(i2c_address, user_register, data);
        Serial.print("0x");
        Serial.print(data, HEX);
        Serial.print(" written to register 0x");
        Serial.println(user_register, HEX);
        break;
      case 4:
        // Set a single bit within a chosen register.
        Serial.print(F("\nAddress (in hex with '0x' prefix) of register: "));
        user_register = read_int();
        Serial.print("0x");
        Serial.println(user_register, HEX);
        if (!valid_register(user_register, reg_write_list, sizeof(reg_write_list)))
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Bit position (0-7) to set: "));
        data = read_int();
        if (data < 0 || data > 7)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.println(data, DEC);
        ack |= LTC3589_bit_set(i2c_address, user_register, data);
        Serial.print("Bit set. Register data is now 0x");
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data, HEX);
        break;
      case 5:
        // Clear a single bit within a chosen register.
        Serial.print(F("\nAddress (in hex with '0x' prefix) of register: "));
        user_register = read_int();
        Serial.print("0x");
        Serial.println(user_register, HEX);
        if (!valid_register(user_register, reg_write_list, sizeof(reg_write_list)))
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Bit position (0-7) to clear: "));
        data = read_int();
        if (data < 0 || data > 7)
        {
          Serial.println(F("Invalid input."));
          break;
        }
        Serial.println(data, DEC);
        ack |= LTC3589_bit_clear(i2c_address, user_register, data);
        Serial.print("Bit cleared. Register data is now 0x");
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data, HEX);
        break;
      case 6:
        // Clear IRQ register
        Serial.println(F("\n  Clear IRQ command sent."));
        ack |= LTC3589_register_write(i2c_address, LTC3589_REG_CLIRQ, 0x01);
        break;
      default:
        if (user_command != 'm')
          Serial.println("Invalid Selection");
        break;
    }
  }
  while ((user_command != 'm') && (ack != 1));
  return(ack);
}

//! Prints the Regulator Settings menu and handles the user response.
//! @return State of the acknowledge bit after menu selection. 0=valid selection, 1=invalid selection.
int8_t menu_2_regulator_settings()
{
  int8_t ack=0;
  uint8_t user_command;
  uint8_t data;
  uint8_t user_register;
  uint8_t user_int;
  uint8_t user_buck;
  uint8_t user_ldo;
  int8_t user_char;
  do
  {
    //! Displays the Regulator Settings menu
    Serial.print(F("\nRegulator Settings\n\n"));
    Serial.print(F("  1-Enable/Disable Switchers\n"));
    Serial.print(F("  2-Enable/Disable LDOs\n"));
    Serial.print(F("  3-Set Buck Output Voltage\n"));
    Serial.print(F("  4-Set Buck Feedback Reference\n"));
    Serial.print(F("  5-Select Buck Reference\n"));
    Serial.print(F("  6-Set LDO2 Output Voltage\n"));
    Serial.print(F("  7-Set LDO2 Feedback Reference\n"));
    Serial.print(F("  8-Select LDO2 Reference\n"));
    Serial.print(F("  9-Set Buck Switching Mode\n"));
    Serial.print(F(" 10-Set Buck-Boost Switching Mode\n"));
    Serial.print(F(" 11-Set Start-Up Mode (300mV check)\n"));
    Serial.print(F(" 12-Set PGOOD Slewing Mask Bits\n"));
    Serial.print(F(" 13-Set LDO4 Voltage\n"));
    Serial.print(F(" 14-Set Switch DV/DT Control\n"));
    Serial.print(F(" 15-Set Regulator Slew Rate\n"));
    Serial.print(F(" 16-Exit Software Control Mode\n"));
    Serial.print(F("  m-Main Menu\n"));
    Serial.print(F("\nEnter a command: "));

    user_command = read_int();                              //! Reads the user command
    if (user_command == 'm')                                // Print m if it is entered
      Serial.print(F("m\n"));
    else
      Serial.println(user_command);                         // Print user command

    //! Reads or writes to a LTC3589 and prints result.
    switch (user_command)
    {
      case 1:
        //Enter software control mode
        if (!LTC3589_bit_is_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL))
        {
          Serial.print(F("\n********** Note: LTC3589 is now in Sofware Control Mode **********\n"));
          Serial.print(F("***************Select Option 16 to resume Pin Control ************\n"));
          ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL);
        }
        // Enable/Disable Bucks
        Serial.print(F("\nSelect Regulator(1-3=Bucks, 4=Buck-boost, 5=All): "));
        user_buck = read_int();
        Serial.println(user_buck, DEC);
        if (user_buck < 1 || user_buck > 5)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.println(F("0=Disable, 1=Enable"));
        Serial.print(F("Enter selection: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int > 1)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        if (user_buck == 5)
        {
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN1, user_int);
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN2, user_int);
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN3, user_int);
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN4, user_int);
        }
        else
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, user_buck-1, user_int);
        Serial.println(F("Done."));
        break;
      case 2:
        //Enter software control mode
        if (!LTC3589_bit_is_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL))
        {
          Serial.print(F("\n********** Note: LTC3589 is now in Sofware Control Mode **********\n"));
          Serial.print(F("***************Select Option 16 to resume Pin Control ************\n"));
          ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL);
        }
        // Enable/Disable LDOs
        Serial.print(F("\nSelect LDO(2-4, 5=all): "));
        user_ldo = read_int();
        Serial.println(user_ldo, DEC);
        if (user_ldo < 2 || user_ldo > 5)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.println(F("0=Disable, 1=Enable"));
        Serial.print(F("Enter selection: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int > 1)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        if (user_ldo == 5)
        {
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN_LDO2, user_int);
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN_LDO3, user_int);
          ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, LTC3589_EN_LDO4, user_int);
        }
        ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_OVEN, user_ldo+2, user_int);
        Serial.println(F("Done."));
        break;
      case 3:
        // Set buck output voltage in mV
        float user_output;
        float new_output;
        Serial.print(F("\nSelect Buck(1-3): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 1 || user_int > 3)
        {
          Serial.println(F("Invalid input."));
          break;
        }
        if (user_int == 1)
          user_register = LTC3589_REG_B1DTV1;    //Converts selection to appropriate register address.
        else if (user_int == 2)
          user_register = LTC3589_REG_B2DTV1;    //Converts selection to appropriate register address.
        else if (user_int == 3)
          user_register = LTC3589_REG_B3DTV1;    //Converts selection to appropriate register address.
        Serial.print(F("Select Reference (1=B"));
        Serial.print(user_int, DEC);
        Serial.print(F("DTV1, 2=B"));
        Serial.print(user_int, DEC);
        Serial.print(F("DTV2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char < '1' || user_char > '2')
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        else if (user_char == '2')
          user_register += 1;    //Converts selection of appropriate register address.
        Serial.print(F("\nPotential output voltage range: "));
        Serial.print(LTC3589_buck_vout_min(user_int), 0);
        Serial.print(F("mV to "));
        Serial.print(LTC3589_buck_vout_max(user_int), 0);
        Serial.print(F("mV."));
        Serial.print(F("\nNew output voltage in mV: "));
        user_output = read_float();
        Serial.println(user_output, 0);
        if (user_output < LTC3589_buck_vout_min(user_int) | user_output > LTC3589_buck_vout_max(user_int))
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        new_output = LTC3589_set_buck_output_voltage(i2c_address, user_register, user_output);
        Serial.print(F("Output voltage set to "));
        Serial.print(new_output, 0);
        Serial.println(F("mV"));
        Serial.print(F("New Feedback Reference Bits: 0x"));
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data & 0x1F, HEX);
        break;
      case 4:
        // Set buck feedback reference voltage in mV
        float user_reference;
        float new_reference;
        Serial.print(F("\nSelect Buck(1-3): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 1 || user_int > 3)
        {
          Serial.println(F("Invalid input."));
          break;
        }
        if (user_int == 1)
          user_register = LTC3589_REG_B1DTV1;    //Converts selection to appropriate register address.
        else if (user_int == 2)
          user_register = LTC3589_REG_B2DTV1;    //Converts selection to appropriate register address.
        else if (user_int == 3)
          user_register = LTC3589_REG_B3DTV1;    //Converts selection to appropriate register address.
        Serial.print(F("Select Reference (1=B"));
        Serial.print(user_int);
        Serial.print(F("DTV1, 2=B"));
        Serial.print(user_int);
        Serial.print(F("DTV2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char < '1' || user_char > '2')
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        else if (user_char == '2')
          user_register += 1;    //Converts selection of appropriate register address.
        Serial.print(F("\nNew feedback reference input in mV (362.5-750): "));
        user_reference = read_float();
        Serial.println(user_reference);
        if (user_reference < 362.5 | user_reference > 750)
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        new_reference = LTC3589_set_buck_fb_ref(i2c_address, user_register, user_reference);
        Serial.print(F("Feedback reference input set to "));
        Serial.print(new_reference, 0);
        Serial.println(F("mV"));
        Serial.print(F("New Feedback Reference Bits: 0x"));
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data & 0x1F, HEX);
        break;
      case 5:
        // Select buck reference (1 or 2)
        Serial.print(F("\nSelect Buck(1-3, 4=all): "));
        user_buck = read_int();
        Serial.println(user_buck, DEC);
        if (user_buck < 1 || user_buck > 4)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Select Reference 1 or 2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char == '1' || user_char == '2')
        {
          if (user_buck == 4)
            ack |= LTC3589_select_buck_reference(i2c_address, 0xFF, user_char);
          else
            ack |= LTC3589_select_buck_reference(i2c_address, user_buck, user_char);
          Serial.println(F("\nDone."));
          break;
        }
        Serial.println(F("\n  Invalid input."));
        break;
      case 6:
        // Set LDO2 output voltage in mV
        user_register = LTC3589_REG_L2DTV1;
        Serial.print(F("Select Reference (1=L2DTV1, 2=L2DTV2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char < '1' || user_char > '2')
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        else if (user_char == '2')
          user_register += 1;    //Converts selection of appropriate register address.
        Serial.print(F("\nPotential output voltage range: "));
        Serial.print(LTC3589_ldo2_vout_min(), 0);
        Serial.print(F("mV to "));
        Serial.print(LTC3589_ldo2_vout_max(), 0);
        Serial.print(F("mV"));
        Serial.print(F("\nNew output voltage in mV: "));
        user_output = read_float();
        Serial.println(user_output, 0);
        if (user_output < LTC3589_ldo2_vout_min() | user_output > LTC3589_ldo2_vout_max())
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        new_output = LTC3589_set_ldo2_output_voltage(i2c_address, user_register, user_output);
        Serial.print(F("Output voltage set to "));
        Serial.print(new_output, 0);
        Serial.println(F("mV"));
        Serial.print(F("New Feedback Reference Bits: 0x"));
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data & 0x1F, HEX);
        break;
      case 7:
        // Set LDO2 feedback reference voltage in mV
        Serial.print(F("Select Reference (1=L2DTV1, 2=L2DTV2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char < '1' || user_char > '2')
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        else if (user_char == '2')
          user_register += 1;    //Converts selection of appropriate register address.
        Serial.print(F("\nNew feedback reference input in mV (362.5-750): "));
        user_reference = read_float();
        Serial.println(user_reference);
        if (user_reference < 362.5 | user_reference > 750)
        {
          Serial.println(F("\nInvalid input."));
          break;
        }
        new_reference = LTC3589_set_ldo2_fb_ref(i2c_address, user_register, user_reference);
        Serial.print(F("Feedback reference input set to "));
        Serial.print(new_reference, 0);
        Serial.println(F("mV"));
        Serial.print(F("New Feedback Reference Bits: 0x"));
        ack |= LTC3589_register_read(i2c_address, user_register, &data);
        Serial.println(data & 0x1F, HEX);
        break;
      case 8:
        // Select LDO2 reference (1 or 2)
        Serial.print(F("Select Reference 1 or 2): "));
        user_char = read_char();
        Serial.write(user_char);
        if (user_char == '1' || user_char == '2')
        {
          ack |= LTC3589_select_ldo2_reference(i2c_address, user_char);
          Serial.println(F("\nDone."));
          break;
        }
        Serial.println(F("\n  Invalid input."));
        break;
      case 9:
        // Set buck switching mode
        Serial.print(F("\nSelect Buck(1-3, 4=all): "));
        user_register = read_int();
        Serial.println(user_register, DEC);
        if (user_register < 1 || user_register > 4)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Select mode (0=Pulse Skipping, 1=Burst, 2=Forced Continuous): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 0 || user_int > 2)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        if (user_register == 4)
          ack |= LTC3589_set_buck_mode(i2c_address, 0xFF, user_int);
        else
          ack |= LTC3589_set_buck_mode(i2c_address, user_register, user_int);
        Serial.println(F("Switching mode(s) set."));
        break;
      case 10:
        // Set buck-boost switching mode
        Serial.print(F("Select mode (0=Continuous, 1=Burst): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 0 || user_int > 1)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_SCR1, LTC3589_BUCKBOOST_MODE, user_int);
        Serial.println(F("Switching mode(s) set."));
        break;
      case 11:
        // Sets the startup mode for all bucks
        Serial.println(F("0=Wait for output <300mV to enable, 1=Don't wait & disable discharge resistor"));  //Standard and -1 Option
        // Serial.println(F("0=Enable at any output voltage, 1=Wait for output <300mV to enable"));    //-2 Option
        Serial.print(F("\nSelect start-up mode: "));
        Serial.print(F("Enter selection: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 0 || user_int > 1)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.println(F("Start-up modes set."));
        break;
      case 12:
        // Sets PGOOD mask bit.
        Serial.println(F("0=PGOOD low when slewing, 1=PGOOD not forced low when slewing"));
        Serial.print(F("Enter selection: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 0 || user_int > 1)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        ack |= LTC3589_set_pgood_mask(i2c_address, user_int);
        Serial.println(F("PGOOD Mask bits set."));
        break;
      case 13:
        // Set LDO4 Output Voltage
        //if (board_option == 'B')
        //{
        if (demo_board.option == 'A' || demo_board.option == 'B')
        {
          Serial.print(F("Select LDO4 Voltage (0=1.2V, 1=1.8V, 2=2.5V, 3=3.2V): "));
        }
        else
        {
          Serial.print(F("Select LDO4 Voltage (0=2.8V, 1=2.5V, 2=1.8V, 3=3.3V): "));
        }
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int > 3)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        ack |= LTC3589_set_ldo4_voltage(i2c_address, user_int);
        Serial.println(F("LDO4 Voltage Set."));
        break;
        //}
        //Serial.println(" Invalid Selection");
        //break;
      case 14:
        // Set switch DV/DT control
        Serial.print(F("Select DV/DT Control (0=1ns, 1=2ns, 2=4ns, 3=8ns): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int > 3)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        ack |= LTC3589_set_switch_dvdt_control(i2c_address, user_int);
        Serial.println(F("Switch DV/DT Set."));
        break;
      case 15:
        // Set regulator slew rate
        Serial.print(F("\nSelect Regulator(1-3=Bucks, 4=LDO2, 5=All): "));
        user_buck = read_int();
        Serial.println(user_buck, DEC);
        if (user_buck < 1 || user_buck > 5)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        Serial.print(F("Select Slew Rate (0=0.88mV/us, 1=1.75mV/us, 2=3.5mV/us, 3=7mV/us): "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int > 3)
        {
          Serial.println(F("  Invalid input."));
          break;
        }
        if (user_buck == 5)
        {
          ack |= LTC3589_set_regulator_slew(i2c_address, 0xFF, user_int);
        }
        else
          ack |= LTC3589_set_regulator_slew(i2c_address, 3<<((user_buck-1)*2), user_int);
        Serial.println(F("Done."));
        break;
      case 16:
        // Exit software control mode
        ack |= LTC3589_bit_clear(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL);
        Serial.println(F("\nDone."));
        break;
      default:
        if (user_command != 'm')
          Serial.println(" Invalid Selection");
        break;
    }
  }
  while ((user_command != 'm') && (ack != 1));
  return (ack);
}

//! Prints the Powerup Sequencing menu and handles the user response.
//! @return State of the acknowledge bit after menu selection. 0=valid selection, 1=invalid selection.
int8_t menu_3_sequencing(uint8_t *reg_phase)
{
  int8_t ack=0;
  uint8_t user_command;
  uint8_t data;
  uint8_t user_sequence;
  uint8_t user_int;
  uint8_t reg_map[6];
  uint8_t reg_oven;
  uint8_t reg_bit_position[7] = {0,1,2,3,4,5,6};
  int count;

  //Enter software control mode
  if (!LTC3589_bit_is_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL))
  {
    Serial.print(F("\n********** Note: LTC3589 is now in Sofware Control Mode **********\n"));
    Serial.print(F("************** Select Option 5 to resume Pin Control *************\n"));
    ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL);
  }
  do
  {
    //! Displays the Startup Sequencing menu

    Serial.print(F("\nPowerup Sequencing\n\n"));
    Serial.print(F("  1-Set Power-up Sequence\n"));
    Serial.print(F("  2-Print Power-up Sequence\n"));
    Serial.print(F("  3-Power-up Regulators\n"));
    Serial.print(F("  4-Power-down Regulators\n"));
    Serial.print(F("  5-Exit Software Control Mode\n"));
    Serial.print(F("  m-Main Menu\n"));
    Serial.print(F("\nEnter a command: "));

    user_command = read_int();                              //! Reads the user command
    if (user_command == 'm')                                // Print m if it is entered
      Serial.print(F("m\n"));
    else
      Serial.println(user_command);                         // Print user command

    switch (user_command)
    {
      case 1:
        Serial.println(F("\nRegulators will power-up in 4 phases"));
        Serial.println(F("Select a phase for each"));
        Serial.println(F("1=First phase, 2=Second phase, 3=Third phase, 4=Fourth phase, 0=Don't enable"));
        Serial.print(F("Buck1: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[0] = user_int;
        Serial.print(F("Buck2: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[1] = user_int;
        Serial.print(F("Buck3: "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[2] = user_int;
        Serial.print(F("BB:    "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[3] = user_int;
        Serial.print(F("LDO2:  "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[4] = user_int;
        Serial.print(F("LDO3:  "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[5] = user_int;
        Serial.print(F("LDO4:  "));
        user_int = read_int();
        Serial.println(user_int, DEC);
        if (user_int < 5)
          reg_phase[6] = user_int;
        Serial.print(F("Enter delay between phases in milliseconds: "));
        delay_ms = read_float();
        if (delay_ms >= 0 && delay_ms <= 10000)
          Serial.println(delay_ms, 1);
        else
          Serial.println(F("Values less than 0 or greater than 10s not allowed."));
        break;
      case 2:
        Serial.print(F("\nBuck1: "));
        Serial.println(reg_phase[0]);
        Serial.print(F("Buck2: "));
        Serial.println(reg_phase[1]);
        Serial.print(F("Buck3: "));
        Serial.println(reg_phase[2]);
        Serial.print(F("BB:    "));
        Serial.println(reg_phase[3]);
        Serial.print(F("LDO2:  "));
        Serial.println(reg_phase[4]);
        Serial.print(F("LDO3:  "));
        Serial.println(reg_phase[5]);
        Serial.print(F("LDO4:  "));
        Serial.println(reg_phase[6]);
        Serial.print(F("Delay: "));
        Serial.print(delay_ms, 1);
        Serial.println(F("ms"));
        break;
      case 3:
        ack |= LTC3589_register_read(i2c_address, LTC3589_REG_OVEN, &reg_oven);
        //Start Phase 1 Regulators
        for (count=0; count<7; count++)
        {
          if (reg_phase[count] == 1)
          {
            reg_oven |= 0x01<<reg_bit_position[count];
            ack |= LTC3589_register_write(i2c_address, LTC3589_REG_OVEN, reg_oven);
          }
        }
        delay(delay_ms);

        //Start Phase 2 Regulators
        for (count=0; count<7; count++)
        {
          if (reg_phase[count] == 2)
          {
            reg_oven |= 0x01<<reg_bit_position[count];
            ack |= LTC3589_register_write(i2c_address, LTC3589_REG_OVEN, reg_oven);
          }
        }
        delay(delay_ms);

        //Start Phase 3 Regulators
        for (count=0; count<7; count++)
        {
          if (reg_phase[count] == 3)
          {
            reg_oven |= 0x01<<reg_bit_position[count];
            ack |= LTC3589_register_write(i2c_address, LTC3589_REG_OVEN, reg_oven);
          }
        }
        delay(delay_ms);

        //Start Phase 4 Regulators
        for (count=0; count<7; count++)
        {
          if (reg_phase[count] == 4)
          {
            reg_oven |= 0x01<<reg_bit_position[count];
            ack |= LTC3589_register_write(i2c_address, LTC3589_REG_OVEN, reg_oven);
          }
        }
        break;
      case 4:
        // Power-down by clearing all enable bits
        ack |= LTC3589_register_write(i2c_address, LTC3589_REG_OVEN, 0x80);
        break;
      case 5:
        // Exit software control mode
        ack |= LTC3589_bit_clear(i2c_address, LTC3589_REG_OVEN, LTC3589_SOFTWARE_CNTRL);
        user_command = 'm';
        break;
      default:
        if (user_command != 'm')
          Serial.println(" Invalid Selection");
        break;
    }
  }
  while ((user_command != 'm') && (ack != 1));
  return (ack);
}

//! Prints the title block when program first starts.
void print_title()
{
  Serial.print(F("\n******************************************************************\n"));
  Serial.print(F("* DC1558A Demonstration Program                                  *\n"));
  Serial.print(F("*                                                                *\n"));
  Serial.print(F("* This program demonstrates how to send and receive data from    *\n"));
  Serial.print(F("* the LTC3589 8-Output Regulator with Sequencing and I2C.        *\n"));
  Serial.print(F("*                                                                *\n"));
  Serial.print(F("* Setup:                                                         *\n"));
  Serial.print(F("* Set the baud rate to 115200 and select the newline terminator. *\n"));
  Serial.print(F("* Set all switches in SW1 to their default position.             *\n"));
  Serial.print(F("* Tie PWR_ON high by connecting it to VIN.                       *\n"));
  Serial.print(F("* Power VIN from an external power supply.                       *\n"));
  Serial.print(F("*                                                                *\n"));
  Serial.print(F("* Note:                                                          *\n"));
  Serial.print(F("* For proper IRQ LED behavior, move resistor R39 to the          *\n"));
  Serial.print(F("* optional R38 position on the DC2026B.                          *\n"));
  Serial.print(F("******************************************************************\n"));
}

//! Prints main menu.
void print_prompt()
{
  Serial.print(F("\n  1-Read/Write Registers\n"));
  Serial.print(F("  2-Regulator Settings\n"));
  Serial.print(F("  3-Sequencing\n"));
  Serial.print(F("\nEnter a command:"));
}

//! Prints a warning that no demo board was not detected.
void print_warning_prompt()
{
  Serial.println(F("\nWarning: Demo board not detected. Linduino will attempt to proceed."));
}

//! Reads and prints the data in every register
//! @return State of the acknowledge bit. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_print_all_registers(uint8_t i2c_address)
{
  int8_t ack = 0;
  uint8_t data;
  uint8_t i;
  for (i=0; i<sizeof(reg_read_list); i++)
  {
    ack |= LTC3589_register_read(i2c_address, reg_read_list[i], &data);   //! Read register
    Serial.print("Register 0x");
    Serial.print(reg_read_list[i], HEX);
    Serial.print(":\t0x");
    Serial.println(data, HEX);
  }
  return ack;
}

//! Checks to see if a register address is a valid address in this device.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
boolean valid_register(uint8_t user_register, uint8_t register_array[], uint8_t array_length)
{
  uint8_t i=0;
  for (i=0; i<array_length; i++)
  {
    if (register_array[i] == user_register)
    {
      return true;
    }
  }
  return false;
}

//! Read the ID string from the EEPROM to identify the connected demo board.
//! @return Returns 1 if successful, 0 if not successful
int8_t discover_demo_boards(char *demo_name_1, char *demo_name_2)
{
  int8_t connected;
  connected = 1;
  // read the ID from the serial EEPROM on the board
  // reuse the buffer declared in UserInterface
  if (read_quikeval_id_string(&ui_buffer[0]) == 0) connected = 0;
  // make sure it is the correct demo board
  if (strcmp(demo_board.name, demo_name_1) == 0) connected = 1;
  else if (strcmp(demo_board.name, demo_name_2) == 0) connected = 1;
  else connected = 0;
  if (connected != 0)
  {
    Serial.print("Demo Board Name: ");
    Serial.println(demo_board.name);
    Serial.print("Product Name: ");
    Serial.println(demo_board.product_name);
    if (demo_board.option)
    {
      Serial.print("Demo Board Option: ");
      Serial.println(demo_board.option);
    }
  }
  else
  {
    Serial.print("Demo board not found, \nfound ");
    Serial.print(demo_board.name);
    Serial.println(" instead. \nConnect the correct demo board, then press the reset button.");
  }
  return(connected);
}

Download LTC3589 Linduino Header File

/*!
LTC3589: 8-Output Regulator with Sequencing and I2C

@verbatim

The LTC3589 is a complete power management solution for ARM and ARM-based
processors and advanced portable microprocessor systems. The device contains
three step-down DC/DC converters for core, memory and SoC rails, a
buck-boost regulator for I/O at 1.8V to 5V and three 250mA LDO regulators
for low noise analog supplies. An I2C serial port is used to control enables,
output voltage levels, dynamic voltage scaling, operating modes and status
reporting.
Regulator start-up is sequenced by connecting outputs to enable pins in the
desired order or programmed via the I2C port. System power-on, power-off,
and reset functions are controlled by pushbutton interface, pin inputs, or
I2C interface.
The LTC3589 supports i.MX53/51, PXA and OMAP processors with eight
independent rails at appropriate power levels. Other features include
interface signals such as the VSTB pin that simultaneously toggle up to
four rails between programmed run and standby output voltages.  The device
is available in a low profile 40-pin 6mm x 6mm exposed pad QFN package.

I2C DATA FORMAT (MSB FIRST);

@endverbatim

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

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

REVISION HISTORY
$Revision: 5045 $
$Date: 2015-03-18$

Copyright (c) 2014, 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 LTC3589
    Library Header File for LTC3589: 8-Output Regulator with Sequencing and I2C
*/

#ifndef LTC3589_H
#define LTC3589_H
#endif

/*! @name I2C Address
    I2C address of the LTC3589/LTC3589-1/LTC3589-2.
@{ */
/* LTC3589 I2C Addresses */
#define LTC3589_I2C_ADDRESS         0x34
/*! @} */

/*! @name Feedback Resistors
    Factory feedback resistor values for the LTC3589 demo boards in kOhm.
@{ */
#define LTC3589_RES_BUCK1_RTOP      604
#define LTC3589_RES_BUCK1_RBOT      768
#define LTC3589_RES_BUCK2_RTOP      715
#define LTC3589_RES_BUCK2_RBOT      422
#define LTC3589_RES_BUCK3_RTOP      681
#define LTC3589_RES_BUCK3_RBOT      787
#define LTC3589_RES_LDO2_RTOP       604
#define LTC3589_RES_LDO2_RBOT       768
/*! @} */

/*! @name Registers
@{ */
/* LTC3589 Registers */
#define LTC3589_REG_SCR1             0x07
#define LTC3589_REG_OVEN             0x10
#define LTC3589_REG_SCR2             0x12
#define LTC3589_REG_VCCR             0x20
#define LTC3589_REG_CLIRQ            0x21
#define LTC3589_REG_B1DTV1           0x23
#define LTC3589_REG_B1DTV2           0x24
#define LTC3589_REG_VRRCR            0x25
#define LTC3589_REG_B2DTV1           0x26
#define LTC3589_REG_B2DTV2           0x27
#define LTC3589_REG_B3DTV1           0x29
#define LTC3589_REG_B3DTV2           0x2A
#define LTC3589_REG_L2DTV1           0x32
#define LTC3589_REG_L2DTV2           0x33
#define LTC3589_REG_IRQSTAT          0x02
#define LTC3589_REG_PGSTAT           0x13
/*! @} */

/*! @name LTC3589_REG_SCR1 Register Settings
    Bit position of single bit settings in the LTC3589_REG_SCR1 registers.
@{ */
#define LTC3589_BUCKBOOST_MODE       6
/*! @} */

/*! @name LTC3589_REG_OVEN Register Settings
    Bit position of single bit settings in the LTC3589_REG_OVEN register.
@{ */
#define LTC3589_SOFTWARE_CNTRL       7
#define LTC3589_EN_LDO4              6
#define LTC3589_EN_LDO3              5
#define LTC3589_EN_LDO2              4
#define LTC3589_EN4                  3
#define LTC3589_EN3                  2
#define LTC3589_EN2                  1
#define LTC3589_EN1                  0
/*! @} */

/*! @name LTC3589_REG_SCR2 Register Settings
    Bit position of single bit settings in the LTC3589_REG_SCR2 register.
@{ */
#define LTC3589_MASK_PG_SHUTDOWN     7
#define LTC3589_LDO4_STARTUP         6
#define LTC3589_LDO3_STARTUP         5
#define LTC3589_LDO2_STARTUP         4
#define LTC3589_BB_STARTUP           3
#define LTC3589_BUCK3_STARTUP        2
#define LTC3589_BUCK2_STARTUP        1
#define LTC3589_BUCK1_STARTUP        0
/*! @} */

/*! @name LTC3589_REG_VCCR Register Settings
    Bit position of single bit settings in the LTC3589_REG_VCCR register.
@{ */
#define LTC3589_LDO2_REF_SELECT      7
#define LTC3589_LDO2_GO              6
#define LTC3589_BUCK3_REF_SELECT     5
#define LTC3589_BUCK3_GO             4
#define LTC3589_BUCK2_REF_SELECT     3
#define LTC3589_BUCK2_GO             2
#define LTC3589_BUCK1_REF_SELECT     1
#define LTC3589_BUCK1_GO             0
/*! @} */

/*! @name LTC3589_REG_BxDTV1 Register Settings
    Bit position of single bit settings in the LTC3589_REG_BxDTV1 registers.
@{ */
#define LTC3589_BUCK_PG_MASK         5
/*! @} */

/*! @name LTC3589_REG_BxDTV2 Register Settings
    Bit position of single bit settings in the LTC3589_REG_BxDTV2 register.
@{ */
#define LTC3589_BUCK_KEEP_ALIVE      7
#define LTC3589_BUCK_PHASE_SEL       6
#define LTC3589_BUCK_CLOCK_RATE      5
/*! @} */

/*! @name LTC3589_REG_L2DTV1 Register Settings
    Bit position of single bit settings in the LTC3589_REG_L2DTV1 register.
@{ */
#define LTC3589_LDO2_KEEP_ALIVE      7
#define LTC3589_LDO2_PG_MASK         5
/*! @} */

/*! @name LTC3589_REG_L2DTV2 Register Settings
    Bit position of single bit settings in the LTC3589_REG_L2DTV2 register.
@{ */
#define LTC3589_LDO2_CNTRL_MODE      7
/*! @} */

/*! @name LTC3589_REG_IRQSTAT Register Settings
    Bit position of status bits in the LTC3589_REG_IRQSTAT register.
@{ */
#define LTC3589_IRQ_OT_SHUTDOWN      7
#define LTC3589_IRQ_OT_WARNING       6
#define LTC3589_IRQ_UV_SHUTDOWN      5
#define LTC3589_IRQ_UV_WARNING       4
#define LTC3589_IRQ_PG_SHUTDOWN      3
/*! @} */

/*! @name LTC3589_REG_PGSTAT Register Settings
    Bit position of status bits in the LTC3589_REG_PGSTAT register.
@{ */
#define LTC3589_PG_LDO4              7
#define LTC3589_PG_LDO3              6
#define LTC3589_PG_LDO2              5
#define LTC3589_PG_BB                4
#define LTC3589_PG_BUCK3             3
#define LTC3589_PG_BUCK2             2
#define LTC3589_PG_BUCK1             1
#define LTC3589_PG_LDO1              0
/*! @} */

/*! @name LTC3589 Mask Settings
    Bitwise AND with register data to determine present setting.
@{ */
#define LTC3589_BUCK_MODE_MASK(num) (0x03<<((num)*2)-2)
#define LTC3589_BUCK3_MODE_MASK      0x30
#define LTC3589_BUCK2_MODE_MASK      0x0C
#define LTC3589_BUCK1_MODE_MASK      0x03
#define LTC3589_BUCK_DVDT_MASK       0xC0
#define LTC3589_FB_REF_MASK          0x1F
#define LTC3589_LDO2_SLEW_MASK       0xC0
#define LTC3589_BUCK3_SLEW_MASK      0x30
#define LTC3589_BUCK2_SLEW_MASK      0x0C
#define LTC3589_BUCK1_SLEW_MASK      0x03
#define LTC3589_LDO4_VOLTAGE_MASK    0x60
/*! @} */


//! Reads an 8-bit register from the LTC3589 using the standard repeated start format.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_register_read(uint8_t i2c_address,       //!< I2C address of the LTC3589.
                             uint8_t register_address,  //!< Address of the LTC3589 register to be read. This is also known as the "command byte".
                             uint8_t *register_data     //!< returns 8-bit value read from the LTC3589 register.
                            );

//! Writes to an 8-bit register inside the LTC3589 using the standard I2C repeated start format.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_register_write(uint8_t i2c_address,      //!< I2C address of the LTC3589.
                              uint8_t register_address, //!< Address of the LTC3589 register to be overwritten.  This is also known as the "command byte".
                              uint8_t register_data     //!< Value that will be written to the register.
                             );

//! Sets any bit inside the LTC3589 using the standard I2C repeated start format.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_bit_set(uint8_t i2c_address,      //!< I2C address of the LTC3589.
                       uint8_t register_address, //!< Address of the LTC3589 register to be overwritten.  This is also known as the "command byte".
                       uint8_t bit_number        //!< Bit location (0-7) to be written.
                      );

//! Clears any bit inside the LTC3589 using the standard I2C repeated start format.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_bit_clear(uint8_t i2c_address,      //!< I2C address of the LTC3589.
                         uint8_t register_address, //!< Address of the LTC3589 register to be overwritten.  This is also known as the "command byte".
                         uint8_t bit_number       //!< Address of the bit to set within the register.
                        );

//! Writes any bit inside the LTC3589 using the standard I2C repeated start format.
//! @return State of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_bit_write(uint8_t i2c_address,       //!< I2C address of the LTC3589.
                         uint8_t register_address,  //!< Address of the LTC3589 register to be written.
                         uint8_t bit_number,        //!< Bit location (0-7) to be written.
                         uint8_t bit_data           //!< Bit data (0 or 1) to be written.
                        );

//! Reads the value of any bit in any register or the LTC3589.
//! @return Bit value at the passed register subaddress and bit location.
uint8_t LTC3589_bit_is_set(uint8_t i2c_address,        //!< I2C address of the LTC3589.
                           uint8_t register_address,   //!< Address of the LTC3589 register to be read. This is also known as the "command byte".
                           uint8_t bit_number          //!< Bit location (0-7) to be read.
                          );

//! Sets the output voltage of LDO2.
//! @return New LDO2 output voltage, the closest allowable voltage to the user's chosen voltage.
float LTC3589_set_ldo2_output_voltage(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                      uint8_t register_address, //!< Address of the LTC3589 LDO2 FB reference register to be written.
                                      float output_voltage //!< New output voltage to set, in mV. Assumes a valid voltage for the feedback resistors.
                                     );

//! Sets the output voltage of any buck.
//! @return New buck output voltage, the closest allowable voltage to the user's chosen voltage.
float LTC3589_set_buck_output_voltage(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                      uint8_t register_address, //!< Address of the LTC3589 Buck FB reference register to be written.
                                      float output_voltage //!< New output voltage to set, in mV. Assumes a valid voltage for the feedback resistors.
                                     );

//! Writes the Feedback Reference Voltage of LDO2.
//! @return New Feedback Reference Input Voltage, the closest allowable voltage to the user's chosen voltage.
float LTC3589_set_ldo2_fb_ref(uint8_t i2c_address, //!< I2C address of the LTC3589.
                              uint8_t register_address, //!< Address of the LTC3589 LDO2 FB reference register to be written.
                              float fb_ref_voltage //!< New Feedback Reference voltage to set in mV.  Values between 362.5 and 750 are allowed.
                             );

//! Writes the Feedback Reference Voltage of any buck.
//! @return New Feedback Reference Input Voltage, the closest allowable voltage to the user's chosen voltage.
float LTC3589_set_buck_fb_ref(uint8_t i2c_address, //!< I2C address of the LTC3589.
                              uint8_t register_address, //!< Address of the LTC3589 Buck FB reference register to be written.
                              float fb_ref_voltage //!< New Feedback Reference voltage to set in mV.  Values between 362.5 and 750 are allowed.
                             );

//! Calculates the maximum output voltage of LDO2 in mV based on the feedback resistors.
//! @return Maximum possible output voltage for LDO2.
float LTC3589_ldo2_vout_max();

//! Calculates the minimum output voltage of LDO2 mV based on the feedback resistors.
//! @return Minimum possible output voltage for LDO2.
float LTC3589_ldo2_vout_min();

//! Calculates the maximum output voltage of any buck in mV based on the feedback resistors.
//! @return Maximum possible output voltage for the selected buck.
float LTC3589_buck_vout_max(uint8_t buck_number //!< Number (1-3) of buck.
                           );

//! Calculates the minimum output voltage of any buck in mV based on the feedback resistors.
//! @return Minimum possible output voltage for the selected buck.
float LTC3589_buck_vout_min(uint8_t buck_number //!< Number (1-3) of buck.
                           );

//! Selects the reference for LDO2.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_select_ldo2_reference(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                     int8_t ref_char //!< Reference to select (A or B).
                                    );

//! Selects the reference for the specified buck regulator(s).
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_select_buck_reference(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                     uint8_t buck_number, //!< Number (1-3) of the buck whose reference will be selected. Enter 0xFF for all bucks.
                                     int8_t ref_char //!< Reference to select (A or B).
                                    );

//! Sets the switching mode for the specified buck regulator(s).
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_buck_mode(uint8_t i2c_address, //!< I2C address of the LTC3589.
                             uint8_t buck_number, //!< Number (1-3) of the buck to set. Enter 0xFF for all bucks.
                             uint8_t mode //!< Switching mode to be set (0=pulse skipping, 1=burst, 2=forced continuous)
                            );

//! Sets the switching mode for the buck-boost regulator.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_buckboost_mode(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                  uint8_t mode //!< Switching mode to be set (0=pulse skipping, 1=burst, 2=forced continuous)
                                 );

//! Sets the start-up mode for all regulators.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_startup_mode(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                uint8_t startup_bit //!< Data to write to start-up bit (0=enable at any output, 1=enable only if output <300mV)
                               );

//! Sets the PGOOD mask bit for all bucks and LDO2.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_pgood_mask(uint8_t i2c_address, //!< I2C address of the LTC3589.
                              uint8_t pgood_bit //!< Data to write to PGOOD bit (0=PGOOD low when slewing, 1=PGOOD not forced low when slewing)
                             );

//! Sets LDO4 output voltage on the LTC3589.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_ldo4_voltage(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                uint8_t ldo4_output_voltage_code //!< Voltage code for new LDO4 output voltage (varies by part option).
                               );

//! Sets the dynamnic reference slew rate for the regulator(s).
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_regulator_slew(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                  uint8_t regulator_mask, //!< Mask of the regulator to set. Enter 0xFF for all regulators.
                                  uint8_t slew_rate //!< Slew rate code to set.
                                 );

//! Sets the switch DV/DT control for the buck regulators.
//! @return State of the acknowledge bit after the I2C addresss write. 0=acknowledge, 1=no acknowledge.
int8_t LTC3589_set_switch_dvdt_control(uint8_t i2c_address, //!< I2C address of the LTC3589.
                                       uint8_t dvdt_control_bits //!< Two-bit DV/DT control code to set.
                                      );

//! Sets all of the GO bits in the VCCR register.
int8_t LTC3589_set_go_bits(uint8_t i2c_address //!< I2C address of the LTC3589.
                          );

Download LTC3589 Linduino.CPP

/*!
LTC3589: 8-Output Regulator with Sequencing and I2C

@verbatim

The LTC3589 is a complete power management solution for ARM and ARM-based
processors and advanced portable microprocessor systems. The device contains
three step-down DC/DC converters for core, memory and SoC rails, a
buck-boost regulator for I/O at 1.8V to 5V and three 250mA LDO regulators
for low noise analog supplies. An I2C serial port is used to control enables,
output voltage levels, dynamic voltage scaling, operating modes and status
reporting.
Regulator start-up is sequenced by connecting outputs to enable pins in the
desired order or programmed via the I2C port. System power-on, power-off,
and reset functions are controlled by pushbutton interface, pin inputs, or
I2C interface.
The LTC3589 supports i.MX53/51, PXA and OMAP processors with eight
independent rails at appropriate power levels. Other features include
interface signals such as the VSTB pin that simultaneously toggle up to
four rails between programmed run and standby output voltages.  The device
is available in a low profile 40-pin 6mm x 6mm exposed pad QFN package.

I2C DATA FORMAT (MSB FIRST)

@endverbatim

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

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

REVISION HISTORY
$Revision: 5045 $
$Date: 2015-03-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.
*/

//! @defgroup LTC3589 LTC3589: 8-Output Regulator with Sequencing and I2C

/*! @file
    @ingroup LTC3589
    Library for LTC3589: 8-Output Regulator with Sequencing and I2C
*/

#include <Arduino.h>
#include <stdint.h>
#include <math.h>
#include "Linduino.h"
#include "LT_I2C.h"
#include "LTC3589.h"

// Reads an 8-bit register from the LTC3589 using the standard repeated start format.
int8_t LTC3589_register_read(uint8_t i2c_address, uint8_t register_address, uint8_t *register_data)
{
  int8_t ack = 0;
  ack = i2c_read_byte_data(i2c_address, register_address, register_data);
  return(ack);
}

// Writes to an 8-bit register inside the LTC3589 using the standard I2C repeated start format.
int8_t LTC3589_register_write(uint8_t i2c_address, uint8_t register_address, uint8_t register_data)
{
  int8_t ack = 0;
  ack = i2c_write_byte_data(i2c_address, register_address, register_data);
  return(ack);
}

// Sets any bit inside the LTC3589 using the standard I2C repeated start format.
int8_t LTC3589_bit_set(uint8_t i2c_address, uint8_t register_address, uint8_t bit_number)
{
  uint8_t register_data;
  uint8_t bit_mask;
  int8_t ack = 0;
  bit_mask = 0x01 << bit_number;
  ack |= LTC3589_register_read(i2c_address, register_address, &register_data);  //Read register
  register_data = register_data | bit_mask;  //Set the bit at bit_address
  ack |= LTC3589_register_write(i2c_address, register_address, register_data);  //Write new data to register
  return(ack);
}

// Clears any bit inside the LTC3589 using the standard I2C repeated start format.
int8_t LTC3589_bit_clear(uint8_t i2c_address, uint8_t register_address, uint8_t bit_number)
{
  uint8_t register_data;
  uint8_t bit_mask;
  int8_t ack = 0;
  bit_mask = 0x01 << bit_number;
  ack |= LTC3589_register_read(i2c_address, register_address, &register_data);  //Read register
  register_data = register_data & (~bit_mask);  //Clears the bit at bit_address
  ack |= LTC3589_register_write(i2c_address, register_address, register_data);  //Write new data to register
  return(ack);
}

// Writes any bit inside the LTC3589 using the standard I2C repeated start format.
int8_t LTC3589_bit_write(uint8_t i2c_address, uint8_t register_address, uint8_t bit_number, uint8_t bit_data)
{
  uint8_t register_data;
  uint8_t bit_mask;
  int8_t ack = 0;
  bit_mask = 0x01 << bit_number;
  ack |= LTC3589_register_read(i2c_address, register_address, &register_data);  //Read register
  register_data = register_data & (~bit_mask);  //Clears the bit at bit_address
  register_data = register_data | ((bit_data & 0x01) << bit_number);  //Writes the new bit
  ack |= LTC3589_register_write(i2c_address, register_address, register_data);  //Write new data to register
  return(ack);
}

// Reads the value of any bit in any register or the LTC3589.
uint8_t LTC3589_bit_is_set(uint8_t i2c_address, uint8_t register_address, uint8_t bit_number)
{
  uint8_t register_data;
  int8_t ack = 0;
  ack |= LTC3589_register_read(i2c_address, register_address, &register_data);
  register_data = register_data >> bit_number;  //Clears everything but the bit of interest
  return (register_data & 0x01);
}


// Sets the output voltage of LDO2.
float LTC3589_set_ldo2_output_voltage(uint8_t i2c_address, uint8_t register_address, float output_voltage)
{
  uint8_t register_data;
  float fb_ref = 0;
  int8_t nack = 0;
  if (register_address == 0x32 | register_address == 0x33)
  {
    fb_ref = output_voltage / (1 + LTC3589_RES_LDO2_RTOP/LTC3589_RES_LDO2_RBOT);  //Generates desired FB reference input for given output voltage.
    return (1 + LTC3589_RES_LDO2_RTOP/LTC3589_RES_LDO2_RBOT) * LTC3589_set_ldo2_fb_ref(i2c_address, register_address, fb_ref);  //Writes new buck output fb refernce.
  }
}

// Sets the output voltage of any buck.
float LTC3589_set_buck_output_voltage(uint8_t i2c_address, uint8_t register_address, float output_voltage)
{
  uint8_t register_data;
  float fb_ref = 0;
  int8_t nack = 0;
  if (register_address == 0x23 | register_address == 0x24)
  {
    fb_ref = output_voltage / (1 + LTC3589_RES_BUCK1_RTOP/LTC3589_RES_BUCK1_RBOT);  //Generates desired FB reference input for given output voltage.
    return (1 + LTC3589_RES_BUCK1_RTOP/LTC3589_RES_BUCK1_RBOT) * LTC3589_set_buck_fb_ref(i2c_address, register_address, fb_ref);  //Writes new buck output fb refernce.
  }
  if (register_address == 0x26 | register_address == 0x27)
  {
    fb_ref = output_voltage / (1 + LTC3589_RES_BUCK2_RTOP/LTC3589_RES_BUCK2_RBOT);  //Generates desired FB reference input for given output voltage.
    return (1 + LTC3589_RES_BUCK2_RTOP/LTC3589_RES_BUCK2_RBOT) * LTC3589_set_buck_fb_ref(i2c_address, register_address, fb_ref);  //Writes new buck output fb refernce.
  }
  if (register_address == 0x29 | register_address == 0x2A)
  {
    fb_ref = output_voltage / (1 + LTC3589_RES_BUCK3_RTOP/LTC3589_RES_BUCK3_RBOT);  //Generates desired FB reference input for given output voltage.
    return (1 + LTC3589_RES_BUCK3_RTOP/LTC3589_RES_BUCK3_RBOT) * LTC3589_set_buck_fb_ref(i2c_address, register_address, fb_ref);  //Writes new buck output fb refernce.
  }
}

// Writes the Feedback Reference Voltage of LDO2.
float LTC3589_set_ldo2_fb_ref(uint8_t i2c_address, uint8_t register_address, float fb_ref_voltage)
{
  uint8_t register_data;
  uint8_t fb_ref_data = 0;
  int8_t nack = 0;
  fb_ref_data = (uint8_t) ((fb_ref_voltage + 6.25 - 362.5) / 12.5);  //Generates 5-bit code for closest allowable value to user's chosen reference voltage.
  nack |= LTC3589_register_read(i2c_address, register_address, &register_data); //Read current register value
  register_data = register_data & (~LTC3589_FB_REF_MASK); //Clears existing feedback reference bits
  register_data = register_data | fb_ref_data;
  nack |= LTC3589_register_write(i2c_address, register_address, register_data);  //Writes new register value
  nack |= LTC3589_set_go_bits(i2c_address);
  return (362.5 + (fb_ref_data * 12.5));
}

// Writes the Feedback Reference Voltage of any buck.
float LTC3589_set_buck_fb_ref(uint8_t i2c_address, uint8_t register_address, float fb_ref_voltage)
{
  uint8_t register_data;
  uint8_t fb_ref_data = 0;
  int8_t nack = 0;
  fb_ref_data = (uint8_t) ((fb_ref_voltage + 6.25 - 362.5) / 12.5);  //Generates 5-bit code for closest allowable value to user's chosen reference voltage.
  nack |= LTC3589_register_read(i2c_address, register_address, &register_data); //Read current register value
  register_data = register_data & (~LTC3589_FB_REF_MASK); //Clears existing feedback reference bits
  register_data = register_data | fb_ref_data;
  nack |= LTC3589_register_write(i2c_address, register_address, register_data);  //Writes new register value
  nack |= LTC3589_set_go_bits(i2c_address);
  return (362.5 + (fb_ref_data * 12.5));
}

// Calculates the maximum output voltage of LDO2 in mV based on the feedback resistors.
float LTC3589_ldo2_vout_max()
{
  return ((1 + (LTC3589_RES_LDO2_RTOP/LTC3589_RES_LDO2_RBOT)) * 750);
}

// Calculates the minimum output voltage of LDO2 mV based on the feedback resistors.
float LTC3589_ldo2_vout_min()
{
  return ((1 + (LTC3589_RES_LDO2_RTOP/LTC3589_RES_LDO2_RBOT)) * 362.5);
}

// Calculates the maximum output voltage of any buck in mV based on the feedback resistors.
float LTC3589_buck_vout_max(uint8_t buck_number)
{
  switch (buck_number)
  {
    case 1:
      return ((1 + (LTC3589_RES_BUCK1_RTOP/LTC3589_RES_BUCK1_RBOT)) * 750);
      break;
    case 2:
      return ((1 + (LTC3589_RES_BUCK2_RTOP/LTC3589_RES_BUCK2_RBOT)) * 750);
      break;
    case 3:
      return ((1 + (LTC3589_RES_BUCK3_RTOP/LTC3589_RES_BUCK3_RBOT)) * 750);
      break;
  }
}

// Calculates the minimum output voltage of any buck in mV based on the feedback resistors.
float LTC3589_buck_vout_min(uint8_t buck_number)
{
  switch (buck_number)
  {
    case 1:
      return ((1 + LTC3589_RES_BUCK1_RTOP/LTC3589_RES_BUCK1_RBOT) * 362.5);
      break;
    case 2:
      return ((1 + LTC3589_RES_BUCK2_RTOP/LTC3589_RES_BUCK2_RBOT) * 362.5);
      break;
    case 3:
      return ((1 + LTC3589_RES_BUCK3_RTOP/LTC3589_RES_BUCK3_RBOT) * 362.5);
      break;
  }
}

// Selects the reference for LDO2.
int8_t LTC3589_select_ldo2_reference(uint8_t i2c_address, int8_t ref_char)
{
  int8_t ack = 0;
  if (ref_char == '1')
    ack |= LTC3589_bit_clear(i2c_address, LTC3589_REG_VCCR, LTC3589_LDO2_REF_SELECT);
  else if (ref_char == '2')
    ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, LTC3589_LDO2_REF_SELECT);
  ack |= LTC3589_set_go_bits(i2c_address);
  return(ack);
}

// Selects the reference for the specified buck regulator(s).
int8_t LTC3589_select_buck_reference(uint8_t i2c_address, uint8_t buck_number, int8_t ref_char)
{
  int8_t ack = 0;
  if (buck_number == 0xFF)
  {
    ack |= LTC3589_select_buck_reference(i2c_address, 1, ref_char);
    ack |= LTC3589_select_buck_reference(i2c_address, 2, ref_char);
    ack |= LTC3589_select_buck_reference(i2c_address, 3, ref_char);
    return(ack);
  }
  if (ref_char == '1')
    ack |= LTC3589_bit_clear(i2c_address, LTC3589_REG_VCCR, (buck_number*2)-1);
  else if (ref_char == '2')
    ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, (buck_number*2)-1);
  ack |= LTC3589_set_go_bits(i2c_address);
  return(ack);
}

// Sets the switching mode for the specified buck regulator(s).
int8_t LTC3589_set_buck_mode(uint8_t i2c_address, uint8_t buck_number, uint8_t mode)
{
  uint8_t register_data;
  int8_t ack = 0;
  if (buck_number == 0xFF)
  {
    ack |= LTC3589_set_buck_mode(i2c_address, 0x01, mode);
    ack |= LTC3589_set_buck_mode(i2c_address, 0x02, mode);
    ack |= LTC3589_set_buck_mode(i2c_address, 0x03, mode);
    return(ack);
  }
  ack |= LTC3589_register_read(i2c_address, LTC3589_REG_SCR1, &register_data);  //Read register
  register_data = register_data & (~LTC3589_BUCK_MODE_MASK(buck_number));  //Clears the Mode bits in the Buck register
  register_data = register_data | (mode << ((buck_number*2)-2));
  ack |= LTC3589_register_write(i2c_address, LTC3589_REG_SCR1, register_data);  //Writes new register value
  return(ack);
}

// Sets the switching mode for the buck-boost regulator.
int8_t LTC3589_set_buckboost_mode(uint8_t i2c_address, uint8_t mode)
{
  uint8_t register_data;
  int8_t ack = 0;
  ack |= LTC3589_bit_write(i2c_address, LTC3589_REG_SCR1, LTC3589_BUCKBOOST_MODE, mode);  //Writes new mode-bit value
  return(ack);
}

// Sets the start-up mode for all regulators.
int8_t LTC3589_set_startup_mode(uint8_t i2c_address, uint8_t startup_bit)
{
  int8_t ack = 0;
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_BUCK1_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_BUCK2_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_BUCK3_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_BB_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_LDO2_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_LDO3_STARTUP, startup_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_SCR2, LTC3589_LDO4_STARTUP, startup_bit);
  return(ack);
}

// Sets the PGOOD mask bit for all bucks and LDO2.
int8_t LTC3589_set_pgood_mask(uint8_t i2c_address, uint8_t pgood_bit)
{
  int8_t ack = 0;
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_B1DTV1, LTC3589_BUCK_PG_MASK, pgood_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_B2DTV1, LTC3589_BUCK_PG_MASK, pgood_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_B3DTV1, LTC3589_BUCK_PG_MASK, pgood_bit);
  ack |= LTC3589_bit_write(LTC3589_I2C_ADDRESS, LTC3589_REG_L2DTV1, LTC3589_LDO2_PG_MASK, pgood_bit);
  return(ack);
}

// Sets LDO4 output voltage on the LTC3589.
int8_t LTC3589_set_ldo4_voltage(uint8_t i2c_address, uint8_t ldo4_output_voltage_code)
{
  int8_t ack = 0;
  uint8_t register_data;
  ack |= LTC3589_register_read(i2c_address, LTC3589_REG_L2DTV2, &register_data);  //Read register
  register_data = register_data & (~LTC3589_LDO4_VOLTAGE_MASK);  //Clears the LDO4 Output Voltage bits in the L2DTV2 register
  register_data = register_data | (ldo4_output_voltage_code << 5);
  ack |= LTC3589_register_write(i2c_address, LTC3589_REG_L2DTV2, register_data);  //Writes new register value
  return(ack);
}

// Sets the dynamic reference slew rate for the regulator(s).
int8_t LTC3589_set_regulator_slew(uint8_t i2c_address, uint8_t regulator_mask, uint8_t slew_rate)
{
  uint8_t register_data;
  uint8_t bit_shift = log(regulator_mask/3) / log(2);
  int8_t ack = 0;
  if (regulator_mask == 0xFF)
  {
    ack |= LTC3589_set_regulator_slew(i2c_address, LTC3589_BUCK1_SLEW_MASK, slew_rate);
    ack |= LTC3589_set_regulator_slew(i2c_address, LTC3589_BUCK2_SLEW_MASK, slew_rate);
    ack |= LTC3589_set_regulator_slew(i2c_address, LTC3589_BUCK3_SLEW_MASK, slew_rate);
    ack |= LTC3589_set_regulator_slew(i2c_address, LTC3589_LDO2_SLEW_MASK, slew_rate);
    return(ack);
  }
  ack |= LTC3589_register_read(i2c_address, LTC3589_REG_VRRCR, &register_data);  //Read register
  register_data = register_data & (~regulator_mask);  //Clears the Mode bits in the Buck register
  register_data = register_data | (slew_rate << bit_shift);
  ack |= LTC3589_register_write(i2c_address, LTC3589_REG_VRRCR, register_data);  //Writes new register value
  return(ack);
}

// Sets the switch DV/DT control for the buck regulators.
int8_t LTC3589_set_switch_dvdt_control(uint8_t i2c_address, uint8_t dvdt_control_bits)
{
  uint8_t register_data;
  int8_t ack = 0;
  ack |= LTC3589_register_read(i2c_address, LTC3589_REG_B1DTV1, &register_data);
  register_data = register_data & (~LTC3589_BUCK_DVDT_MASK);
  register_data = register_data | (dvdt_control_bits << 6);
  ack |= LTC3589_register_write(i2c_address, LTC3589_REG_B1DTV1, register_data);
  return(ack);
}

// Sets all four GO bits in the VCCR register.
int8_t LTC3589_set_go_bits(uint8_t i2c_address)
{
  int8_t ack = 0;
  ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, LTC3589_BUCK1_GO);
  ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, LTC3589_BUCK2_GO);
  ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, LTC3589_BUCK3_GO);
  ack |= LTC3589_bit_set(i2c_address, LTC3589_REG_VCCR, LTC3589_LDO2_GO);
  return(ack);
}

Technical Support