Implementing an external ADC in Arduino
To get an understanding of how to read from the various ADS1220 channels, first review Figure 38, Analog Input Multiplexer, in the Datasheet as obtained from a link on TI.com's ADS1220 technicaldocuments webpage.


As can be seen, you'll need to close a switch from an AINx input line to the AINₚ bus, and also close the switch between AINₙ and AVSS.  The IDACx switches and the BCS switches should remain open.

To operate those switches, first look at §8.6.1, Configuration Registers, in the Register Map section of the Datasheet.  You'll see that MUX bits are in register 0, BCS is in register 1, IDAC is in register 2, and IxMUX are in register 3.  To see what to put into those fields, look at Tables 16, 17, 19, and 20.  For the MUX field, you will want a binary value like 1000, 1001, 1010, or 1011 to select one of AIN0-AIN3 as the AINₚ input and AVSS as the AINₙ input.  BCS, IDAC, I1MUX, and I2MUX all should be zero.

For example, to read channels 0, 1, 2 in sequence, set MUX to 1000, set up other register fields, and trigger a conversion.  After reading the result, change MUX to 1001, trigger a conversion, read result,  change MUX to 1010, trigger a conversion, read result, etc.



Edit 1: In slightly more detail, one could do as follows.


  • Use a WREG command [as in §8.5.3.6; or some library equivalent] to send three bytes to set up Configuration Registers 1, 2, 3.
  • For i=0, 1, and 2 in turn, construct a configuration byte, send that byte to Configuration Register 0, start a conversion, await result, read result; as follows:
  
  
    Set the MUX field of a byte to i
    Set PGA as desired (ie, to 1, 2, or 4, via codes 000, 001, or 010)
    Set the PGA_BYPASS bit (as required when AINₙ = AVSS)
    Use a WREG to send the constructed byte to Configuration Register 0
    Use a START/SYNC command to start a conversion (see §8.5.3.2)
    Wait for DRDY to go low
    Use an RDATA command to read iᵗʰ ADC result (see §8.5.3.4)  
  




Edit 2: In Protocentral's ADS1220.ino sketch, one finds the code sequence

  MSB = SPI_RX_Buff_Ptr[0];    
  data = SPI_RX_Buff_Ptr[1];
  LSB = SPI_RX_Buff_Ptr[2];
  bit24 = MSB;
  bit24 = (bit24 &lt;&lt; 8) | data;
  bit24 = (bit24 &lt;&lt; 8) | LSB; // Converting 3 bytes to a 24 bit int
  bit24= ( bit24 &lt;&lt; 8 );
  bit32 = ( bit24 &gt;&gt; 8 );     // Converting 24 bit two's complement to 32 bit two's complement


More competently and concisely, and with SPI_RX_Buff_Ptr renamed to SPI_RX_Buff, this could be written as:

  bit32 = (((long)(SPI_RX_Buff[0]&lt;&lt;8 | SPI_RX_Buff[1])&lt;&lt;8 | SPI_RX_Buff[2])&lt;&lt;8)&gt;&gt;8;


which acts as follows:  Assemble three bytes from SPI_RX_Buff into a 24-bit twos-complement-signed number.  Shift that number left 8 bits so that its sign bit now sits in the sign bit position of a 32-bit signed integer.  Shift that result 8 bits right with sign extension so that the final result is a signed 32-bit integer with possible values from -2²³ up to (2²³-1).

Sign extension occurs – usually – because in many implementations of C, the &gt;&gt; operator does an arithmetic shift instead of a logical shift when its operand is signed.