LTC2484 - 24-Bit ΔΣ ADC with Easy Drive Input Current Cancellation

Features

  • Easy Drive Technology Enables Rail-to-Rail Inputs with Zero Differential Input Current
  • Directly Digitizes High Impedance Sensors with Full Accuracy
  • 600nVRMS Noise
  • GND to VCC Input/Reference Common Mode Range
  • Programmable 50Hz, 60Hz or Simultaneous
  •  /60Hz Rejection Mode
  • 2ppm INL, No Missing Codes
  • 1ppm Offset and 15ppm Total Unadjusted Error
  • Selectable 2× Speed Mode (15Hz Using Internal Oscillator)
  • No Latency: Digital Filter Settles in a Single Cycle
  • Single Supply 2.7V to 5.5V Operation
  • Internal Oscillator
  • Available in a Tiny (3mm × 3mm) 10-Lead DFN Package
Designed for Automotive and Transportation Applications
AEC-Q100 generic family data available for specific packages


Typical Application

LTC2484 Typical Application
LTC2484 Typical Application

Description

The LTC®2484 combines a 24-bit No Latency ΔΣ™ analogto- digital converter with patented Easy Drive™ technology. The patented sampling scheme eliminates dynamic input current errors and the shortcomings of on-chip buffering through automatic cancellation of differential input current. This allows large external source impedances and input signals with rail-to-rail input range to be directly digitized while maintaining exceptional DC accuracy.

The LTC2484 includes an on-chip oscillator. The LTC2484 can be configured to reject line frequencies. 50Hz, 60Hz or simultaneous 50Hz/60Hz line frequency rejection can be selected as well as a 2× speed-up mode.

The LTC2484 allows a wide common mode input range (0V to VCC) independent of the reference voltage. The reference can be as low as 100mV or can be tied directly to VCC. The LTC2484 includes an on-chip trimmed oscillator, eliminating the need for external crystals or oscillators. Absolute accuracy and low drift are automatically maintained through continuous, transparent, offset and full-scale calibration.

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
LTC2484CDD#PBF 3x3 DFN-10 DD C 05-08-1699 Yes
LTC2484CDD#TRPBF 3x3 DFN-10 DD C 05-08-1699 Yes
LTC2484IDD#PBF 3x3 DFN-10 DD I 05-08-1699 Yes
LTC2484IDD#TRPBF 3x3 DFN-10 DD I 05-08-1699 Yes


LTC2484 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
LTC2484CDD#PBF 3x3 DFN-10 C $3.50 $2.45 Yes
LTC2484CDD#TRPBF 3x3 DFN-10 C $2.51 Yes
LTC2484IDD#PBF 3x3 DFN-10 I $4.20 $2.94 Yes
LTC2484IDD#TRPBF 3x3 DFN-10 I $3.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
DC2126A High-Accuracy Wireless Temperature Sensor with Solar Battery Life Extender $175.00
DC939A LTC2484IDD Demo Board | 24-Bit Delta Sigma ADC w/Temp (req. DC2026) $50.00
Buy Now

Companion Boards

Part Number Description Price Documentation
DC9006A Eterna Interface Card $100.00
DC9010B Eterna Serial Programmer $399.00
DC9021B SmartMesh IP Starter Kit $750.00
DC2026C Linduino One Isolated USB Demo Board: An Arduino- and QuikEval-Compatible Code Development Platform $75.00
Buy Now
Click here to view our complete list of demo boards

Designed for Automotive and Transportation Applications

Please contact your local sales representative for more information regarding reliability reports and AEC-Q100 data or to inquire about parts that are not included. For more information, view our Automotive and Transportation page

Part Number Package Temp Price
(1-99)
Price
(1k)*
RoHS
LTC2484IDD#PBF 3x3 DFN-10 I $4.20 $2.94 Yes
LTC2484IDD#TRPBF 3x3 DFN-10 I $3.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.

Applications

  • Direct Sensor Digitizer
  • Weight Scales
  • Direct Temperature Measurement
  • Strain Gauge Transducers
  • Instrumentation
  • Industrial Process Control
  • DVMs and Meters

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 LTC2484 - DC939A Linduino .INO File

/*!
Linear Technology DC939A Demonstration Board.
LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation.

@verbatim

NOTES
  Setup:
   Set the terminal baud rate to 115200 and select the newline terminator. Equipment
   required is a precision voltage source and a precision voltmeter. No external
   power supply is required. Ensure JP1 is in the +5V position.

  To Read data:
   The voltage source should be connected with positive lead to IN+ and negative
   lead to IN-. The voltage source negative output must also be connected to the GND
   pin in order to provide a ground-referenced voltage. Ensure voltage is within
   analog input voltage range -0.3V to +2.5V. Swapping input voltages results in a 
   reversed polarity reading.

  How to calibrate:
    Short the inputs to ground to calibrate the offset. Next, hit ENTER (this takes
    the reading). Now apply approximately 2.49 volts to +IN, with -IN connected to
    ground. Measure this voltage with a precise voltmeter and enter this value.
    Calibration is now stored in EEPROM. Upon startup the calibration values will be
    restored.

    Explanation of Commands:

                           **** MAIN MENU ****

      0- Read- By entering this a voltage at the +IN, -IN terminals will be read.
      1- Set Rejection- Select this to access the Filter rejection menu. Follow
         command cues to enable desired rejection profile of on-chip digital filters.
      2- Select 2X Rate- This selection allows disabling of the autocalibration
         feature to achieve a benefit of twice the output rate.
      3- Calibrate Voltage- Follow the calibration cues to calibrate the device
         voltage.
      4- Calibrate Temperature- Select this and follow the cues if it is desired to
         calibrate the integrated
         temperature sensor.

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

@endverbatim

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

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

REVISION HISTORY
$Revision: 2315 $
$Date: 2014-03-31 13:05:50 -0700 (Mon, 31 Mar 2014) $

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 LTC2484
*/

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

// Rejection Constants
#define REJECTION50_60  0               //!< 50-60Hz rejection
#define REJECTION50     1               //!< 50Hz rejection
#define REJECTION60     2               //!< 60Hz rejection

// Function Declaration
void print_title();                             // Print the title block
void print_prompt();                            // Prompt the user for an input command
int8_t restore_calibration();                   // Read the DAC calibration from EEPROM, Return 1 if successful, 0 if not
void store_calibration();                       // Store the ADC calibration to the EEPROM
uint8_t build_adc_command(uint8_t temperature); // Build the ADC command byte

uint8_t menu_0_read();
void menu_1_set_rejection();
void menu_2_set_1X_2X();
uint8_t menu_3_calibrate_voltage();
uint8_t menu_4_calibrate_temperature();

// Global variables
static uint8_t demo_board_connected;            //!< Set to 1 if the board is connected
static int8_t  adc_rejection = REJECTION50_60;  //!< The LTC2484 rejection
static int8_t  adc_2x = 0;                      //!< The LTC2484 2x speed mode

// Calibration variables
static float LTC2484_lsb = 9.3132258E-9;  //!< Ideal LSB size, 5V/(2^29) for a 5V reference
static int32_t LTC2484_offset_code = 0;   //!< Ideal offset
static float LTC2484_t0 = 27.0;           //!< Nominal temperature
static float LTC2484_r0 = 45.097156E6;    //!< ADC code at the nominal temperature (420mV default)

const uint16_t MISO_TIMEOUT = 1000;       //!< The MISO timeout (ms)

//! Initialize Linduino
void setup()
// Setup the program
{
  char demo_name[] = "DC939";   // Demo Board Name stored in QuikEval EEPROM

  quikeval_SPI_init();          // Configure the spi port for 4MHz SCK
  quikeval_SPI_connect();       // Connect SPI to main data port
  quikeval_I2C_init();          // Configure the EEPROM I2C port for 100kHz
  Serial.begin(115200);         // Initialize the serial port to the PC
  print_title();
  demo_board_connected = discover_demo_board(demo_name);
  if (demo_board_connected)
  {
    restore_calibration();
    print_prompt();
  }
}

//! Repeats Linduino loop
void loop()
{
  uint8_t user_command;             // The user input command
  uint8_t acknowledge = 0; 
  if (demo_board_connected)
  {
    if (Serial.available())         // Check for user input
    {
      user_command = read_int();    // Read the user command
      if (user_command == 'm');
      else
        Serial.println(user_command);
      delay(50);                    // Allow the print to finish
      switch (user_command)
      {
        case 0:
          acknowledge |= menu_0_read();
          break;
        case 1:
          menu_1_set_rejection();
          break;
        case 2:
          menu_2_set_1X_2X();
          break;
        case 3:
          acknowledge |= menu_3_calibrate_voltage();
          break;
        case 4:
          acknowledge |= menu_4_calibrate_temperature();
          break;
        default:
          Serial.println("Incorrect Option");
          break;
      }
      if(acknowledge)
        Serial.println(F("***** SPI ERROR *****"));
      Serial.println(F("*****************************************************************"));
      print_prompt();
    }
  }
}

// Function Definitions

//! Prints the title block when program first starts.
void print_title()
{
  Serial.println();
  Serial.println(F("*****************************************************************"));
  Serial.println(F("* DC939A Demonstration Program                                  *"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("* This program demonstrates how to send data and receive data   *"));
  Serial.println(F("* from the 24-bit delta-sigma ADC.                              *"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("* Set the baud rate to 115200 select the newline terminator.    *"));
  Serial.println(F("*                                                               *"));
  Serial.println(F("*****************************************************************"));
}

//! Prints main menu.
void print_prompt()
{
  Serial.println(F("\nPresent Values:"));
  Serial.print(F("  Rejection: "));
  switch (adc_rejection)
  {
    case REJECTION50_60:
      Serial.println(F("50-60Hz rejection"));
      break;
    case REJECTION50:
      Serial.println(F("50Hz rejection"));
      break;
    case REJECTION60:
      Serial.println(F("60Hz rejection"));
      break;
  }
  Serial.print(F("  2X Speed: "));
  Serial.println(adc_2x, DEC);
  Serial.print(F("  Offset Code="));
  Serial.println(LTC2484_offset_code);
  Serial.print(F("  LSB="));
  Serial.print(LTC2484_lsb * 1.0e9, 4);
  Serial.println(F("nV (32-bits)"));
  Serial.print(F("  R0="));
  Serial.println(LTC2484_r0, 0);
  Serial.print(F("  T0="));
  Serial.print(LTC2484_t0, 1);
  Serial.println(F("C"));
  Serial.println();
  Serial.println(F("Command Summary:"));
  Serial.println(F("  0-Read"));
  Serial.println(F("  1-Set Rejection"));
  Serial.println(F("  2-Set 2X Speed"));
  Serial.println(F("  3-Calibrate Voltage"));
  Serial.println(F("  4-Calibrate Temperature"));
  Serial.println();
  Serial.print(F("Enter a command:"));
}

//! Read stored calibration parameters from nonvolatile EEPROM on demo board
//! @return 0 if successful, 1 if failure
int8_t restore_calibration()
// Read the DAC calibration from EEPROM
{
  int16_t cal_key;
  // Read the cal key from the EEPROM
  eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
  if (cal_key == EEPROM_CAL_KEY)
  {
    // Calibration has been stored, read offset and lsb
    eeprom_read_int32(EEPROM_I2C_ADDRESS, &LTC2484_offset_code, EEPROM_CAL_STATUS_ADDRESS + 2);  // Offset
    eeprom_read_float(EEPROM_I2C_ADDRESS, &LTC2484_lsb, EEPROM_CAL_STATUS_ADDRESS + 6);          // LSB
    eeprom_read_float(EEPROM_I2C_ADDRESS, &LTC2484_r0, EEPROM_CAL_STATUS_ADDRESS + 10);          // Temp r0
    eeprom_read_float(EEPROM_I2C_ADDRESS, &LTC2484_t0, EEPROM_CAL_STATUS_ADDRESS + 14);          // Temp t0
    Serial.println(F("Calibration Restored"));
    return (1);
  }
  else
  {
    Serial.println(F("Calibration not found"));
    return (0);
  }
}

//! Store measured calibration parameters to nonvolatile EEPROM on demo board
void store_calibration()
// Store the ADC calibration to the EEPROM
{
  eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS);           // Cal key
  eeprom_write_int32(EEPROM_I2C_ADDRESS, LTC2484_offset_code, EEPROM_CAL_STATUS_ADDRESS + 2);  // Offset
  eeprom_write_float(EEPROM_I2C_ADDRESS, LTC2484_lsb, EEPROM_CAL_STATUS_ADDRESS + 6);          // LSB
  eeprom_write_float(EEPROM_I2C_ADDRESS, LTC2484_r0, EEPROM_CAL_STATUS_ADDRESS + 10);          // Temp r0
  eeprom_write_float(EEPROM_I2C_ADDRESS, LTC2484_t0, EEPROM_CAL_STATUS_ADDRESS + 14);          // Temp t0
  Serial.println(F("Calibration Stored to EEPROM"));
}

//! Construct ADC command from rejection, input, and 2X parameters
//! @return ADC command
uint8_t build_adc_command(uint8_t temperature)
// Build the ADC command byte
{
  uint8_t adc_command = 0;          // The LTC2484 command byte
  adc_command = LTC2484_ENABLE;     // Set ENABLE
  switch (adc_rejection)
  {
    case REJECTION50_60:                            // Set REJECTION
      adc_command |= LTC2484_REJECTION_50HZ_60HZ;
      break;
    case REJECTION50:
      adc_command |= LTC2484_REJECTION_50HZ;
      break;
    case REJECTION60:
      adc_command |= LTC2484_REJECTION_60HZ;
      break;
  }
  if (temperature)                                  // Set Temperature Input
  {
    adc_command |= LTC2484_TEMPERATURE_INPUT;
    adc_command |= LTC2484_AUTO_CALIBRATION;
  }
  else
  {
    adc_command |= LTC2484_EXTERNAL_INPUT;          // Set Voltage Input
    if (adc_2x)
      adc_command |= LTC2484_SPEED_2X;              // Set 2X Speed
    else
      adc_command |= LTC2484_AUTO_CALIBRATION;
  }
  return(adc_command);
}

//! Read ADC
//! @return 0 if successful, 1 if failure
uint8_t menu_0_read()
{
  // Read values
  int32_t adc_code = 0;     // The LTC2484 code
  float adc_voltage = 0.0;  // The LTC2484 input voltage
  float adc_temperature;    // The LTC2484 temperature sensor value
  uint8_t adc_command;      // The LTC2484 command byte

  adc_command = build_adc_command(0);                       // Build ADC command byte for voltage input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Throw away last reading
  adc_command = build_adc_command(1);                       // Build ADC command byte for temperature input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Read voltage
  Serial.println(F("\nVoltage Measurement"));
  Serial.print(F("  Received Code: 0x"));
  Serial.println(adc_code, HEX);
  Serial.print(F("  Voltage:"));
  adc_voltage = LTC2484_code_to_voltage(adc_code, LTC2484_lsb, LTC2484_offset_code);
  Serial.print(adc_voltage, 6);
  Serial.println(F("V "));
  adc_command = build_adc_command(1);                       // Build ADC command byte for voltage input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Read temperature
  Serial.println(F("\nTemperature Measurement"));
  Serial.print(F("  Received Code: 0x"));
  Serial.println(adc_code, HEX);
  Serial.print(F("  Sensor Voltage:"));
  adc_voltage = LTC2484_code_to_voltage(adc_code, LTC2484_lsb, LTC2484_offset_code);
  Serial.print(adc_voltage, 6);
  Serial.println(F("V"));
  Serial.print(F("  Temperature:"));
  adc_temperature = LTC2484_temperature(adc_code, LTC2484_t0, LTC2484_r0);
  Serial.print(adc_temperature, 1);
  Serial.println(F("C\n"));
  return(0);
}

//! Set rejection mode
void menu_1_set_rejection()
{
  uint8_t user_command; // The user input command

  // Set rejection
  Serial.println(F("Rejection :"));
  Serial.println(F("  0: 50-60Hz rejection"));
  Serial.println(F("  1: 50Hz rejection"));
  Serial.println(F("  2: 60Hz rejection"));
  Serial.println();
  Serial.print(F("Select Rejection:"));
  user_command = read_int();                              // Read the user command
  Serial.println(user_command);
  switch (user_command)
  {
    case 1:
      adc_rejection = REJECTION50;
      break;
    case 2:
      adc_rejection = REJECTION60;
      break;
    default:
      adc_rejection = REJECTION50_60;
      break;
  }
}

//! Select 1X or 2X mode
void menu_2_set_1X_2X()
{
  // Set 2X rate
  uint8_t user_command; // The user input command

  Serial.println();
  Serial.print(F("Select 2X Rate (0-OFF, 1-ON): "));
  user_command = read_int();                              // Read the user command
  Serial.println(user_command);
  switch (user_command)
  {
    case 0:
      adc_2x = 0;
      break;
    case 1:
      adc_2x = 1;
      break;
    default:
      adc_2x = 0;
      break;
  }
}

//! Calibrate ADC given two known inputs
//! @return 0 if successful, 1 if failure
uint8_t menu_3_calibrate_voltage()
{
  // Calibrate voltage measurement
  float zero_voltage;       // Measured cal voltage
  float fs_voltage;         // Measured cal voltage
  int32_t zero_code;        // Cal zero code
  int32_t fs_code;          // Cal full scale code
  uint8_t user_command;     // The user input command
  int32_t adc_code = 0;     // The LTC2484 code
  uint8_t adc_command;      // The LTC2484 command byte

  Serial.println(F("Short the inputs to ground calibrate the offset."));
  Serial.println(F("or apply a voltage for the lower point in two point calibration"));
  Serial.print(F("Enter the measured input voltage:"));
  zero_voltage = read_float();
  Serial.println(zero_voltage, 6);
  
  adc_command = build_adc_command(0);                       // Build ADC command byte for voltage input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Throw away previous reading
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &zero_code);        // Measure zero
  
  Serial.println(F("Apply ~2.40V to +IN"));
  Serial.println(F("Enter the measured input voltage:"));
  fs_voltage = read_float();
  
  adc_command = build_adc_command(0);                       // Build ADC command byte for voltage input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Throw away previous reading
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &fs_code);          // Measure full scale
  
  LTC2484_cal_voltage(zero_code, fs_code, zero_voltage, fs_voltage, &LTC2484_lsb, &LTC2484_offset_code);
  
  Serial.print(F("ADC offset : "));
  Serial.print(LTC2484_offset_code);
  Serial.print(F(" ADC lsb : "));
  Serial.print(LTC2484_lsb * 1.0e9, 4);
  Serial.println(F("nV (32-bits)"));
  store_calibration();
  return(0);
}

//! Calibrate Temperature given two known inputs
//! @return 0 if successful, 1 if failure
uint8_t menu_4_calibrate_temperature()
{
  float adc_cal_temperature;    // Measured cal temperature
  int32_t adc_code = 0;         // The LTC2484 code
  uint8_t adc_command;          // The LTC2484 command byte

  Serial.println(F("Enter the actual temperature(C):"));
  adc_cal_temperature = read_float();
  adc_command = build_adc_command(1);                       // Build ADC command byte for temperature input
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Throw away previous reading
  if(LTC2484_EOC_timeout(LTC2484_CS, MISO_TIMEOUT))         // Check for EOC
    return(1);
  LTC2484_read(LTC2484_CS, adc_command, &adc_code);         // Measure temperature
  LTC2484_cal_temperature(adc_code, adc_cal_temperature, &LTC2484_t0, &LTC2484_r0);  // Cal temperature
  store_calibration();                                      // Store to eeprom
  return(0);
}

Download LTC2484 Linduino .CPP File

//! @todo Review this file.
/*!
LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation

@verbatim

The LTC2484 combines a 24-bit no latency delta-sigma analog-to-digital 
converter with patented Easy Drive technology. The patented sampling scheme 
eliminates dynamic input current errors and the shortcomings of on-chip 
buffering through automatic cancellation of differential input current. This 
allows large external source impedances and input signals with rail-to-rail 
input range to be directly digitized while maintaining exceptional DC accuracy. 

The LTC2484 includes an on-chip oscillator. The LTC2484 can be configured to 
reject line frequencies. 50Hz, 60Hz or simultaneous 50Hz/60Hz line frequency 
rejection can be selected as well as a 2x speed-up mode. 

The LTC2484 allows a wide common mode input range (0V to VCC) independent of the 
reference voltage. The reference can be as low as 100mV or can be tied directly 
to VCC. The LTC2484 includes an on-chip trimmed oscillator, eliminating the need 
for external crystals or oscillators. Absolute accuracy and low drift are 
automatically maintained through continuous, transparent, offset and full-scale 
calibration. 

@endverbatim

REVISION HISTORY
$Revision: 2316 $
$Date: 2014-03-31 14:17:01 -0700 (Mon, 31 Mar 2014) $

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 LTC2484 LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation

/*! @file
    @ingroup LTC2484
    Library for LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation
*/

#include <stdint.h>
#include <Arduino.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include "LTC2484.h"
#include "LTC24XX_general.h"
#include <SPI.h>

// Checks for EOC with a specified timeout
int8_t LTC2484_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
{

  return LTC24XX_EOC_timeout(cs, miso_timeout);
}
                         
void LTC2484_read(uint8_t cs, uint8_t adc_command, int32_t *adc_code)
// Reads the LTC2484
{
  LTC24XX_SPI_8bit_command_32bit_data(cs, adc_command, adc_code);
}

float LTC2484_code_to_voltage(int32_t adc_code, float LTC2484_lsb, int32_t LTC2484_offset_code)
// Calculates the LTC2484 input bipolar voltage
{
  return(LTC24XX_diff_code_to_calibrated_voltage(adc_code,  LTC2484_lsb, LTC2484_offset_code));
}

float LTC2484_temperature(int32_t adc_code, float LTC2484_t0, float LTC2484_r0)
// Calculate the LTC2484 temperature.
{
  adc_code -= 0x20000000;                                                   // Converts offset binary to binary
  return (((((float) adc_code) / LTC2484_r0) * (LTC2484_t0 + 273)) - 273);  // Calculate temperature from ADC code, t0, r0.
}

void LTC2484_cal_voltage(int32_t zero_code, int32_t fs_code, float zero_voltage, float fs_voltage, float *LTC2484_lsb, int32_t *LTC2484_offset_code)
// Calibrate the lsb
{
  zero_code -= 0x20000000;                                              // Converts zero code from offset binary to binary
  fs_code -= 0x20000000;                                                // Converts full scale from offset binary to binary
  
  float temp_offset;
  *LTC2484_lsb = (fs_voltage-zero_voltage)/((float)(fs_code - zero_code));                              // Calculate the LSB
  
  temp_offset = (zero_voltage/ *LTC2484_lsb) - zero_code;                                               // Calculate Unipolar offset
  temp_offset = (temp_offset > (floor(temp_offset) + 0.5)) ? ceil(temp_offset) : floor(temp_offset);    // Round
  *LTC2484_offset_code = (int32_t)temp_offset;                                                          // Cast as int32_t
}

void LTC2484_cal_temperature(int32_t adc_code, float temperature,  float *LTC2484_t0, float *LTC2484_r0)
// Calibrate temperature
{
  adc_code -= 0x20000000;              // Converts offset binary to binary
  *LTC2484_r0 = (float) adc_code;      // Convert the adc_code to a float value
  *LTC2484_t0 = temperature;           // Store the calibration temperature
}

Download LTC2484 Linduino Header File

//! @todo Review this file.
/*!
LTC2484: 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation

@verbatim

The LTC2484 combines a 24-bit no latency delta-sigma analog-to-digital converter 
with patented Easy Drive technology. The patented sampling scheme eliminates 
dynamic input current errors and the shortcomings of on-chip buffering through 
automatic cancellation of differential input current. This allows large external 
source impedances and input signals with rail-to-rail input range to be directly 
digitized while maintaining exceptional DC accuracy. 

The LTC2484 includes an on-chip oscillator. The LTC2484 can be configured to 
reject line frequencies. 50Hz, 60Hz or simultaneous 50Hz/60Hz line frequency 
rejection can be selected as well as a 2x speed-up mode. 

The LTC2484 allows a wide common mode input range (0V to VCC) independent of the 
reference voltage. The reference can be as low as 100mV or can be tied directly 
to VCC. The LTC2484 includes an on-chip trimmed oscillator, eliminating the need 
for external crystals or oscillators. Absolute accuracy and low drift are 
automatically maintained through continuous, transparent, offset and full-scale 
calibration. 

 SPI DATA FORMAT (MSB First):

             Byte #1                            Byte #2                           Byte #3                    Byte #4
 Data Out :  !EOC DMY SIG D23 D22 D21 D20 D19   D18 D17 D16 D15 D14 D13 D12 D11   D10 D9 D8 D7 D6 D5 D4 D3   D2 D1 D0 X X X X X
 Data In  :  EN   X   X   X   IM  FOA FOB SPD   X   X   X   X   X   X   X   X     X   X  X  X  X  X  X  X    X  X  X  X X X X X

 !EOC : End of Conversion Bit (Active Low)
 DMY  : Dummy Bit (Always 0)
 SIG  : Sign Bit (1-data positive, 0-data negative)
 Dx   : Data Bits
 EN   : Enable Bit (0-keep previous mode, 1-change mode)
 IM   : Internal Mode Bit (0-ADC input, 1-temperature sensor input)
 FoA  : Line Frequency Rejection Select Bit A
 FoB  : Line Frequency Rejection Select Bit B
 SPD  : Double Output Rate Select Bit (0-normal rate, auto-calibration on, 2x rate, auto_calibration off)
 X    : Don't Care

 Command Byte
 EN  IM   FoA  FoB  SPD   Comments
 0    X    X    X    X    Keep Previous Mode
 1    0    0    0    0    External Input, 50Hz and 60Hz Rejection, Autocalibration
 1    0    0    1    0    External Input, 50Hz Rejection, Autocalibration
 1    0    1    0    0    External Input, 60Hz Rejection, Autocalibration
 1    0    0    0    1    External Input, 50Hz and 60Hz Rejection, 2x Speed
 1    0    0    1    1    External Input, 50Hz Rejection, 2x Speed
 1    0    1    0    1    External Input, 60Hz Rejection, 2x Speed
 1    1    0    0    X    Temperature Input, 50Hz and 60Hz Rejection, Autocalibration
 1    1    0    1    X    Temperature Input, 50Hz Rejection, Autocalibration
 1    1    1    0    X    Temperature Input, 60Hz Rejection, Autocalibration
 1    X    1    1    X    Reserved, Do Not Use


Example Code:

Read the ADC voltage with 60Hz rejection

    uint16_t miso_timeout = 1000;
    // Build ADC command to read the ADC voltage
    adc_command = LTC2484_ENABLE;
    adc_command |= LTC2484_EXTERNAL_INPUT;
    adc_command |= LTC2484_AUTO_CALIBRATION;
    adc_command |= LTC2484_REJECTION_60HZ;
    
    
    if(LTC2484_EOC_timeout(LTC2484_CS, miso_timeout))    // Check for EOC
        return(1);
    LTC2484_read(LTC2484_CS, adc_command, &adc_code);   // Throw away last reading
    
    if(LTC2484_EOC_timeout(LTC2484_CS, miso_timeout))    // Check for EOC
        return(1);
    LTC2484_read(LTC2484_CS, adc_command, &adc_code);   // Obtains the current reading and stores to adc_code variable

    // Convert adc_code to voltage
    adc_voltage = LTC2484_code_to_voltage(adc_code, LTC2484_lsb, LTC2484_offset_code);

Read temperature

    uint16_t miso_timeout = 1000;
    
    // Build ADC command to read temperature
    adc_command = LTC2484_ENABLE;
    adc_command |= LTC2484_TEMPERATURE_INPUT;
    adc_command |= LTC2484_AUTO_CALIBRATION;

    if(LTC2484_EOC_timeout(LTC2484_CS, miso_timeout))    // Check for EOC
        return(1);
    LTC2484_read(LTC2484_CS, adc_command, &adc_code);   // Throw away last reading
    
    if(LTC2484_EOC_timeout(LTC2484_CS, miso_timeout))    // Check for EOC
        return(1);
    LTC2484_read(LTC2484_CS, adc_command, &adc_code);   // Obtains the current reading and stores to adc_code variable

    // Convert adc_code to temperature
    adc_temperature = LTC2484_temperature(adc_code, LTC2484_t0, LTC2484_r0);

@endverbatim

REVISION HISTORY
$Revision: 2315 $
$Date: 2014-03-31 13:05:50 -0700 (Mon, 31 Mar 2014) $

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 LTC2484
    Header for 2484 24-Bit Delta Sigma ADC with Easy Drive Input Current Cancellation
*/


#ifndef LTC2484_H
#define LTC2484_H

//! define the SPI CS pin
#ifndef LTC2484_CS
#define LTC2484_CS QUIKEVAL_CS
#endif

//! @name LTC2484 Command constants
//!@{
//! Command constants. OR together to form the adc_command byte.
#define LTC2484_ENABLE              0x80
#define LTC2484_DISABLE             0x00

#define LTC2484_EXTERNAL_INPUT      0x00
#define LTC2484_TEMPERATURE_INPUT   0x08

#define LTC2484_REJECTION_50HZ_60HZ 0x00
#define LTC2484_REJECTION_50HZ      0x02
#define LTC2484_REJECTION_60HZ      0x04

#define LTC2484_AUTO_CALIBRATION    0x00
#define LTC2484_SPEED_2X            0x01
//! @}

// Commands
// Construct enable with any other command to form an int command. You can also enable 2Xmode,
// which will increase sample rate by a factor of 2.

//! Checks for EOC with a specified timeout
//! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
int8_t LTC2484_EOC_timeout(uint8_t cs,          //!< Chip Select pin 
                           uint16_t miso_timeout //!< Timeout (in millisends)
                          );
                         
//! Read LTC2484 result, program configuration for next conversion
// Example - read channel external input with 60Hz rejection and 2X enabled.
// adc_command = (LTC2484_EXTERNAL_INPUT | LTC2484_REJECTION_60HZ) | LTC2484_SPEED_2X;
//! @return void
void LTC2484_read(uint8_t cs,           //!< Chip Select pin
                  uint8_t adc_command,  //!< Command byte
                  int32_t *adc_code     //!< Returns raw 32-bit code read from ADC
                 );

//! Calculates the LTC2484 input bipolar voltage
//! @return Calculated voltage
float LTC2484_code_to_voltage(int32_t adc_code,           //!< Raw ADC code
                              float LTC2484_lsb,          //!< LSB value (volts)
                              int32_t LTC2484_offset_code //!< Offset (Code)
                             );

//! Calculate the LTC2484 temperature.
//! @return Calculated Temperature
float LTC2484_temperature(int32_t adc_code,               //!< ADC code
                          float LTC2484_t0,               //!< Temperature calibration value
                          float LTC2484_r0                //!< Voltage for temperature calibration value
                         );

//! Calibrate the lsb
//! @return Void
void LTC2484_cal_voltage(int32_t zero_code,               //!< Offset (Code)
                         int32_t fs_code,                 //!< Code measured with full-scale input applied
                         float zero_voltage,              //!< Measured zero voltage
                         float fs_voltage,                //!< Actual voltage applied during full-scale measurement
                         float *LTC2484_lsb,              //!< Returns LSB value (volts)
                         int32_t *LTC2484_offset_code     //!< Returns Offset (Code)
                        );

//! Calibrate temperature
//! @return Void
void LTC2484_cal_temperature(int32_t adc_code,            //!< ADC code
                             float temperature,           //!< Actual temperature
                             float *LTC2484_t0,           //!< Temperature calibration value
                             float *LTC2484_r0            //!< Voltage for temperature calibration value
                            );

#endif  // LTC2484_H

Download LTC24XX – Linduino Header File

/*!
LTC24XX General Library: Functions and defines for all SINC4 Delta Sigma ADCs.

@verbatim


LTC2442 / LTC2444 / LTC2445 / LTC2448 / LTC2449 (Are there don't care bits in the low channel counts?
SPI DATA FORMAT (MSB First):

            Byte #1                            Byte #2

Data Out :  !EOC DMY SIG D28 D27 D26 D25 D24   D23  D22  D21  D20  D19 D18 D17 D16
Data In  :  1    0   EN  SGL OS  S2  S1  S0    OSR3 OSR2 OSR1 OSR1 SPD X   X   X

            Byte #3                            Byte #4
            D15  D14 D13 D12 D11 D10 D9  D8    D7  D6  D5  D4 *D3  *D2 *D1 *D0
            X    X   X   X   X   X   X   X     X   X   X   X   X   X   X   X

!EOC : End of Conversion Bit (Active Low)
DMY  : Dummy Bit (Always 0)
SIG  : Sign Bit (1-data positive, 0-data negative)
Dx   : Data Bits
*Dx  : Data Bits Below lsb
EN   : Enable Bit (0-keep previous mode, 1-change mode)
SGL  : Enable Single-Ended Bit (0-differential, 1-single-ended)
OS   : ODD/Sign Bit
Sx   : Address Select Bit
0SRX : Over Sampling Rate Bits
SPD  : Double Output Rate Select Bit (0-Normal rate, auto-calibration on, 2x rate, auto_calibration off)

Command Byte #1
1    0    EN   SGL  OS   S2   S1   S0   Comments
1    0    0    X    X    X    X    X    Keep Previous Mode
1    0    1    0    X    X    X    X    Differential Mode
1    0    1    1    X    X    X    X    Single-Ended Mode

|  Coversion Rate    |  RMS  | ENOB | OSR  | Latency
Command Byte #2          |Internal | External | Noise |      |      |
|  9MHz   | 10.24MHz |       |      |      |
OSR3 OSR2 OSR1 OSR1 SPD  | Clock   |  Clock   |       |      |      |
0    0    0    0    0      Keep Previous Speed/Resolution
0    0    0    1    0      3.52kHz   4kHz       23uV    17     64     none
0    0    1    0    0      1.76kHz   2kHz       3.5uV   20.1   128    none
0    0    1    1    0      880Hz     1kHz       2uV     21.3   256    none
0    1    0    0    0      440Hz     500Hz      1.4uV   21.8   512    none
0    1    0    1    0      220Hz     250Hz      1uV     22.4   1024   none
0    1    1    0    0      110Hz     125Hz      750nV   22.9   2048   none
0    1    1    1    0      55Hz      62.5Hz     510nV   23.4   4096   none
1    0    0    0    0      27.5Hz    31.25Hz    375nV   24     8192   none
1    0    0    1    0      13.75Hz   15.625Hz   250nV   24.4   16384  none
1    1    1    1    0      6.87kHz   7.8125Hz   200nV   24.6   32768  none
0    0    0    0    1      Keep Previous Speed/Resolution
OSR3 OSR2 OSR1 OSR1 1      2X Mode  *all clock speeds double

Example Code:

Read Channel 0 in Single-Ended with OSR of 65536

    uint16_t miso_timeout = 1000;
    adc_command = LTC2449_CH0 | LTC2449_OSR_32768 | LTC2449_SPEED_2X;   // Build ADC command for channel 0
                                                                        // OSR = 32768*2 = 65536

    if(LTC2449_EOC_timeout(LTC2449_CS, miso_timeout))    // Check for EOC
        return;                                          // Exit if timeout is reached
    LTC2449_read(LTC2449_CS, adc_command, &adc_code);    // Throws out last reading
    
    if(LTC2449_EOC_timeout(LTC2449_CS, miso_timeout))    // Check for EOC
        return;                                          // Exit if timeout is reached
    LTC2449_read(LTC2449_CS, adc_command, &adc_code);    // Obtains the current reading and stores to adc_code variable

    // Convert adc_code to voltage
    adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);

@endverbatim

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

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

REVISION HISTORY
$Revision: 1881 $
$Date: 2013-08-15 09:16:50 -0700 (Thu, 15 Aug 2013) $

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 LTC24XX_general
    Header for LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution
*/

#ifndef LTC24XX_general_H
#define LTC24XX_general_H

//! Define the SPI CS pin
#ifndef LTC24XX_CS
#define LTC24XX_CS QUIKEVAL_CS
#endif

//! In 2X Mode, A non offset binary 0 can be produced. This is corrected in the
//! differential code to voltage functions. To disable this correction, uncomment
//! The following #define. 
//#define SKIP_EZDRIVE_2X_ZERO_CHECK

/*! @name Mode Configuration for High Speed Family
 @{
*/
#define LTC24XX_HS_MULTI_KEEP_PREVIOUS_MODE              0x80
#define LTC24XX_HS_MULTI_KEEP_PREVIOUS_SPEED_RESOLUTION  0x00
#define LTC24XX_HS_MULTI_SPEED_1X                        0x00
#define LTC24XX_HS_MULTI_SPEED_2X                        0x08
/*!
 @}
*/

/*! @name Mode Configuration for EasyDrive Family
 @{
*/
// Select ADC source - differential input or PTAT circuit
#define LTC24XX_EZ_MULTI_VIN    0b10000000
#define LTC24XX_EZ_MULTI_PTAT   0b11000000

// Select rejection frequency - 50, 55, or 60Hz
#define LTC24XX_EZ_MULTI_R50    0b10010000
#define LTC24XX_EZ_MULTI_R55    0b10000000
#define LTC24XX_EZ_MULTI_R60    0b10100000

// Speed settings is bit 7 in the 2nd byte
#define LTC24XX_EZ_MULTI_SLOW   0b10000000 // slow output rate with autozero
#define LTC24XX_EZ_MULTI_FAST   0b10001000 // fast output rate with no autozero
/*!
 @}
*/


/*! @name Single-Ended Channel Configuration
@verbatim
Channel selection for all multi-channel, differential input ADCs, even those that only require
8 bits of configuration (no further options.) Most devices in this category require a second
byte of configuration for speed mode, temperature sensor selection, etc., but for the sake
of simplicity a single function will be used to read all devices, sending zeros in the second
configuration byte if only the channel is specified.

Applicable devices:
Easy Drive:
LTC2486, LTC2487, LTC2488, LTC2489, LTC2492, LTC2493,
LTC2494, LTC2495, LTC2496, LTC2497, LTC2498, LTC2499
First Generation Differential:
LTC2414, LTC2418, LTC2439
High Speed:
LTC2442, LTC2444, LTC2445, LTC2448, LTC2449
@endverbatim
@{ */
#define LTC24XX_MULTI_CH_CH0            0xB0
#define LTC24XX_MULTI_CH_CH1            0xB8
#define LTC24XX_MULTI_CH_CH2            0xB1
#define LTC24XX_MULTI_CH_CH3            0xB9
#define LTC24XX_MULTI_CH_CH4            0xB2
#define LTC24XX_MULTI_CH_CH5            0xBA
#define LTC24XX_MULTI_CH_CH6            0xB3
#define LTC24XX_MULTI_CH_CH7            0xBB
#define LTC24XX_MULTI_CH_CH8            0xB4
#define LTC24XX_MULTI_CH_CH9            0xBC
#define LTC24XX_MULTI_CH_CH10           0xB5
#define LTC24XX_MULTI_CH_CH11           0xBD
#define LTC24XX_MULTI_CH_CH12           0xB6
#define LTC24XX_MULTI_CH_CH13           0xBE
#define LTC24XX_MULTI_CH_CH14           0xB7
#define LTC24XX_MULTI_CH_CH15           0xBF
/*! @} */

/*! @name Differential Channel Configuration
@verbatim
See note for single-ended configuration above.

@endverbatim
@{ */
#define LTC24XX_MULTI_CH_P0_N1          0xA0
#define LTC24XX_MULTI_CH_P1_N0          0xA8

#define LTC24XX_MULTI_CH_P2_N3          0xA1
#define LTC24XX_MULTI_CH_P3_N2          0xA9

#define LTC24XX_MULTI_CH_P4_N5          0xA2
#define LTC24XX_MULTI_CH_P5_N4          0xAA

#define LTC24XX_MULTI_CH_P6_N7          0xA3
#define LTC24XX_MULTI_CH_P7_N6          0xAB

#define LTC24XX_MULTI_CH_P8_N9          0xA4
#define LTC24XX_MULTI_CH_P9_N8          0xAC

#define LTC24XX_MULTI_CH_P10_N11        0xA5
#define LTC24XX_MULTI_CH_P11_N10        0xAD

#define LTC24XX_MULTI_CH_P12_N13        0xA6
#define LTC24XX_MULTI_CH_P13_N12        0xAE

#define LTC24XX_MULTI_CH_P14_N15        0xA7
#define LTC24XX_MULTI_CH_P15_N14        0xAF
/*! @} */

/*Commands
Construct a channel / resolution control word by bitwise ORing one choice from the channel configuration
and one choice from the Oversample ratio configuration. You can also enable 2Xmode, which will increase
sample rate by a factor of 2 but introduce one cycle of latency.

Example - read channel 3 single-ended at OSR2048, with 2X mode enabled.
adc_command = (LTC2449_CH3 | LTC2449_OSR_2048) | LTC2449_SPEED_2X;
*/

/*! @name Oversample Ratio (OSR) Commands
@{ */
#define LTC24XX_MULTI_CH_OSR_64         0x10
#define LTC24XX_MULTI_CH_OSR_128        0x20
#define LTC24XX_MULTI_CH_OSR_256        0x30
#define LTC24XX_MULTI_CH_OSR_512        0x40
#define LTC24XX_MULTI_CH_OSR_1024       0x50
#define LTC24XX_MULTI_CH_OSR_2048       0x60
#define LTC24XX_MULTI_CH_OSR_4096       0x70
#define LTC24XX_MULTI_CH_OSR_8192       0x80
#define LTC24XX_MULTI_CH_OSR_16384      0x90
#define LTC24XX_MULTI_CH_OSR_32768      0xF0
/*! @}*/

//! Checks for EOC with a specified timeout. Applies to all SPI interface delta sigma
//! ADCs that have SINC4 rejection, does NOT apply to LTC2450/60/70 family.
//! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
int8_t LTC24XX_EOC_timeout(uint8_t cs,           //!< Chip Select pin 
                          uint16_t miso_timeout  //!< Timeout (in milliseconds)
                          );


// Read functions for SPI interface ADCs with a 32 bit output word. These functions are used with both
// Single-ended and differential parts, as there is no interpretation of the data done in
// the function. Also note that these functions can be used for devices that have shorter output lengths,
// the lower bits will read out as "1", as the conversion will be triggered by the last data bit being
// read, which causes SDO to go high.


//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_32bit_data(uint8_t cs,         //!< Chip Select pin 
                            int32_t *adc_code   //!< 4 byte conversion code read from LTC24XX
                           );

//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_8bit_command_32bit_data(uint8_t cs,               //!< Chip Select pin 
                                         uint8_t adc_command,      //!< 1 byte command written to LTC24XX
                                         int32_t *adc_code         //!< 4 byte conversion code read from LTC24XX
                                        );

//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_16bit_command_32bit_data(uint8_t cs,                  //!< Chip Select pin 
                                          uint8_t adc_command_high,    //!< First command byte written to LTC24XX
                                          uint8_t adc_command_low,     //!< Second command written to LTC24XX
                                          int32_t *adc_code            //!< 4 byte conversion code read from LTC24XX
                                         );

//! Reads from LTC24XX two channel "Ping-Pong" ADC, placing the channel information in the adc_channel parameter
//! and returning the 32 bit result with the channel bit cleared so the data format matches the rest of the family
//! @return void
void LTC24XX_SPI_2ch_ping_pong_32bit_data(uint8_t cs,           //!< Chip Select pin 
                                          uint8_t *adc_channel, //!< Returns channel number read.
                                          int32_t *code         //!< 4 byte conversion code read from LTC24XX
                                         );


// Read functions for SPI interface ADCs with a 24 bit or 19 bit output word. These functions
// are used with both Single-ended and differential parts, as there is no interpretation of
// the data done in the function. 24 bits will be read out of 19 bit devices
// (LTC2433, LTC2436, LTC2439), with the additional 5 bits being set to 1.

//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_24bit_data(uint8_t cs,         //!< Chip Select pin 
                            int32_t *adc_code   //!< 4 byte conversion code read from LTC24XX
                           );

//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_8bit_command_24bit_data(uint8_t cs,            //!< Chip Select pin 
                                         uint8_t adc_command,   //!< 1 byte command written to LTC24XX
                                         int32_t *adc_code      //!< 4 byte conversion code read from LTC24XX
                                        );

//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_16bit_command_24bit_data(uint8_t cs,                  //!< Chip Select pin 
                                          uint8_t adc_command_high,    //!< First command byte written to LTC24XX
                                          uint8_t adc_command_low,     //!< Second command written to LTC24XX
                                          int32_t *adc_code            //!< 4 byte conversion code read from LTC24XX
                                         );

//! Reads from LTC24XX ADC that accepts a 8 bit configuration and returns a 16 bit result.
//! @return  void
void LTC24XX_SPI_8bit_command_16bit_data(uint8_t cs,                //!< Chip Select pin 
                                          uint8_t adc_command,      //!< First command byte written to LTC24XX
                                          int32_t *adc_code         //!< 4 byte conversion code read from LTC24XX
                                         );                                         
                                         
                                         
//! Reads from LTC24XX two channel "Ping-Pong" ADC, placing the channel information in the adc_channel parameter
//! and returning the 32 bit result with the channel bit cleared so the data format matches the rest of the family
//! @return void
void LTC24XX_SPI_2ch_ping_pong_24bit_data(uint8_t cs,           //!< Chip Select pin 
                                          uint8_t *adc_channel, //!< Returns channel number read.
                                          int32_t *code         //!< 4 byte conversion code read from LTC24XX
                                         );

// Read functions for I2C interface ADCs with a 32 bit output word. These functions are used with both
// Single-ended and differential parts, as there is no interpretation of the data done in
// the function. Also note that these functions can be used for devices that have shorter output lengths,
// the lower bits will read out as "1", as the conversion will be triggered by the last data bit being
// read, which causes SDO to go high.
// Data is formatted to match the SPI devices, with the MSB in the bit 28 position.
// Unlike the SPI members of this family, checking for EOC MUST immediately be followed by reading the data. This
// is because a stop condition will trigger a new conversion.


//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_32bit_data(uint8_t i2c_address,  //!< I2C address of device
                            int32_t *adc_code,      //!< 4 byte conversion code read from LTC24XX
                            uint16_t eoc_timeout    //!< Timeout (in milliseconds)
                           );


//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_8bit_command_32bit_data(uint8_t i2c_address,     //!< I2C address of device
                                           uint8_t adc_command,     //!< 1 byte command written to LTC24XX
                                           int32_t *adc_code,       //!< 4 byte conversion code read from LTC24XX
                                           uint16_t eoc_timeout     //!< Timeout (in milliseconds)
                                           );


//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_16bit_command_32bit_data(uint8_t i2c_address,        //!< I2C address of device
                                            uint8_t adc_command_high,   //!< First command byte written to LTC24XX
                                            uint8_t adc_command_low,    //!< Second command written to LTC24XX
                                            int32_t *adc_code,          //!< 4 byte conversion code read from LTC24XX
                                            uint16_t eoc_timeout        //!< Timeout (in milliseconds)
                                         );


// Read functions for I2C interface ADCs with a 24 bit or 19 bit output word. These functions
// are used with both Single-ended and differential parts, as there is no interpretation of
// the data done in the function. 24 bits will be read out of 19 bit devices
// (LTC2433, LTC2436, LTC2439), with the additional 5 bits being set to 1.


//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! Applies to: LTC2483 (only this lonely one!)
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_24bit_data(uint8_t i2c_address,      //!< I2C address of device
                              int32_t *adc_code,        //!< 4 byte conversion code read from LTC24XX
                              uint16_t eoc_timeout      //!< Timeout (in milliseconds)
                             );


//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_8bit_command_24bit_data(uint8_t i2c_address,      //!< I2C address of device
                                           uint8_t adc_command,      //!< 1 byte command written to LTC24XX
                                           int32_t *adc_code,        //!< 4 byte conversion code read from LTC24XX
                                           uint16_t eoc_timeout      //!< Timeout (in milliseconds)
                                          );

//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_16bit_command_24bit_data(uint8_t i2c_address,         //!< I2C address of device
                                            uint8_t adc_command_high,    //!< First command byte written to LTC24XX
                                            uint8_t adc_command_low,     //!< Second command written to LTC24XX
                                            int32_t *adc_code,           //!< 4 byte conversion code read from LTC24XX
                                            uint16_t eoc_timeout         //!< Timeout (in milliseconds)
                                           );

//! Calculates the voltage corresponding to an ADC code, given the reference voltage.
//! Applies to Single-Ended input parts (LTC2400-type input)
//! @return Returns voltage calculated from ADC code.
float LTC24XX_SE_code_to_voltage(int32_t adc_code,  //!< Code read from ADC
                                 float vref         //!< Reference voltage
                                );
//! Calculates the voltage corresponding to an ADC code, given the reference voltage.
//! Applies to differential input parts (LTC2410 type input)
//! @return Returns voltage calculated from ADC code.
float LTC24XX_diff_code_to_voltage(int32_t adc_code,             //!< Code read from ADC
                                   float vref                    //!< Reference voltage
                                  );

//! Calculates the voltage corresponding to an ADC code, given lsb weight (in volts) and the calibrated
//! ADC offset code (zero code that is subtracted from adc_code).
//! Applies to differential input, SPI interface parts.
//! @return Returns voltage calculated from ADC code.
float LTC24XX_diff_code_to_calibrated_voltage(int32_t adc_code,               //!< Code read from ADC
                                              float LTC24XX_lsb,              //!< LSB weight (in volts)
                                              int32_t LTC24XX_offset_code     //!< The calibrated offset code (This is the ADC code zero code that will be subtracted from adc_code)
                                             );

//! Calculate the lsb weight and offset code given a full-scale code and a measured zero-code.
//! @return Void
void LTC24XX_calibrate_voltage(int32_t zero_code,             //!< Measured code with the inputs shorted to ground
                               int32_t fs_code,               //!< Measured code at nearly full-scale
                               float zero_voltage,            //!< Measured zero voltage
                               float fs_voltage,              //!< Voltage measured at input (with voltmeter) when fs_code was read from ADC
                               float *LTC24XX_lsb,            //!< Overwritten with lsb weight (in volts)
                               int32_t *LTC24XX_offset_code   //!< Overwritten with offset code (zero code)
                              );



// I2C Addresses for 8/16 channel parts (LTC2495/7/9)
//                                   ADDRESS     CA2   CA1    CA0
// #define LTC24XX_16CH_I2C_ADDRESS 0b0010100 // LOW   LOW    LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b0010110 // LOW   LOW    HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b0010101 // LOW   LOW    FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b0100110 // LOW   HIGH   LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b0110100 // LOW   HIGH   HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b0100111 // LOW   HIGH   FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b0010111 // LOW   FLOAT  LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b0100101 // LOW   FLOAT  HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b0100100 // LOW   FLOAT  FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b1010110 // HIGH  LOW    LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b1100100 // HIGH  LOW    HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b1010111 // HIGH  LOW    FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b1110100 // HIGH  HIGH   LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b1110110 // HIGH  HIGH   HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b1110101 // HIGH  HIGH   FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b1100101 // HIGH  FLOAT  LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b1100111 // HIGH  FLOAT  HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b1100110 // HIGH  FLOAT  FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b0110101 // FLOAT LOW   LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b0110111 // FLOAT LOW   HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b0110110 // FLOAT LOW   FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b1000111 // FLOAT HIGH  LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b1010101 // FLOAT HIGH  HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b1010100 // FLOAT HIGH  FLOAT
// #define LTC24XX_16CH_I2C_ADDRESS 0b1000100 // FLOAT FLOAT LOW
// #define LTC24XX_16CH_I2C_ADDRESS 0b1000110 // FLOAT FLOAT HIGH
// #define LTC24XX_16CH_I2C_ADDRESS 0b1000101 // FLOAT FLOAT FLOAT

// I2C Addresses for 2/4 channel parts
//                                  ADDRESS      CA1   CA0
// #define LTC24XX_4CH_I2C_ADDRESS 0b0010100  // LOW   LOW  
// #define LTC24XX_4CH_I2C_ADDRESS 0b0010110  // LOW   HIGH 
// #define LTC24XX_4CH_I2C_ADDRESS 0b0010101  // LOW   FLOAT
// #define LTC24XX_4CH_I2C_ADDRESS 0b0100110  // HIGH  LOW  
// #define LTC24XX_4CH_I2C_ADDRESS 0b0110100  // HIGH  HIGH 
// #define LTC24XX_4CH_I2C_ADDRESS 0b0100111  // HIGH  FLOAT
// #define LTC24XX_4CH_I2C_ADDRESS 0b0010111  // FLOAT LOW  
// #define LTC24XX_4CH_I2C_ADDRESS 0b0100101  // FLOAT HIGH 
// #define LTC24XX_4CH_I2C_ADDRESS 0b0100100  // FLOAT FLOAT
        
        
// I2C Addresses for Single channel parts (LTC2481/83/85)
//                                  ADDRESS      CA1   CA0/f0*
// #define LTC24XX_1CH_I2C_ADDRESS 0b0010100  // LOW   HIGH          
// #define LTC24XX_1CH_I2C_ADDRESS 0b0010101  // LOW   FLOAT      
// #define LTC24XX_1CH_I2C_ADDRESS 0b0010111  // FLOAT HIGH     
// #define LTC24XX_1CH_I2C_ADDRESS 0b0100100  // FLOAT FLOAT 
// #define LTC24XX_1CH_I2C_ADDRESS 0b0100110  // HIGH  HIGH         
// #define LTC24XX_1CH_I2C_ADDRESS 0b0100111  // HIGH  FLOAT     


#endif  // LTC24XX_general_H

Download LTC24XX – Linduino.CPP File

/*!
LTC24XX General Library: Functions and defines for all SINC4 Delta Sigma ADCs.

@verbatim

These functions and defines apply to all No Latency Delta Sigmas in the
LTC2480 EasyDrive family, LTC2410 differential family, LTC2400 single-ended family,
and the LTC2440 High Speed family with selectable speed / resolution.

It does not cover the LTC2450 tiny, low cost delta sigma ADC famliy.

Please refer to the No Latency Delta Sigma ADC selector guide available at:

http://www.linear.com/docs/41341


@endverbatim

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

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

REVISION HISTORY
$Revision: 1807 $
$Date: 2013-07-29 13:06:06 -0700 (Mon, 29 Jul 2013) $

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 LTC24XX LTC24XX: All no-latency delta sigma ADCs with SINC4 rejection

/*! @file
    @ingroup LTC24XX
    Library for LTC24XX no-latency delta sigma ADCs with SINC4 rejection
*/

#include <stdint.h>
#include <Arduino.h>
#include "Linduino.h"
#include <SPI.h>
#include "LT_SPI.h"
#include <Wire.h>
#include "LT_I2C.h"
#include "LTC24XX_general.h"


int8_t LTC24XX_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
// Checks for EOC with a specified timeout (ms)
{
  uint16_t timer_count = 0;             // Timer count for MISO
  output_low(cs);                       //! 1) Pull CS low
  while (1)                             //! 2) Wait for SDO (MISO) to go low
  {
    if (input(MISO) == 0) break;        //! 3) If SDO is low, break loop
    if (timer_count++>miso_timeout)     // If timeout, return 1 (failure)
    {
      output_high(cs);                  // Pull CS high
      return(1);
    }
    else
      delay(1);
  }
  output_high(cs);                  // Pull CS high
  return(0);
}

// Reads from LTC24XX ADC that has no configuration word and a 32 bit output word.
void LTC24XX_SPI_32bit_data(uint8_t cs, int32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC2449 data and command
  command.LT_uint32 = 0;                // Set to zero, not necessary but avoids
                                        // random data in scope shots.
  output_low(cs);                                                       //! 1) Pull CS low
  
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)4);    //! 2) Transfer arrays

  output_high(cs);                                                      //! 3) Pull CS high
  *adc_code = data.LT_int32;
}


// Reads from a SPI LTC24XX device that has an 8 bit command and a 32 bit output word.
void LTC24XX_SPI_8bit_command_32bit_data(uint8_t cs, uint8_t adc_command, int32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC2449 data and command
  command.LT_byte[3] = adc_command;
  command.LT_byte[2] = 0;
  command.LT_byte[1] = 0;
  command.LT_byte[0] = 0;

  output_low(cs);                                                       //! 1) Pull CS low
  
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)4);    //! 2) Transfer arrays 

  output_high(cs);                                                      //! 3) Pull CS high
  *adc_code = data.LT_int32;
}


// Reads from a SPI LTC24XX device that has a 16 bit command and a 32 bit output word.
void LTC24XX_SPI_16bit_command_32bit_data(uint8_t cs, uint8_t adc_command_high, uint8_t adc_command_low, int32_t *adc_code)
{

    
  LT_union_int32_4bytes data, command;  // LTC24XX data and command
  command.LT_byte[3] = adc_command_high;
  command.LT_byte[2] = adc_command_low;
  command.LT_byte[1] = 0;
  command.LT_byte[0] = 0;
 
  output_low(cs);                                                       //! 1) Pull CS low
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)4);    //! 2) Transfer arrays 
  output_high(cs);                                                      //! 3) Pull CS high
  *adc_code = data.LT_int32;
}

//! Reads from LTC24XX two channel "Ping-Pong" ADC, placing the channel information in the adc_channel parameter
//! and returning the 32 bit result with the channel bit cleared so the data format matches the rest of the family
//! @return void
void LTC24XX_SPI_2ch_ping_pong_32bit_data(uint8_t cs, uint8_t *adc_channel, int32_t *code)
{
  LT_union_int32_4bytes data, command;      // ADC data

  command.LT_int32 = 0x00000000;  // This is a "don't care"

  spi_transfer_block(cs, command.LT_byte , data.LT_byte, (uint8_t)4);
  if(data.LT_byte[3] & 0x40) // Obtains Channel Number
  {
    *adc_channel = 1;
  }
  else
  {
    *adc_channel = 0;
  }
  data.LT_byte[3] &= 0x3F;                  // Clear channel bit here so code to voltage function doesn't have to.
  *code = data.LT_int32;                    // Return data
}

//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! @return  void
void LTC24XX_SPI_24bit_data(uint8_t cs, int32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC24XX data and command
  command.LT_int32 = 0;

  output_low(cs);                                                       //! 1) Pull CS low
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)3);    //! 2) Transfer arrays 
  output_high(cs);                                                      //! 3) Pull CS high

  data.LT_byte[3] = data.LT_byte[2]; // Shift bytes up by one. We read out 24 bits,
  data.LT_byte[2] = data.LT_byte[1]; // which are loaded into bytes 2,1,0. Need to left-
  data.LT_byte[1] = data.LT_byte[0]; // justify.
  data.LT_byte[0] = 0x00;

  *adc_code = data.LT_int32;
}

//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 24 bit output word.
//! @return  void
void LTC24XX_SPI_8bit_command_24bit_data(uint8_t cs, uint8_t adc_command, int32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC24XX data and command
  command.LT_byte[2] = adc_command;
  command.LT_byte[1] = 0;
  command.LT_byte[0] = 0;

  output_low(cs);                                                       //! 1) Pull CS low
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)3);    //! 2) Transfer arrays 
  output_high(cs);                                                      //! 3) Pull CS high

  data.LT_byte[3] = data.LT_byte[2]; // Shift bytes up by one. We read out 24 bits,
  data.LT_byte[2] = data.LT_byte[1]; // which are loaded into bytes 2,1,0. Need to left-
  data.LT_byte[1] = data.LT_byte[0]; // justify.
  data.LT_byte[0] = 0x00;

  *adc_code = data.LT_int32;
}

//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 24 bit output word.
//! @return  void
void LTC24XX_SPI_16bit_command_24bit_data(uint8_t cs, uint8_t adc_command_high, uint8_t adc_command_low, int32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC24XX data and command
  command.LT_byte[2] = adc_command_high;
  command.LT_byte[1] = adc_command_low;
  command.LT_byte[0] = 0;
  
  
  output_low(cs);                                                       //! 1) Pull CS low
  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)3);    //! 2) Transfer arrays 
  output_high(cs);                                                      //! 3) Pull CS high

  data.LT_byte[3] = data.LT_byte[2]; // Shift bytes up by one. We read out 24 bits,
  data.LT_byte[2] = data.LT_byte[1]; // which are loaded into bytes 2,1,0. Need to left-
  data.LT_byte[1] = data.LT_byte[0]; // justify.
  data.LT_byte[0] = 0x00;

  *adc_code = data.LT_int32;
}

//! Reads from LTC24XX two channel "Ping-Pong" ADC, placing the channel information in the adc_channel parameter
//! and returning the 24 bit result with the channel bit cleared so the data format matches the rest of the family
//! @return void
void LTC24XX_SPI_2ch_ping_pong_24bit_data(uint8_t cs, uint8_t *adc_channel, int32_t *code)
{
  LT_union_int32_4bytes data, command;      // ADC data

  command.LT_int32 = 0x00000000;  // This is a "don't care"

  spi_transfer_block(cs, command.LT_byte , data.LT_byte, (uint8_t)3);
  data.LT_byte[3] = data.LT_byte[2]; // Shift bytes up by one. We read out 24 bits,
  data.LT_byte[2] = data.LT_byte[1]; // which are loaded into bytes 2,1,0. Need to left-
  data.LT_byte[1] = data.LT_byte[0]; // justify.
  data.LT_byte[0] = 0x00;

  if(data.LT_byte[3] & 0x40) // Obtains Channel Number
  {
    *adc_channel = 1;
  }
  else
  {
    *adc_channel = 0;
  }
  data.LT_byte[3] &= 0x3F;                  // Clear channel bit here so code to voltage function doesn't have to.
  *code = data.LT_int32;                    // Return data
}


//I2C functions

//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 24 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_8bit_command_24bit_data(uint8_t i2c_address, uint8_t adc_command, int32_t *adc_code, uint16_t eoc_timeout)
{
  int8_t ack;
  uint16_t timer_count = 0;        // Timer count to wait for ACK
  int8_t buf[4];
  LT_union_int32_4bytes data;      // LTC24XX data
  while(1)
  {
    ack = i2c_read_block_data(i2c_address, adc_command, 3, data.LT_byte);
    if(!ack) break; // !ack indicates success
    if (timer_count++>eoc_timeout)     // If timeout, return 1 (failure)
      return(1);
    else
      delay(1);
  }
  data.LT_byte[3] = data.LT_byte[2]; // Shift bytes up by one. We read out 24 bits,
  data.LT_byte[2] = data.LT_byte[1]; // which are loaded into bytes 2,1,0. Need to left-
  data.LT_byte[1] = data.LT_byte[0]; // justify.
  data.LT_byte[0] = 0x00;
  data.LT_uint32 >>= 2;  // Shifts data 2 bits to the right; operating on unsigned member shifts in zeros.
  data.LT_byte[3] = data.LT_byte[3] & 0x3F; // Clear upper 2 bits JUST IN CASE. Now the data format matches the SPI parts.
  *adc_code = data.LT_int32;
  return(ack); // Success
}



//! Reads from LTC24XX ADC that has no configuration word and returns a 32 bit result.
//! Data is formatted to match the SPI devices, with the MSB in the bit 28 position.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_32bit_data(uint8_t i2c_address,                   //!< I2C address of device
                            int32_t *adc_code,                      //!< 4 byte conversion code read from LTC24XX
                            uint16_t eoc_timeout                     //!< Timeout (in milliseconds)
                           )
{
  int8_t ack;
  uint16_t timer_count = 0;        // Timer count to wait for ACK
  int8_t buf[4];
  LT_union_int32_4bytes data;      // LTC24XX data
  while(1)
  {
    ack = i2c_read_block_data(i2c_address, 4, data.LT_byte);
    if(!ack) break; // !ack indicates success
    if (timer_count++>eoc_timeout)     // If timeout, return 1 (failure)
      return(1);
    else
      delay(1);
  }

  data.LT_uint32 >>= 2;  // Shifts data 2 bits to the right; operating on unsigned member shifts in zeros.
  data.LT_byte[3] = data.LT_byte[3] & 0x3F; // Clear upper 2 bits JUST IN CASE. Now the data format matches the SPI parts.
  *adc_code = data.LT_int32;
  return(ack); // Success
  }


//! Reads from LTC24XX ADC that accepts an 8 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_8bit_command_32bit_data(uint8_t i2c_address, uint8_t adc_command, int32_t *adc_code, uint16_t eoc_timeout)
{
  int8_t ack;
  uint16_t timer_count = 0;        // Timer count to wait for ACK
  int8_t buf[4];
  LT_union_int32_4bytes data;      // LTC24XX data
  while(1)
  {
    ack = i2c_read_block_data(i2c_address, adc_command, 4, data.LT_byte);
    if(!ack) break; // !ack indicates success
    if (timer_count++>eoc_timeout)     // If timeout, return 1 (failure)
      return(1);
    else
      delay(1);
  }

  data.LT_uint32 >>= 2;  // Shifts data 2 bits to the right; operating on unsigned member shifts in zeros.
  data.LT_byte[3] = data.LT_byte[3] & 0x3F; // Clear upper 2 bits JUST IN CASE. Now the data format matches the SPI parts.
  *adc_code = data.LT_int32;
  return(ack); // Success
}

//! Reads from LTC24XX ADC that accepts a 16 bit configuration and returns a 32 bit result.
//! @return  Returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge.
int8_t LTC24XX_I2C_16bit_command_32bit_data(uint8_t i2c_address,uint8_t adc_command_high,
                                            uint8_t adc_command_low,int32_t *adc_code,uint16_t eoc_timeout)
{
  int8_t ack;
  uint16_t adc_command, timer_count = 0;        // Timer count to wait for ACK
  int8_t buf[4];
  LT_union_int32_4bytes data;      // LTC24XX data
  adc_command = (adc_command_high << 8) | adc_command_low;
  while(1)
  {
    ack = i2c_two_byte_command_read_block(i2c_address, adc_command, 4, data.LT_byte);
    if(!ack) break; // !ack indicates success
    if (timer_count++>eoc_timeout)     // If timeout, return 1 (failure)
      return(1);
    else
      delay(1);
  }

  data.LT_uint32 >>= 2;  // Shifts data 2 bits to the right; operating on unsigned member shifts in zeros.
  data.LT_byte[3] = data.LT_byte[3] & 0x3F; // Clear upper 2 bits JUST IN CASE. Now the data format matches the SPI parts.
  *adc_code = data.LT_int32;
  return(ack); // Success
}

// Calculates the voltage corresponding to an adc code, given the reference voltage (in volts)
float LTC24XX_SE_code_to_voltage(int32_t adc_code, float vref)
{
  float voltage;
  adc_code -= 0x20000000;             //! 1) Subtract offset
  voltage=(float) adc_code;
  voltage = voltage / 268435456.0;    //! 2) This calculates the input as a fraction of the reference voltage (dimensionless)
  voltage = voltage * vref;           //! 3) Multiply fraction by Vref to get the actual voltage at the input (in volts)
  return(voltage);
}

// Calculates the voltage corresponding to an adc code, given the reference voltage (in volts)
// This function handles all differential input parts, including the "single-ended" mode on multichannel
// differential parts. Data from I2C parts must be right-shifted by two bit positions such that the MSB
// is in bit 28 (the same as the SPI parts.)
float LTC24XX_diff_code_to_voltage(int32_t adc_code, float vref)
{
  float voltage;
  
  #ifndef SKIP_EZDRIVE_2X_ZERO_CHECK
  if(adc_code == 0x00000000)
  {
    adc_code = 0x20000000;
  }
  #endif

  adc_code -= 0x20000000;             //! 1) Converts offset binary to binary
  voltage=(float) adc_code;
  voltage = voltage / 536870912.0;    //! 2) This calculates the input as a fraction of the reference voltage (dimensionless)
  voltage = voltage * vref;           //! 3) Multiply fraction by Vref to get the actual voltage at the input (in volts)
  return(voltage);
}

// Calculates the voltage corresponding to an adc code, given lsb weight (in volts) and the calibrated
// adc offset code (zero code that is subtracted from adc_code). For use with the LTC24XX_cal_voltage() function.
float LTC24XX_diff_code_to_calibrated_voltage(int32_t adc_code, float LTC2449_lsb, int32_t LTC2449_offset_code)
{
  float adc_voltage;
  
  #ifndef SKIP_EZDRIVE_2X_ZERO_CHECK
  if(adc_code == 0x00000000)
  {
    adc_code = 0x20000000;
  }
  #endif  
  
  adc_code -= 536870912;                                            //! 1) Converts offset binary to binary
  adc_voltage=(float)(adc_code+LTC2449_offset_code)*LTC2449_lsb;    //! 2) Calculate voltage from ADC code, lsb, offset.
  return(adc_voltage);
}


// Calculate the lsb weight and offset code given a full-scale code and a measured zero-code.
void LTC24XX_calibrate_voltage(int32_t zero_code, int32_t fs_code, float zero_voltage, float fs_voltage, float *LTC24XX_lsb, int32_t *LTC24XX_offset_code)
{
  zero_code -= 536870912;   //! 1) Converts zero code from offset binary to binary
  fs_code -= 536870912;     //! 2) Converts full scale code from offset binary to binary
  
  float temp_offset;
  *LTC24XX_lsb = (fs_voltage-zero_voltage)/((float)(fs_code - zero_code));                              //! 3) Calculate the LSB
  
  temp_offset = (zero_voltage/ *LTC24XX_lsb) - zero_code;                                               //! 4) Calculate Unipolar offset
  temp_offset = (temp_offset > (floor(temp_offset) + 0.5)) ? ceil(temp_offset) : floor(temp_offset);    //! 5) Round
  *LTC24XX_offset_code = (int32_t)temp_offset;                                                          //! 6) Cast as int32_t
}

Technical Support