Maxim Integrated MAX11131 SPI 12-bit 16-channel ADC with SampleSet

Dependents:   MAX11131BOB_Tester MAX11131BOB_12bit_16ch_SampleSet_SPI_ADC MAX11131BOB_Serial_Tester

Revision:
0:f7d706d2904d
Child:
1:77f1ee332e4a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX11131.cpp	Wed Jun 05 02:16:46 2019 +0000
@@ -0,0 +1,2767 @@
+// /*******************************************************************************
+// * Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved.
+// *
+// * Permission is hereby granted, free of charge, to any person obtaining a
+// * copy of this software and associated documentation files (the "Software"),
+// * to deal in the Software without restriction, including without limitation
+// * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// * and/or sell copies of the Software, and to permit persons to whom the
+// * Software is furnished to do so, subject to the following conditions:
+// *
+// * The above copyright notice and this permission notice shall be included
+// * in all copies or substantial portions of the Software.
+// *
+// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+// * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// * OTHER DEALINGS IN THE SOFTWARE.
+// *
+// * Except as contained in this notice, the name of Maxim Integrated
+// * Products, Inc. shall not be used except as stated in the Maxim Integrated
+// * Products, Inc. Branding Policy.
+// *
+// * The mere transfer of this software does not imply any licenses
+// * of trade secrets, proprietary technology, copyrights, patents,
+// * trademarks, maskwork rights, or any other form of intellectual
+// * property whatsoever. Maxim Integrated Products, Inc. retains all
+// * ownership rights.
+// *******************************************************************************
+// */
+// *********************************************************************
+// @file MAX11131.cpp
+// *********************************************************************
+// Device Driver file
+// DO NOT EDIT; except areas designated "CUSTOMIZE". Automatically generated file.
+// generated by XMLSystemOfDevicesToMBED.py
+// System Name = ExampleSystem
+// System Description = Device driver example
+
+#include "MAX11131.h"
+
+// Device Name = MAX11131
+// Device Description = 3Msps, Low-Power, Serial SPI 12-Bit, 16-Channel, Differential/Single-Ended Input, SAR ADC
+// Device Manufacturer = Maxim Integrated
+// Device PartNumber = MAX11131ATI+
+// Device RegValue_Width = DataWidth16bit_HL
+//
+// ADC MaxOutputDataRate = 3Msps
+// ADC NumChannels = 16
+// ADC ResolutionBits = 12
+//
+// SPI CS = ActiveLow
+// SPI FrameStart = CS
+// SPI CPOL = 1
+// SPI CPHA = 1
+// SPI MOSI and MISO Data are both stable on Rising edge of SCLK
+// SPI SCLK Idle High
+// SPI SCLKMaxMHz = 48
+// SPI SCLKMinMHz = 0.48
+//
+// InputPin Name = CNVST
+// InputPin Description = Active-Low Conversion Start Input/Analog Input 14
+// InputPin Function = Trigger
+//
+// InputPin Name = REF+
+// InputPin Description = External Positive Reference Input. Apply a reference voltage at REF+. Bypass to GND with a 0.47uF capacitor.
+// InputPin Function = Reference
+//
+// InputPin Name = REF-/AIN15
+// InputPin Description = External Differential Reference Negative Input/Analog Input 15
+// InputPin Function = Reference
+//
+// OutputPin Name = EOC
+// OutputPin Description = End of Conversion Output. Data is valid after EOC pulls low (Internal clock mode only).
+// OutputPin Function = Event
+//
+// SupplyPin Name = VDD
+// SupplyPin Description = Power-Supply Input. Bypass to GND with a 10uF in parallel with a 0.1uF capacitors.
+// SupplyPin VinMax = 3.6
+// SupplyPin VinMin = 2.35
+// SupplyPin Function = Analog
+//
+// SupplyPin Name = OVDD
+// SupplyPin Description = Interface Digital Power-Supply Input. Bypass to GND with a 10uF in parallel with a 0.1uF capacitors.
+// SupplyPin VinMax = 3.6
+// SupplyPin VinMin = 1.5
+// SupplyPin Function = Digital
+//
+
+// CODE GENERATOR: class constructor definition
+MAX11131::MAX11131(SPI &spi, DigitalOut &cs_pin, // SPI interface
+                 // CODE GENERATOR: class constructor definition gpio InputPin pins
+                 DigitalOut &CNVST_pin, // Digital Trigger Input to MAX11131 device
+                 // AnalogOut &REF__pin, // Reference Input to MAX11131 device
+                 // AnalogOut &REF__AIN15_pin, // Reference Input to MAX11131 device
+                 // CODE GENERATOR: class constructor definition gpio OutputPin pins
+                 DigitalIn &EOC_pin, // Digital Event Output from MAX11131 device
+                 // CODE GENERATOR: class constructor definition ic_variant
+                 MAX11131_ic_t ic_variant)
+    // CODE GENERATOR: class constructor initializer list
+    : m_spi(spi), m_cs_pin(cs_pin), // SPI interface
+    // CODE GENERATOR: class constructor initializer list gpio InputPin pins
+    m_CNVST_pin(CNVST_pin), // Digital Trigger Input to MAX11131 device
+    // m_REF__pin(REF__pin), // Reference Input to MAX11131 device
+    // m_REF__AIN15_pin(REF__AIN15_pin), // Reference Input to MAX11131 device
+    // CODE GENERATOR: class constructor initializer list gpio OutputPin pins
+    m_EOC_pin(EOC_pin), // Digital Event Output from MAX11131 device
+    // CODE GENERATOR: class constructor initializer list ic_variant
+    m_ic_variant(ic_variant)
+{
+    // CODE GENERATOR: class constructor definition SPI interface initialization
+    //
+    // SPI CS = ActiveLow
+    // SPI FrameStart = CS
+    m_SPI_cs_state = 1;
+    m_cs_pin = m_SPI_cs_state;
+
+    // SPI CPOL = 1
+    // SPI CPHA = 1
+    // SPI MOSI and MISO Data are both stable on Rising edge of SCLK
+    // SPI SCLK Idle High
+    m_SPI_dataMode = 3; //SPI_MODE3 // CPOL=1,CPHA=1: Rising Edge stable; SCLK idle High
+    m_spi.format(8,m_SPI_dataMode);         // int bits_must_be_8, int mode=0_3 CPOL=0,CPHA=0
+
+    // SPI SCLKMaxMHz = 48
+    // SPI SCLKMinMHz = 0.48
+    //#define SPI_SCLK_Hz 48000000 // 48MHz
+    //#define SPI_SCLK_Hz 24000000 // 24MHz
+    //#define SPI_SCLK_Hz 12000000 // 12MHz
+    //#define SPI_SCLK_Hz 4000000 // 4MHz
+    //#define SPI_SCLK_Hz 2000000 // 2MHz
+    //#define SPI_SCLK_Hz 1000000 // 1MHz
+    m_SPI_SCLK_Hz = 12000000; // 12MHz; MAX11131 limit is 48MHz
+    m_spi.frequency(m_SPI_SCLK_Hz);
+
+    // TODO1: CODE GENERATOR: class constructor definition gpio InputPin (Input to device) initialization
+    //
+    m_CNVST_pin = 1; // output logic high -- initial value in constructor
+}
+
+// CODE GENERATOR: class destructor definition
+MAX11131::~MAX11131()
+{
+    // do nothing
+}
+
+// CODE GENERATOR: spi_frequency setter definition
+// set SPI SCLK frequency
+void MAX11131::spi_frequency(int spi_sclk_Hz)
+{
+    m_SPI_SCLK_Hz = spi_sclk_Hz;
+    m_spi.frequency(m_SPI_SCLK_Hz);
+}
+
+// CODE GENERATOR: omit global g_MAX11131_device
+// CODE GENERATOR: extern function declarations
+// CODE GENERATOR: extern function requirement MAX11131::SPIoutputCS
+// Assert SPI Chip Select
+// SPI chip-select for MAX11131
+//
+void MAX11131::SPIoutputCS(int isLogicHigh)
+{
+    // CODE GENERATOR: extern function definition for function SPIoutputCS
+    // CODE GENERATOR: extern function definition for standard SPI interface function SPIoutputCS(int isLogicHigh)
+    m_SPI_cs_state = isLogicHigh;
+    m_cs_pin = m_SPI_cs_state;
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::SPIwrite16bits
+// SPI write 16 bits
+// SPI interface to MAX11131 shift 16 bits mosiData16 into MAX11131 DIN
+// ignoring MAX11131 DOUT
+//
+void MAX11131::SPIwrite16bits(int16_t mosiData16)
+{
+    // CODE GENERATOR: extern function definition for function SPIwrite16bits
+    // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function SPIwrite16bits(int16_t mosiData16)
+    size_t byteCount = 2;
+    static char mosiData[2];
+    static char misoData[2];
+    mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte
+    mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ noInterrupts();
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
+    //
+    unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
+    //~ m_spi.transfer(mosiData8_FF0000);
+    //~ m_spi.transfer(mosiData16_00FF00);
+    //~ m_spi.transfer(mosiData16_0000FF);
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ interrupts();
+    //
+    // VERIFY: SPIwrite24bits print diagnostic information
+    //cmdLine.serial().printf(" MOSI->"));
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
+    // hex dump mosiData[0..byteCount-1]
+#if 0 // HAS_MICROUSBSERIAL
+    cmdLine_microUSBserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_microUSBserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_microUSBserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_microUSBserial.serial().printf(" ");
+#endif
+#if 0 // HAS_DAPLINK_SERIAL
+    cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_DAPLINKserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" ");
+#endif
+    // VERIFY: DIAGNOSTIC: print MAX5715 device register write
+    // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
+    // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF);
+    //
+    // int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF;
+    // return misoData16;
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::SPIwrite24bits
+// SPI write 17-24 bits
+// SPI interface to MAX11131 shift 16 bits mosiData16 into MAX11131 DIN
+// followed by one additional SCLK byte.
+// ignoring MAX11131 DOUT
+//
+void MAX11131::SPIwrite24bits(int16_t mosiData16_FFFF00, int8_t mosiData8_0000FF)
+{
+    // CODE GENERATOR: extern function definition for function SPIwrite24bits
+    // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function SPIwrite24bits(int16_t mosiData16_FFFF00, int8_t mosiData8_0000FF)
+    // TODO: implement SPIwrite24bits(int16_t mosiData16_FFFF00, int8_t mosiData8_0000FF)
+    size_t byteCount = 3;
+    static char mosiData[3];
+    static char misoData[3];
+    mosiData[0] = (char)((mosiData16_FFFF00 >> 8) & 0xFF); // MSByte
+    mosiData[1] = (char)((mosiData16_FFFF00 >> 0) & 0xFF); // LSByte
+    mosiData[2] = mosiData8_0000FF;
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ noInterrupts();
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
+    //
+    unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
+    //~ m_spi.transfer(mosiData8_FF0000);
+    //~ m_spi.transfer(mosiData16_00FF00);
+    //~ m_spi.transfer(mosiData16_0000FF);
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ interrupts();
+    //
+    // VERIFY: SPIwrite24bits print diagnostic information
+    //cmdLine.serial().printf(" MOSI->"));
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
+    // hex dump mosiData[0..byteCount-1]
+#if 0 // HAS_MICROUSBSERIAL
+    cmdLine_microUSBserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_microUSBserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_microUSBserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_microUSBserial.serial().printf(" ");
+#endif
+#if 0 // HAS_DAPLINK_SERIAL
+    cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_DAPLINKserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" ");
+#endif
+    // VERIFY: DIAGNOSTIC: print MAX5715 device register write
+    // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
+    //
+    // int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF;
+    // return misoData16;
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::SPIread16bits
+// SPI read 16 bits while MOSI (MAX11131 DIN) is 0
+// SPI interface to capture 16 bits miso data from MAX11131 DOUT
+//
+int16_t MAX11131::SPIread16bits()
+{
+    // CODE GENERATOR: extern function definition for function SPIread16bits
+    // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function int16_t SPIread16bits()
+    int mosiData16 = 0;
+    size_t byteCount = 2;
+    static char mosiData[2];
+    static char misoData[2];
+    mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte
+    mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ noInterrupts();
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
+    //
+    unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
+    //~ m_spi.transfer(mosiData8_FF0000);
+    //~ m_spi.transfer(mosiData16_00FF00);
+    //~ m_spi.transfer(mosiData16_0000FF);
+    //
+    //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
+    //
+    // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
+    //~ interrupts();
+    //
+    // VERIFY: SPIwrite24bits print diagnostic information
+    //cmdLine.serial().printf(" MOSI->"));
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
+    //cmdLine.serial().printf(" 0x"));
+    //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
+    // hex dump mosiData[0..byteCount-1]
+#if 0 // HAS_MICROUSBSERIAL
+    cmdLine_microUSBserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_microUSBserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_microUSBserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_microUSBserial.serial().printf(" ");
+#endif
+#if 0 // HAS_DAPLINK_SERIAL
+    cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
+    if (byteCount > 7) {
+        cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" MOSI->");
+    for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
+    }
+    // hex dump misoData[0..byteCount-1]
+    cmdLine_DAPLINKserial.serial().printf("  MISO<-");
+    for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
+    {
+        cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
+    }
+    cmdLine_DAPLINKserial.serial().printf(" ");
+#endif
+    // VERIFY: DIAGNOSTIC: print MAX5715 device register write
+    // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
+    // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF);
+    //
+    int misoData16 = (misoData[0] << 8) | misoData[1];
+    return misoData16;
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::CNVSToutputPulseLow
+// Assert MAX11131 CNVST convert start.
+// Required when using any of the InternalClock modes with SWCNV 0.
+// Trigger measurement by driving CNVST/AIN14 pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+//
+void MAX11131::CNVSToutputPulseLow()
+{
+    // CODE GENERATOR: extern function definition for function CNVSToutputPulseLow
+    // TODO1: CODE GENERATOR: extern function definition for gpio interface function CNVSToutputPulseLow
+    // TODO1: CODE GENERATOR: gpio pin CNVST assuming member function m_CNVST_pin
+    // TODO1: CODE GENERATOR: gpio direction output
+    // m_CNVST_pin.output(); // only applicable to DigitalInOut
+    // TODO1: CODE GENERATOR: gpio function PulseLow
+    m_CNVST_pin = 0; // output logic low
+    wait(0.01); // pulse low delay time
+    m_CNVST_pin = 1; // output logic high
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::EOCinputWaitUntilLow
+// Wait for MAX11131 EOC pin low, indicating end of conversion.
+// Required when using any of the InternalClock modes.
+//
+void MAX11131::EOCinputWaitUntilLow()
+{
+    // CODE GENERATOR: extern function definition for function EOCinputWaitUntilLow
+    // TODO1: CODE GENERATOR: extern function definition for gpio interface function EOCinputWaitUntilLow
+    // TODO1: CODE GENERATOR: gpio pin EOC assuming member function m_EOC_pin
+    // TODO1: CODE GENERATOR: gpio direction input
+    // m_EOC_pin.input(); // only applicable to DigitalInOut
+    // TODO1: CODE GENERATOR: gpio function WaitUntilLow
+    while (m_EOC_pin != 0)
+    {
+        // spinlock waiting for logic low pin state
+    }
+}
+
+// CODE GENERATOR: extern function requirement MAX11131::EOCinputValue
+// Return the status of the MAX11131 EOC pin.
+//
+int MAX11131::EOCinputValue()
+{
+    // CODE GENERATOR: extern function definition for function EOCinputValue
+    // TODO1: CODE GENERATOR: extern function definition for gpio interface function EOCinputValue
+    // TODO1: CODE GENERATOR: gpio pin EOC assuming member function m_EOC_pin
+    // TODO1: CODE GENERATOR: gpio direction input
+    // m_EOC_pin.input(); // only applicable to DigitalInOut
+    // TODO1: CODE GENERATOR: gpio function Value
+    return m_EOC_pin.read();
+}
+
+// CODE GENERATOR: class member function definitions
+//----------------------------------------
+// Initialize device
+void MAX11131::Init(void)
+{
+    
+    //----------------------------------------
+    // Nominal Full-Scale Voltage Reference
+    VRef = 2.500;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only register ADC_CONFIGURATION
+    ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0
+    const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL
+    const int AVGON_LSB  =  9; const int AVGON_BITS  = 0x01; // ADC_CONFIGURATION.AVGON
+    const int NAVG_LSB   =  7; const int NAVG_BITS   = 0x03; // ADC_CONFIGURATION.NAVG[1:0]
+    const int NSCAN_LSB  =  5; const int NSCAN_BITS  = 0x03; // ADC_CONFIGURATION.NSCAN[1:0]
+    const int SPM_LSB    =  3; const int SPM_BITS    = 0x03; // ADC_CONFIGURATION.SPM[1:0]
+    const int ECHO_LSB   =  2; const int ECHO_BITS   = 0x01; // ADC_CONFIGURATION.ECHO
+    
+    //----------------------------------------
+    // define write-only registers UNIPOLAR,BIPOLAR,RANGE
+    UNIPOLAR = 0x8800;          //!< mosiData16 0x8800..0x8FFF format: 1 0 0 0 1 UCH0/1 UCH2/3 UCH4/5 UCH6/7 UCH8/9 UCH10/11 UCH12/13 UCH14/15 PDIFF_COM x x
+    BIPOLAR = 0x9000;           //!< mosiData16 0x9000..0x97FF format: 1 0 0 1 0 BCH0/1 BCH2/3 BCH4/5 BCH6/7 BCH8/9 BCH10/11 BCH12/13 BCH14/15 x x x
+    RANGE = 0x9800;             //!< mosiData16 0x9800..0x9FFF format: 1 0 0 1 1 RANGE0/1 RANGE2/3 RANGE4/5 RANGE6/7 RANGE8/9 RANGE10/11 RANGE12/13 RANGE14/15 x x x
+    const int AIN_0_1_LSB   = 10; // UNIPOLAR.UCH0/1    BIPOLAR.BCH0/1    RANGE.RANGE0/1  
+    const int AIN_2_3_LSB   =  9; // UNIPOLAR.UCH2/3    BIPOLAR.BCH2/3    RANGE.RANGE2/3  
+    const int AIN_4_5_LSB   =  8; // UNIPOLAR.UCH4/5    BIPOLAR.BCH4/5    RANGE.RANGE4/5  
+    const int AIN_6_7_LSB   =  7; // UNIPOLAR.UCH6/7    BIPOLAR.BCH6/7    RANGE.RANGE6/7  
+    const int AIN_8_9_LSB   =  6; // UNIPOLAR.UCH8/9    BIPOLAR.BCH8/9    RANGE.RANGE8/9  
+    const int AIN_10_11_LSB =  5; // UNIPOLAR.UCH10/11  BIPOLAR.BCH10/11  RANGE.RANGE10/11
+    const int AIN_12_13_LSB =  4; // UNIPOLAR.UCH12/13  BIPOLAR.BCH12/13  RANGE.RANGE12/13
+    const int AIN_14_15_LSB =  3; // UNIPOLAR.UCH14/15  BIPOLAR.BCH14/15  RANGE.RANGE14/15
+    const int PDIFF_COMM_LSB =  2; const int PDIFF_COMM_BITS =  0x01; // UNIPOLAR.PDIFF_COM
+    // Summary of Table 8:
+    // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+    // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+    // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+    // UCH0/1=1, BCH0/1=1, RANGE0/1=0: reserved do not use
+    // UCH0/1=0, BCH0/1=0, RANGE0/1=1: reserved do not use
+    // UCH0/1=1, BCH0/1=0, RANGE0/1=1: reserved do not use
+    // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+    // UCH0/1=1, BCH0/1=1, RANGE0/1=1: reserved do not use
+    // Both channels of a differential pair must be within Input Voltage Range (dynamic signal range) 0..VREF.
+    
+    //----------------------------------------
+    // define write-only registers CSCAN0,CSCAN1
+    CSCAN0 = 0xA000;            //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x
+    const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15
+    const int CHSCAN14_LSB =  9; // CSCAN0.CHSCAN14
+    const int CHSCAN13_LSB =  8; // CSCAN0.CHSCAN13
+    const int CHSCAN12_LSB =  7; // CSCAN0.CHSCAN12
+    const int CHSCAN11_LSB =  6; // CSCAN0.CHSCAN11
+    const int CHSCAN10_LSB =  5; // CSCAN0.CHSCAN10
+    const int CHSCAN9_LSB  =  4; // CSCAN0.CHSCAN9
+    const int CHSCAN8_LSB  =  3; // CSCAN0.CHSCAN8
+    CSCAN1 = 0xA800;            //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x
+    const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7
+    const int CHSCAN6_LSB =  9; // CSCAN1.CHSCAN6
+    const int CHSCAN5_LSB =  8; // CSCAN1.CHSCAN5
+    const int CHSCAN4_LSB =  7; // CSCAN1.CHSCAN4
+    const int CHSCAN3_LSB =  6; // CSCAN1.CHSCAN3
+    const int CHSCAN2_LSB =  5; // CSCAN1.CHSCAN2
+    const int CHSCAN1_LSB =  4; // CSCAN1.CHSCAN1
+    const int CHSCAN0_LSB =  3; // CSCAN1.CHSCAN0
+    
+    //----------------------------------------
+    // Initialize shadow of write-only register SAMPLESET.
+    // Do not write to SAMPLESET at this time.
+    // A write to SAMPLESET must be followed by specified number of pattern entry words.
+    // See ScanSampleSetExternalClock function for details.
+    SAMPLESET = 0xB000;         //!< mosiData16 0xB000..0xB7FF format: 1 0 1 1 0 SEQ_LENGTH[7:0] x x x
+    const int SAMPLESET_LSB   =  3; const int SAMPLESET_BITS   = 0xFF; // SAMPLESET.SEQ_LENGTH[7:0]
+    
+    //----------------------------------------
+    // Reset all registers: ADC_MODE_CONTROL.RESET[1:0] = 2
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((2 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+
+#if REFSEL_0
+    
+    //----------------------------------------
+    // Global setting for all channels: ADC_CONFIGURATION.REFSEL=0: external single-ended reference
+    // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL
+    // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL: EXTERNAL SINGLE-ENDED
+    // SELECT ADC CONFIGURATION register set REFSEL BIT TO 0
+    ADC_CONFIGURATION &= ~ ((    REFSEL_BITS) << REFSEL_LSB); // ADC_CONFIGURATION.REFSEL=0: external single-ended reference. (For the 16-channel chips: channel AIN15 is available.)
+#endif // REFSEL_0
+
+#if REFSEL_1
+    
+    //----------------------------------------
+    // Global setting for all channels: ADC_CONFIGURATION.REFSEL=1: external differential reference (For the 16-channel chips: channel AIN15 is unavailable, the pin is assigned to REF-.)
+    // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL
+    // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL: EXTERNAL DIFFERENTIAL
+    // SELECT ADC CONFIGURATION register set REFSEL BIT TO 1
+    ADC_CONFIGURATION |=   ((1 & REFSEL_BITS) << REFSEL_LSB); // ADC_CONFIGURATION.REFSEL=1: external differential reference. (For the 16-channel chips: channel AIN15 is unavailable, the pin is assigned to REF-.)
+#endif // REFSEL_1
+
+#if PDIFF_COMM_0
+    
+    //----------------------------------------
+    // Global setting for all channels: PDIFF_COMM
+    UNIPOLAR &= ~ ((    PDIFF_COMM_BITS) << PDIFF_COMM_LSB); // UNIPOLAR.PDIFF_COMM=0: all single-ended channels use GND as common
+#endif // PDIFF_COMM_0
+
+#if PDIFF_COMM_1
+    
+    //----------------------------------------
+    // Global setting for all channels: PDIFF_COMM
+    // SELECT UNIPOLAR AND register set BIT PDIFF_COM TO 1 FOR PSEUDODIFFERENTIAL SELECTION
+    UNIPOLAR |=   ((1 & PDIFF_COMM_BITS) << PDIFF_COMM_LSB); // UNIPOLAR.PDIFF_COMM=1: all single-ended channels are pseudo-differential with REF- as common
+#endif // PDIFF_COMM_1
+
+#if AIN_0_1_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN0, AIN1 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN0 is a Single-Ended input using Unipolar transfer function.
+    // AIN1 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN0 voltage must always be between 0 and VREF.
+    // AIN1 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_0_1_LSB);
+    BIPOLAR  &= ~ (1 << AIN_0_1_LSB);
+    RANGE    &= ~ (1 << AIN_0_1_LSB);
+    // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_0_1_SingleEnded
+
+#if AIN_0_1_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN0, AIN1 = Differential Unipolar (AIN0 > AIN1)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN0, AIN1 are a Differential pair using Unipolar transfer function.
+    // AIN0 voltage must always be between 0 and VREF.
+    // AIN1 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_0_1_LSB);
+    BIPOLAR  &= ~ (1 << AIN_0_1_LSB);
+    RANGE    &= ~ (1 << AIN_0_1_LSB);
+    // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_0_1_DifferentialUnipolar
+
+#if AIN_0_1_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN0, AIN1 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN0, AIN1 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN0 voltage must always be between 0 and VREF.
+    // AIN1 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_0_1_LSB);
+    BIPOLAR  |=   (1 << AIN_0_1_LSB);
+    RANGE    &= ~ (1 << AIN_0_1_LSB);
+    // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_0_1_DifferentialBipolarFSVref
+
+#if AIN_0_1_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN0, AIN1 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN0, AIN1 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN0 voltage must always be between 0 and VREF.
+    // AIN1 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_0_1_LSB);
+    BIPOLAR  |=   (1 << AIN_0_1_LSB);
+    RANGE    |=   (1 << AIN_0_1_LSB);
+    // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_0_1_DifferentialBipolarFS2Vref
+
+#if AIN_2_3_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN2, AIN3 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN2 is a Single-Ended input using Unipolar transfer function.
+    // AIN3 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN2 voltage must always be between 0 and VREF.
+    // AIN3 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_2_3_LSB);
+    BIPOLAR  &= ~ (1 << AIN_2_3_LSB);
+    RANGE    &= ~ (1 << AIN_2_3_LSB);
+    // UCH2/3=0, BCH2/3=0, RANGE2/3=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_2_3_SingleEnded
+
+#if AIN_2_3_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN2, AIN3 = Differential Unipolar (AIN2 > AIN3)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN2, AIN3 are a Differential pair using Unipolar transfer function.
+    // AIN2 voltage must always be between 0 and VREF.
+    // AIN3 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_2_3_LSB);
+    BIPOLAR  &= ~ (1 << AIN_2_3_LSB);
+    RANGE    &= ~ (1 << AIN_2_3_LSB);
+    // UCH2/3=1, BCH2/3=0, RANGE2/3=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_2_3_DifferentialUnipolar
+
+#if AIN_2_3_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN2, AIN3 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN2, AIN3 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN2 voltage must always be between 0 and VREF.
+    // AIN3 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_2_3_LSB);
+    BIPOLAR  |=   (1 << AIN_2_3_LSB);
+    RANGE    &= ~ (1 << AIN_2_3_LSB);
+    // UCH2/3=0, BCH2/3=1, RANGE2/3=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_2_3_DifferentialBipolarFSVref
+
+#if AIN_2_3_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN2, AIN3 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN2, AIN3 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN2 voltage must always be between 0 and VREF.
+    // AIN3 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_2_3_LSB);
+    BIPOLAR  |=   (1 << AIN_2_3_LSB);
+    RANGE    |=   (1 << AIN_2_3_LSB);
+    // UCH2/3=0, BCH2/3=1, RANGE2/3=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_2_3_DifferentialBipolarFS2Vref
+
+#if AIN_4_5_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN4, AIN5 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN4 is a Single-Ended input using Unipolar transfer function.
+    // AIN5 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN4 voltage must always be between 0 and VREF.
+    // AIN5 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_4_5_LSB);
+    BIPOLAR  &= ~ (1 << AIN_4_5_LSB);
+    RANGE    &= ~ (1 << AIN_4_5_LSB);
+    // UCH4/5=0, BCH4/5=0, RANGE4/5=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_4_5_SingleEnded
+
+#if AIN_4_5_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN4, AIN5 = Differential Unipolar (AIN4 > AIN5)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN4, AIN5 are a Differential pair using Unipolar transfer function.
+    // AIN4 voltage must always be between 0 and VREF.
+    // AIN5 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_4_5_LSB);
+    BIPOLAR  &= ~ (1 << AIN_4_5_LSB);
+    RANGE    &= ~ (1 << AIN_4_5_LSB);
+    // UCH4/5=1, BCH4/5=0, RANGE4/5=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_4_5_DifferentialUnipolar
+
+#if AIN_4_5_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN4, AIN5 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN4, AIN5 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN4 voltage must always be between 0 and VREF.
+    // AIN5 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_4_5_LSB);
+    BIPOLAR  |=   (1 << AIN_4_5_LSB);
+    RANGE    &= ~ (1 << AIN_4_5_LSB);
+    // UCH4/5=0, BCH4/5=1, RANGE4/5=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_4_5_DifferentialBipolarFSVref
+
+#if AIN_4_5_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN4, AIN5 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN4, AIN5 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN4 voltage must always be between 0 and VREF.
+    // AIN5 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_4_5_LSB);
+    BIPOLAR  |=   (1 << AIN_4_5_LSB);
+    RANGE    |=   (1 << AIN_4_5_LSB);
+    // UCH4/5=0, BCH4/5=1, RANGE4/5=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_4_5_DifferentialBipolarFS2Vref
+
+#if AIN_6_7_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN6, AIN7 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN6 is a Single-Ended input using Unipolar transfer function.
+    // AIN7 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN6 voltage must always be between 0 and VREF.
+    // AIN7 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_6_7_LSB);
+    BIPOLAR  &= ~ (1 << AIN_6_7_LSB);
+    RANGE    &= ~ (1 << AIN_6_7_LSB);
+    // UCH6/7=0, BCH6/7=0, RANGE6/7=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_6_7_SingleEnded
+
+#if AIN_6_7_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN6, AIN7 = Differential Unipolar (AIN6 > AIN7)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN6, AIN7 are a Differential pair using Unipolar transfer function.
+    // AIN6 voltage must always be between 0 and VREF.
+    // AIN7 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_6_7_LSB);
+    BIPOLAR  &= ~ (1 << AIN_6_7_LSB);
+    RANGE    &= ~ (1 << AIN_6_7_LSB);
+    // UCH6/7=1, BCH6/7=0, RANGE6/7=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_6_7_DifferentialUnipolar
+
+#if AIN_6_7_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN6, AIN7 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN6, AIN7 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN6 voltage must always be between 0 and VREF.
+    // AIN7 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_6_7_LSB);
+    BIPOLAR  |=   (1 << AIN_6_7_LSB);
+    RANGE    &= ~ (1 << AIN_6_7_LSB);
+    // UCH6/7=0, BCH6/7=1, RANGE6/7=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_6_7_DifferentialBipolarFSVref
+
+#if AIN_6_7_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN6, AIN7 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN6, AIN7 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN6 voltage must always be between 0 and VREF.
+    // AIN7 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_6_7_LSB);
+    BIPOLAR  |=   (1 << AIN_6_7_LSB);
+    RANGE    |=   (1 << AIN_6_7_LSB);
+    // UCH6/7=0, BCH6/7=1, RANGE6/7=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_6_7_DifferentialBipolarFS2Vref
+
+#if AIN_8_9_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN8, AIN9 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN8 is a Single-Ended input using Unipolar transfer function.
+    // AIN9 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN8 voltage must always be between 0 and VREF.
+    // AIN9 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_8_9_LSB);
+    BIPOLAR  &= ~ (1 << AIN_8_9_LSB);
+    RANGE    &= ~ (1 << AIN_8_9_LSB);
+    // UCH8/9=0, BCH8/9=0, RANGE8/9=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_8_9_SingleEnded
+
+#if AIN_8_9_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN8, AIN9 = Differential Unipolar (AIN8 > AIN9)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN8, AIN9 are a Differential pair using Unipolar transfer function.
+    // AIN8 voltage must always be between 0 and VREF.
+    // AIN9 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_8_9_LSB);
+    BIPOLAR  &= ~ (1 << AIN_8_9_LSB);
+    RANGE    &= ~ (1 << AIN_8_9_LSB);
+    // UCH8/9=1, BCH8/9=0, RANGE8/9=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_8_9_DifferentialUnipolar
+
+#if AIN_8_9_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN8, AIN9 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN8, AIN9 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN8 voltage must always be between 0 and VREF.
+    // AIN9 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_8_9_LSB);
+    BIPOLAR  |=   (1 << AIN_8_9_LSB);
+    RANGE    &= ~ (1 << AIN_8_9_LSB);
+    // UCH8/9=0, BCH8/9=1, RANGE8/9=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_8_9_DifferentialBipolarFSVref
+
+#if AIN_8_9_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN8, AIN9 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN8, AIN9 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN8 voltage must always be between 0 and VREF.
+    // AIN9 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_8_9_LSB);
+    BIPOLAR  |=   (1 << AIN_8_9_LSB);
+    RANGE    |=   (1 << AIN_8_9_LSB);
+    // UCH8/9=0, BCH8/9=1, RANGE8/9=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_8_9_DifferentialBipolarFS2Vref
+
+#if AIN_10_11_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN10, AIN11 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN10 is a Single-Ended input using Unipolar transfer function.
+    // AIN11 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN10 voltage must always be between 0 and VREF.
+    // AIN11 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_10_11_LSB);
+    BIPOLAR  &= ~ (1 << AIN_10_11_LSB);
+    RANGE    &= ~ (1 << AIN_10_11_LSB);
+    // UCH10/11=0, BCH10/11=0, RANGE10/11=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_10_11_SingleEnded
+
+#if AIN_10_11_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN10, AIN11 = Differential Unipolar (AIN10 > AIN11)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN10, AIN11 are a Differential pair using Unipolar transfer function.
+    // AIN10 voltage must always be between 0 and VREF.
+    // AIN11 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_10_11_LSB);
+    BIPOLAR  &= ~ (1 << AIN_10_11_LSB);
+    RANGE    &= ~ (1 << AIN_10_11_LSB);
+    // UCH10/11=1, BCH10/11=0, RANGE10/11=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_10_11_DifferentialUnipolar
+
+#if AIN_10_11_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN10, AIN11 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN10, AIN11 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN10 voltage must always be between 0 and VREF.
+    // AIN11 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_10_11_LSB);
+    BIPOLAR  |=   (1 << AIN_10_11_LSB);
+    RANGE    &= ~ (1 << AIN_10_11_LSB);
+    // UCH10/11=0, BCH10/11=1, RANGE10/11=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_10_11_DifferentialBipolarFSVref
+
+#if AIN_10_11_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN10, AIN11 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN10, AIN11 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN10 voltage must always be between 0 and VREF.
+    // AIN11 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_10_11_LSB);
+    BIPOLAR  |=   (1 << AIN_10_11_LSB);
+    RANGE    |=   (1 << AIN_10_11_LSB);
+    // UCH10/11=0, BCH10/11=1, RANGE10/11=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_10_11_DifferentialBipolarFS2Vref
+
+#if AIN_12_13_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN12, AIN13 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN12 is a Single-Ended input using Unipolar transfer function.
+    // AIN13 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN12 voltage must always be between 0 and VREF.
+    // AIN13 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_12_13_LSB);
+    BIPOLAR  &= ~ (1 << AIN_12_13_LSB);
+    RANGE    &= ~ (1 << AIN_12_13_LSB);
+    // UCH12/13=0, BCH12/13=0, RANGE12/13=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_12_13_SingleEnded
+
+#if AIN_12_13_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN12, AIN13 = Differential Unipolar (AIN12 > AIN13)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN12, AIN13 are a Differential pair using Unipolar transfer function.
+    // AIN12 voltage must always be between 0 and VREF.
+    // AIN13 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_12_13_LSB);
+    BIPOLAR  &= ~ (1 << AIN_12_13_LSB);
+    RANGE    &= ~ (1 << AIN_12_13_LSB);
+    // UCH12/13=1, BCH12/13=0, RANGE12/13=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_12_13_DifferentialUnipolar
+
+#if AIN_12_13_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN12, AIN13 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN12, AIN13 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN12 voltage must always be between 0 and VREF.
+    // AIN13 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_12_13_LSB);
+    BIPOLAR  |=   (1 << AIN_12_13_LSB);
+    RANGE    &= ~ (1 << AIN_12_13_LSB);
+    // UCH12/13=0, BCH12/13=1, RANGE12/13=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_12_13_DifferentialBipolarFSVref
+
+#if AIN_12_13_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN12, AIN13 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN12, AIN13 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN12 voltage must always be between 0 and VREF.
+    // AIN13 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_12_13_LSB);
+    BIPOLAR  |=   (1 << AIN_12_13_LSB);
+    RANGE    |=   (1 << AIN_12_13_LSB);
+    // UCH12/13=0, BCH12/13=1, RANGE12/13=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_12_13_DifferentialBipolarFS2Vref
+
+#if AIN_14_15_SingleEnded
+    
+    //----------------------------------------
+    // ADC Channels AIN14, AIN15 = Both Single-Ended, Unipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN14 is a Single-Ended input using Unipolar transfer function.
+    // AIN15 is a Single-Ended input using Unipolar transfer function.
+    // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+    // AIN14 voltage must always be between 0 and VREF.
+    // AIN15 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION
+    UNIPOLAR &= ~ (1 << AIN_14_15_LSB);
+    BIPOLAR  &= ~ (1 << AIN_14_15_LSB);
+    RANGE    &= ~ (1 << AIN_14_15_LSB);
+    // UCH14/15=0, BCH14/15=0, RANGE14/15=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_14_15_SingleEnded
+
+#if AIN_14_15_DifferentialUnipolar
+    
+    //----------------------------------------
+    // ADC Channels AIN14, AIN15 = Differential Unipolar (AIN14 > AIN15)
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN14, AIN15 are a Differential pair using Unipolar transfer function.
+    // AIN14 voltage must always be between 0 and VREF.
+    // AIN15 voltage must always be between 0 and VREF.
+    //
+    // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR
+    UNIPOLAR |=   (1 << AIN_14_15_LSB);
+    BIPOLAR  &= ~ (1 << AIN_14_15_LSB);
+    RANGE    &= ~ (1 << AIN_14_15_LSB);
+    // UCH14/15=1, BCH14/15=0, RANGE14/15=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_14_15_DifferentialUnipolar
+
+#if AIN_14_15_DifferentialBipolarFSVref
+    
+    //----------------------------------------
+    // ADC Channels AIN14, AIN15 = Differential Bipolar
+    // Full Scale = VREF
+    // Voltage per LSB count = VREF/4096
+    // AIN14, AIN15 are a Differential pair using Bipolar transfer function with range ±½Vref
+    // AIN14 voltage must always be between 0 and VREF.
+    // AIN15 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2
+    UNIPOLAR &= ~ (1 << AIN_14_15_LSB);
+    BIPOLAR  |=   (1 << AIN_14_15_LSB);
+    RANGE    &= ~ (1 << AIN_14_15_LSB);
+    // UCH14/15=0, BCH14/15=1, RANGE14/15=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+#endif // AIN_14_15_DifferentialBipolarFSVref
+
+#if AIN_14_15_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // ADC Channels AIN14, AIN15 = Differential Bipolar
+    // Full Scale = 2 * VREF
+    // Voltage per LSB count = VREF/2048
+    // AIN14, AIN15 are a Differential pair using Bipolar transfer function with range ±Vref
+    // AIN14 voltage must always be between 0 and VREF.
+    // AIN15 voltage must always be between 0 and VREF.
+    //
+    // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL
+    // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+
+    UNIPOLAR &= ~ (1 << AIN_14_15_LSB);
+    BIPOLAR  |=   (1 << AIN_14_15_LSB);
+    RANGE    |=   (1 << AIN_14_15_LSB);
+    // UCH14/15=0, BCH14/15=1, RANGE14/15=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+#endif // AIN_14_15_DifferentialBipolarFS2Vref
+    
+    //----------------------------------------
+    // SPI write ADC CONFIGURATION register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_CONFIGURATION);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // SPI write UNIPOLAR BIPOLAR RANGE registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(UNIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(BIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(RANGE);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // SPI write CSCAN0 CSCAN1 registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN0);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN1);
+    SPIoutputCS(1); // drive CS high
+}
+
+//----------------------------------------
+// ADC Channels AIN(channelId), AIN(channelId+1) = Both Single-Ended, Unipolar
+// Full Scale = VREF
+// Voltage per LSB count = VREF/4096
+// AIN(channelId) is a Single-Ended input using Unipolar transfer function.
+// AIN(channelId+1) is a Single-Ended input using Unipolar transfer function.
+// If PDIFF_COM_1, both are Pseudo-Differential with REF- as common.
+// AIN(channelId) voltage must always be between 0 and VREF.
+// AIN(channelId+1) voltage must always be between 0 and VREF.
+//
+void MAX11131::Reconfigure_SingleEnded(int channelNumber_0_15)
+{
+    
+    //----------------------------------------
+    // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=0, RANGE(ch)/(ch+1)=0:
+    // AIN(ch)/AIN(ch+1) two independent single-ended inputs,
+    // unipolar code (Full Scale = VREF, LSB = VREF/4096)
+    // 
+    const int channelPairIndex = channelNumber_0_15 / 2;
+    const int bitmask = (1 << (10 - channelPairIndex));
+    UNIPOLAR &= ~ bitmask;
+    BIPOLAR  &= ~ bitmask;
+    RANGE    &= ~ bitmask;
+    
+    //----------------------------------------
+    // SPI write UNIPOLAR BIPOLAR RANGE registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(UNIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(BIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(RANGE);
+    SPIoutputCS(1); // drive CS high
+}
+
+//----------------------------------------
+// ADC Channels AIN(channelId), AIN(channelId+1) = Differential Unipolar (AIN(channelId) > AIN(channelId+1))
+// Full Scale = VREF
+// Voltage per LSB count = VREF/4096
+// AIN(channelId), AIN(channelId+1) are a Differential pair using Unipolar transfer function.
+// AIN(channelId) voltage must always be between 0 and VREF.
+// AIN(channelId+1) voltage must always be between 0 and VREF.
+//
+void MAX11131::Reconfigure_DifferentialUnipolar(int channelNumber_0_15)
+{
+    
+    //----------------------------------------
+    // UCH(ch)/(ch+1)=1, BCH(ch)/(ch+1)=0, RANGE(ch)/(ch+1)=0:
+    // AIN(ch)/AIN(ch+1) differential input pair,
+    // unipolar code (AIN(ch)>AIN(ch+1)) (Full Scale = VREF, LSB = VREF/4096)
+    // 
+    const int channelPairIndex = channelNumber_0_15 / 2;
+    const int bitmask = (1 << (10 - channelPairIndex));
+    UNIPOLAR |=   bitmask;
+    BIPOLAR  &= ~ bitmask;
+    RANGE    &= ~ bitmask;
+    // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+    
+    //----------------------------------------
+    // SPI write UNIPOLAR BIPOLAR RANGE registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(UNIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(BIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(RANGE);
+    SPIoutputCS(1); // drive CS high
+}
+
+//----------------------------------------
+// ADC Channels AIN(channelId), AIN(channelId+1) = Differential Bipolar
+// Full Scale = VREF
+// Voltage per LSB count = VREF/4096
+// AIN(channelId), AIN(channelId+1) are a Differential pair using Bipolar transfer function with range ±½Vref
+// AIN(channelId) voltage must always be between 0 and VREF.
+// AIN(channelId+1) voltage must always be between 0 and VREF.
+//
+void MAX11131::Reconfigure_DifferentialBipolarFSVref(int channelNumber_0_15)
+{
+    
+    //----------------------------------------
+    // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=1, RANGE(ch)/(ch+1)=0:
+    // AIN(ch)/AIN(ch+1) differential input pair ±½Vref,
+    // bipolar code (Full Scale = VREF, LSB = VREF/4096)
+    // 
+    const int channelPairIndex = channelNumber_0_15 / 2;
+    const int bitmask = (1 << (10 - channelPairIndex));
+    UNIPOLAR &= ~ bitmask;
+    BIPOLAR  |=   bitmask;
+    RANGE    &= ~ bitmask;
+    
+    //----------------------------------------
+    // SPI write UNIPOLAR BIPOLAR RANGE registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(UNIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(BIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(RANGE);
+    SPIoutputCS(1); // drive CS high
+}
+
+//----------------------------------------
+// ADC Channels AIN(channelId), AIN(channelId+1) = Differential Bipolar
+// Full Scale = 2 * VREF
+// Voltage per LSB count = VREF/2048
+// AIN(channelId), AIN(channelId+1) are a Differential pair using Bipolar transfer function with range ±Vref
+// AIN(channelId) voltage must always be between 0 and VREF.
+// AIN(channelId+1) voltage must always be between 0 and VREF.
+//
+void MAX11131::Reconfigure_DifferentialBipolarFS2Vref(int channelNumber_0_15)
+{
+    
+    //----------------------------------------
+    // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=1, RANGE(ch)/(ch+1)=1:
+    // AIN(ch)/AIN(ch+1) differential input pair ±Vref,
+    // bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+    // 
+    const int channelPairIndex = channelNumber_0_15 / 2;
+    const int bitmask = (1 << (10 - channelPairIndex));
+    UNIPOLAR &= ~ bitmask;
+    BIPOLAR  |=   bitmask;
+    RANGE    |=   bitmask;
+    // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+    
+    //----------------------------------------
+    // SPI write UNIPOLAR BIPOLAR RANGE registers
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(UNIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(BIPOLAR);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(RANGE);
+    SPIoutputCS(1); // drive CS high
+}
+
+//----------------------------------------
+// SCAN_0000_NOP
+//
+// Shift 16 bits out of ADC, without changing configuration.
+// Note: @return data format depends on CHAN_ID bit:
+//     "CH[3:0] DATA[11:0]" when CHAN_ID = 1, or
+//     "0 DATA[11:0] x x x" when CHAN_ID = 0.
+int16_t MAX11131::ScanRead(void)
+{
+    
+    //----------------------------------------
+    // Read SPI data from device while MOSI (Maxim DIN) is 0. Effectively ADC_MODE_CONTROL SCAN[3:0] = SCAN_0000_NOP = 0
+    SPI_MOSI_Semantic = 0; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    int16_t misoData16 = SPIread16bits();
+    SPIoutputCS(1); // drive CS high
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    return misoData16;
+}
+
+//----------------------------------------
+// SCAN_0000_NOP
+//
+// Read raw ADC codes from device into AINcode[] and RAW_misoData16[].
+// If internal clock mode with SWCNV=0, measurements will be triggered using CNVST pin.
+//
+// @pre one of the Scan functions was called, setting NumWords
+// @post RAW_misoData16[index] contains the raw SPI Master-In,Slave-Out data
+// @post AINcode[NUM_CHANNELS] contains the latest readings in LSBs
+//
+void MAX11131::ReadAINcode(void)
+{
+    
+    //----------------------------------------
+    // loop index for RAW_misoData16[SAMPLESET_MAX_ENTRIES];
+    int index;
+    
+    //----------------------------------------
+    // If internal clock mode with SWCNV=0, trigger measurement using CNVST pin and wait for EOC pin.
+      if (isExternalClock == 0)
+      {
+        if (swcnv_0_1 == 0)
+        {
+          // SWCNV=0: trigger measurement by driving CNVST/AIN14 pin low
+          // for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+          // One CNVST pulse scans all requested channels and stores the results in the FIFO.
+          CNVSToutputPulseLow();
+        }
+        // wait for EOC low (internal clock mode end of conversion)
+        EOCinputWaitUntilLow();
+      }
+    
+    //----------------------------------------
+    // Read raw ADC codes from device into AINcode[] and RAW_misoData16[].
+      // For external clock modes, the data format returned depends on the CHAN_ID bit.
+      //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+      //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+      // For internal clock modes, the data format always includes the channel address.
+      //     misoData16 = CH[3:0] DATA[11:0]
+      switch(ScanMode)
+      {
+        //----------------------------------------
+        // read data words
+        // For internal clock modes, the data format always includes the channel address.
+        //     misoData16 = CH[3:0] DATA[11:0]
+      case SCAN_0000_NOP:
+      case SCAN_0011_StandardInternalClock:
+      case SCAN_0101_UpperInternalClock:
+      case SCAN_0111_CustomInternalClock:
+      default:
+          for (index = 0; index < NumWords; index++) {
+            RAW_misoData16[index] = ScanRead();
+            // For internal clock modes, the data format always includes the channel address.
+            //     misoData16 = CH[3:0] DATA[11:0]
+            int16_t value_u12 = (RAW_misoData16[index] & 0x0FFF);
+            int channelId = ((RAW_misoData16[index] >> 12) & 0x000F);
+            AINcode[channelId] = value_u12;
+          }
+        break;
+        //----------------------------------------
+        // read data words
+        // For external clock modes, the data format returned depends on the CHAN_ID bit.
+        //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+        //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+        // For internal clock modes, the data format always includes the channel address.
+        //     misoData16 = CH[3:0] DATA[11:0]
+      case SCAN_0001_Manual:
+      case SCAN_0100_StandardExternalClock:
+      case SCAN_0110_UpperExternalClock:
+      case SCAN_1000_CustomExternalClock:
+      case SCAN_1001_SampleSetExternalClock:
+        if (chan_id_0_1 != 0) {
+          for (index = 0; index < NumWords; index++) {
+            RAW_misoData16[index] = ScanRead();
+            // For internal clock modes, the data format always includes the channel address.
+            //     misoData16 = CH[3:0] DATA[11:0]
+            int16_t value_u12 = (RAW_misoData16[index] & 0x0FFF);
+            int channelId = ((RAW_misoData16[index] >> 12) & 0x000F);
+            AINcode[channelId] = value_u12;
+          }
+        } else {
+          for (index = 0; index < NumWords; index++) {
+            RAW_misoData16[index] = ScanRead();
+            int16_t value_u12 = ((RAW_misoData16[index] >> 3) & 0x0FFF);
+            int channelId = channelNumber_0_15;
+            AINcode[channelId] = value_u12;
+          }
+        }
+        break;
+        //----------------------------------------
+        // read data words and calculate mean, stddev
+      case SCAN_0010_Repeat:
+        // ScanRead_nWords_chanID_mean(NumWords); // TODO1: missing function
+        // was this function AINcode_print_value_chanID_mean(int nWords) in main?
+        // But this function prints to standard output so can't be inside the driver.
+        for (index = 0; index < NumWords; index++) {
+          RAW_misoData16[index] = ScanRead();
+        }
+        break;
+      }
+}
+
+//----------------------------------------
+// Sign-Extend a right-aligned MAX11131 code into a signed 2's complement value.
+// Supports the bipolar transfer functions.
+// @param[in] value_u12: raw 12-bit MAX11131 code (right justified).
+// @return sign-extended 2's complement value.
+//
+int32_t MAX11131::TwosComplementValue(uint32_t regValue)
+{
+    const uint16_t SIGN_BIT_12BIT = 0x0800;
+    const uint16_t FULL_SCALE_CODE_12BIT = 0x0fff;
+    if (((regValue & SIGN_BIT_12BIT) != 0) && !((regValue & (SIGN_BIT_12BIT << 1)) != 0))
+    {
+        // (bSignBitNegative && !bExtendedSignBitNegative)
+        // Twos_Complement negative value
+        int32_t Offset_regValue = (int32_t)(regValue - (FULL_SCALE_CODE_12BIT + 1));
+        return Offset_regValue;
+    }
+    // Twos_Complement positive value or zero
+    return (int32_t)regValue;
+}
+
+//----------------------------------------
+// Return the physical voltage corresponding to MAX11131 code.
+// Does not perform any offset or gain correction.
+// @pre VRef = Voltage of REF input, in Volts
+// @param[in] value_u12: raw 12-bit MAX11131 code (right justified).
+// @param[in] channelId: AIN channel number.
+// @return physical voltage corresponding to MAX11131 code.
+//
+double MAX11131::VoltageOfCode(int16_t value_u12, int channelId)
+{
+    int channelPairIndex = channelId / 2;
+    // format: 1 0 0 0 1 UCH0/1 UCH2/3 UCH4/5 UCH6/7 UCH8/9 UCH10/11 UCH12/13 UCH14/15 PDIFF_COM x x
+    int UCHn = (UNIPOLAR >> (10 - channelPairIndex)) & 0x01;
+    int BCHn = (BIPOLAR >> (10 - channelPairIndex)) & 0x01;
+    int RANGEn = (RANGE >> (10 - channelPairIndex)) & 0x01;
+    if (UCHn)
+    {
+        // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096)
+        return (value_u12 * VRef / 4096);
+    }
+    else
+    {
+        if (BCHn)
+        {
+            if (RANGEn)
+            {
+                // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair ±Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048)
+                return (TwosComplementValue(value_u12) * VRef / 2048);
+            }
+            else
+            {
+                // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair ±½Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096)
+                return (TwosComplementValue(value_u12) * VRef / 4096);
+            }
+        }
+        else
+        {
+            // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096)
+            return (value_u12 * VRef / 4096);
+        }
+    }
+}
+
+//----------------------------------------
+// SCAN_0001_Manual
+//
+// Measure ADC channel channelNumber_0_15 once.
+// External clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID
+// @return number of ScanRead() words needed to retrieve the data.
+// For external clock modes, the data format depends on CHAN_ID.
+//     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+//     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanManual(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = 1;
+    
+    //----------------------------------------
+    // External Clock Mode
+    isExternalClock = 1;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0001_Manual;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0001_Manual = 1
+    //~ const int SCAN_0001_Manual = 1; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0001_Manual & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT
+    // (applicable to external clock mode only)
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    ADC_MODE_CONTROL |=   ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB);
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0010_Repeat
+//
+// Measure ADC channel channelNumber_0_15 repeatedly with averaging.
+// Internal clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word.
+//     average_0_4_8_16_32=0 to disable averaging.
+// @param[in] nscan_4_8_12_16: Number of ScanRead() words to report.
+// @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV
+//     SWCNV=0: trigger measurement by driving CNVST pin low.
+//         Minimum active-low pulse duration of 5ns. (AIN14 is not available)
+//     SWCNV=1: trigger measurement on SPI CS rising edge.
+//         CS must be held low for minimum of 17 SCLK cycles.
+//         CNVST pin is not used. (AIN14 is available)
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @return number of ScanRead() words needed to retrieve the data.
+// For internal clock modes, the data format always includes the channel address.
+//     misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanRepeat(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = (nscan_4_8_12_16);
+    
+    //----------------------------------------
+    // Internal Clock Mode
+    isExternalClock = 0;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0010_Repeat;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only register ADC_CONFIGURATION
+    ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0
+    const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL
+    const int AVGON_LSB  =  9; const int AVGON_BITS  = 0x01; // ADC_CONFIGURATION.AVGON
+    const int NAVG_LSB   =  7; const int NAVG_BITS   = 0x03; // ADC_CONFIGURATION.NAVG[1:0]
+    const int NSCAN_LSB  =  5; const int NSCAN_BITS  = 0x03; // ADC_CONFIGURATION.NSCAN[1:0]
+    const int SPM_LSB    =  3; const int SPM_BITS    = 0x03; // ADC_CONFIGURATION.SPM[1:0]
+    const int ECHO_LSB   =  2; const int ECHO_BITS   = 0x01; // ADC_CONFIGURATION.ECHO
+    
+    //----------------------------------------
+    // if average, ADC CONFIGURATION register set AVG and NAVG[1:0]
+    // (applicable to internal clock mode only)
+    // if average, ADC CONFIGURATION register set AVG ON BIT TO 1
+    // if average, ADC CONFIGURATION register set NAVG[1:0] TO N
+    if (average_0_4_8_16_32 == 4) {
+        // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((0 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 8) {
+        // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((1 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 16) {
+        // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((2 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 32) {
+        // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((3 & NAVG_BITS) << NAVG_LSB);
+    } else {
+        // Disable Averaging (AVGON=0, NAVG[1:0]=0)
+        ADC_CONFIGURATION &= ~ ((    AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+    }
+    
+    //----------------------------------------
+    // ADC CONFIGURATION register set NSCAN[1:0] for scan count
+    // (applicable to SCAN_0010_Repeat only)
+    if (nscan_4_8_12_16 == 4) {
+        // Set scan count 4
+        ADC_CONFIGURATION &= ~ ((    NSCAN_BITS) << NSCAN_LSB);
+        ADC_CONFIGURATION |=   ((0 & NSCAN_BITS) << NSCAN_LSB);
+    } else if (nscan_4_8_12_16 == 8) {
+        // Set scan count 8
+        ADC_CONFIGURATION &= ~ ((    NSCAN_BITS) << NSCAN_LSB);
+        ADC_CONFIGURATION |=   ((1 & NSCAN_BITS) << NSCAN_LSB);
+    } else if (nscan_4_8_12_16 == 12) {
+        // Set scan count 12
+        ADC_CONFIGURATION &= ~ ((    NSCAN_BITS) << NSCAN_LSB);
+        ADC_CONFIGURATION |=   ((2 & NSCAN_BITS) << NSCAN_LSB);
+    } else if (nscan_4_8_12_16 == 16) {
+        // Set scan count 16
+        ADC_CONFIGURATION &= ~ ((    NSCAN_BITS) << NSCAN_LSB);
+        ADC_CONFIGURATION |=   ((3 & NSCAN_BITS) << NSCAN_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC CONFIGURATION register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_CONFIGURATION);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0010_Repeat = 2
+    //~ const int SCAN_0010_Repeat = 2; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0010_Repeat & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SWCNV if CNVST pin is not used
+    // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT
+    // (applicable to internal clock mode only)
+    // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available)
+    // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+    if (swcnv_0_1) {
+        ADC_MODE_CONTROL |=   ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB);
+    } else {
+        ADC_MODE_CONTROL &= ~ ((            SWCNV_BITS) << SWCNV_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    if (swcnv_0_1) {
+      // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+      // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17".
+      SPIwrite24bits(ADC_MODE_CONTROL, 0);
+    } else {
+      SPIwrite16bits(ADC_MODE_CONTROL);
+    }
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0011_StandardInternalClock
+//
+// Measure ADC channels in sequence from AIN0 to channelNumber_0_15.
+// Internal clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word.
+//     average_0_4_8_16_32=0 to disable averaging.
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV
+//     SWCNV=0: trigger measurement by driving CNVST pin low.
+//         Minimum active-low pulse duration of 5ns. (AIN14 is not available)
+//     SWCNV=1: trigger measurement on SPI CS rising edge.
+//         CS must be held low for minimum of 17 SCLK cycles.
+//         CNVST pin is not used. (AIN14 is available)
+// @return number of ScanRead() words needed to retrieve the data.
+// For internal clock modes, the data format always includes the channel address.
+//     misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanStandardInternalClock(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = (1 + channelNumber_0_15);
+    
+    //----------------------------------------
+    // Internal Clock Mode
+    isExternalClock = 0;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0011_StandardInternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only register ADC_CONFIGURATION
+    ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0
+    const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL
+    const int AVGON_LSB  =  9; const int AVGON_BITS  = 0x01; // ADC_CONFIGURATION.AVGON
+    const int NAVG_LSB   =  7; const int NAVG_BITS   = 0x03; // ADC_CONFIGURATION.NAVG[1:0]
+    const int NSCAN_LSB  =  5; const int NSCAN_BITS  = 0x03; // ADC_CONFIGURATION.NSCAN[1:0]
+    const int SPM_LSB    =  3; const int SPM_BITS    = 0x03; // ADC_CONFIGURATION.SPM[1:0]
+    const int ECHO_LSB   =  2; const int ECHO_BITS   = 0x01; // ADC_CONFIGURATION.ECHO
+    
+    //----------------------------------------
+    // if average, ADC CONFIGURATION register set AVG and NAVG[1:0]
+    // (applicable to internal clock mode only)
+    // if average, ADC CONFIGURATION register set AVG ON BIT TO 1
+    // if average, ADC CONFIGURATION register set NAVG[1:0] TO N
+    if (average_0_4_8_16_32 == 4) {
+        // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((0 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 8) {
+        // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((1 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 16) {
+        // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((2 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 32) {
+        // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((3 & NAVG_BITS) << NAVG_LSB);
+    } else {
+        // Disable Averaging (AVGON=0, NAVG[1:0]=0)
+        ADC_CONFIGURATION &= ~ ((    AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC CONFIGURATION register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_CONFIGURATION);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0011_StandardInternalClock = 3
+    //~ const int SCAN_0011_StandardInternalClock = 3; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0011_StandardInternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SWCNV if CNVST pin is not used
+    // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT
+    // (applicable to internal clock mode only)
+    // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available)
+    // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+    if (swcnv_0_1) {
+        ADC_MODE_CONTROL |=   ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB);
+    } else {
+        ADC_MODE_CONTROL &= ~ ((            SWCNV_BITS) << SWCNV_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    if (swcnv_0_1) {
+      // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+      // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17".
+      SPIwrite24bits(ADC_MODE_CONTROL, 0);
+    } else {
+      SPIwrite16bits(ADC_MODE_CONTROL);
+    }
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0100_StandardExternalClock
+//
+// Measure ADC channels in sequence from AIN0 to channelNumber_0_15.
+// External clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID
+// @return number of ScanRead() words needed to retrieve the data.
+// For external clock modes, the data format depends on CHAN_ID.
+//     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+//     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanStandardExternalClock(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = (1 + channelNumber_0_15);
+    
+    //----------------------------------------
+    // External Clock Mode
+    isExternalClock = 1;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0100_StandardExternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0100_StandardExternalClock = 4
+    //~ const int SCAN_0100_StandardExternalClock = 4; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0100_StandardExternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT
+    // (applicable to external clock mode only)
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    ADC_MODE_CONTROL |=   ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB);
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0101_UpperInternalClock
+//
+// Measure ADC channels in sequence from channelNumber_0_15 to AIN15.
+// Internal clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word.
+//     average_0_4_8_16_32=0 to disable averaging.
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV
+//     SWCNV=0: trigger measurement by driving CNVST pin low.
+//         Minimum active-low pulse duration of 5ns. (AIN14 is not available)
+//     SWCNV=1: trigger measurement on SPI CS rising edge.
+//         CS must be held low for minimum of 17 SCLK cycles.
+//         CNVST pin is not used. (AIN14 is available)
+// @return number of ScanRead() words needed to retrieve the data.
+// For internal clock modes, the data format always includes the channel address.
+//     misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanUpperInternalClock(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = (16 - channelNumber_0_15);
+    
+    //----------------------------------------
+    // Internal Clock Mode
+    isExternalClock = 0;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0101_UpperInternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only register ADC_CONFIGURATION
+    ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0
+    const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL
+    const int AVGON_LSB  =  9; const int AVGON_BITS  = 0x01; // ADC_CONFIGURATION.AVGON
+    const int NAVG_LSB   =  7; const int NAVG_BITS   = 0x03; // ADC_CONFIGURATION.NAVG[1:0]
+    const int NSCAN_LSB  =  5; const int NSCAN_BITS  = 0x03; // ADC_CONFIGURATION.NSCAN[1:0]
+    const int SPM_LSB    =  3; const int SPM_BITS    = 0x03; // ADC_CONFIGURATION.SPM[1:0]
+    const int ECHO_LSB   =  2; const int ECHO_BITS   = 0x01; // ADC_CONFIGURATION.ECHO
+    
+    //----------------------------------------
+    // if average, ADC CONFIGURATION register set AVG and NAVG[1:0]
+    // (applicable to internal clock mode only)
+    // if average, ADC CONFIGURATION register set AVG ON BIT TO 1
+    // if average, ADC CONFIGURATION register set NAVG[1:0] TO N
+    if (average_0_4_8_16_32 == 4) {
+        // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((0 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 8) {
+        // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((1 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 16) {
+        // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((2 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 32) {
+        // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((3 & NAVG_BITS) << NAVG_LSB);
+    } else {
+        // Disable Averaging (AVGON=0, NAVG[1:0]=0)
+        ADC_CONFIGURATION &= ~ ((    AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC CONFIGURATION register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_CONFIGURATION);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0101_UpperInternalClock = 5
+    //~ const int SCAN_0101_UpperInternalClock = 5; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0101_UpperInternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SWCNV if CNVST pin is not used
+    // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT
+    // (applicable to internal clock mode only)
+    // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available)
+    // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+    if (swcnv_0_1) {
+        ADC_MODE_CONTROL |=   ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB);
+    } else {
+        ADC_MODE_CONTROL &= ~ ((            SWCNV_BITS) << SWCNV_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    if (swcnv_0_1) {
+      // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+      // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17".
+      SPIwrite24bits(ADC_MODE_CONTROL, 0);
+    } else {
+      SPIwrite16bits(ADC_MODE_CONTROL);
+    }
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0110_UpperExternalClock
+//
+// Measure ADC channels in sequence from channelNumber_0_15 to AIN15.
+// External clock mode.
+// @param[in] channelNumber_0_15: AIN Channel Number
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID
+// @return number of ScanRead() words needed to retrieve the data.
+// For external clock modes, the data format depends on CHAN_ID.
+//     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+//     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanUpperExternalClock(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = (16 - channelNumber_0_15);
+    
+    //----------------------------------------
+    // External Clock Mode
+    isExternalClock = 1;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0110_UpperExternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0110_UpperExternalClock = 6
+    //~ const int SCAN_0110_UpperExternalClock = 6; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0110_UpperExternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT
+    // (applicable to external clock mode only)
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    ADC_MODE_CONTROL |=   ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB);
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_0111_CustomInternalClock
+//
+// Measure selected ADC channels in sequence from AIN0 to AIN15,
+//     using only the channels enabled by enabledChannelsMask.
+//     Bit 0x0001 enables AIN0.
+//     Bit 0x0002 enables AIN1.
+//     Bit 0x0004 enables AIN2.
+//     Bit 0x0008 enables AIN3.
+//     Bit 0x0010 enables AIN4.
+//     Bit 0x0020 enables AIN5.
+//     Bit 0x0040 enables AIN6.
+//     Bit 0x0080 enables AIN7.
+//     Bit 0x0100 enables AIN8.
+//     Bit 0x0200 enables AIN9.
+//     Bit 0x0400 enables AIN10.
+//     Bit 0x0800 enables AIN11.
+//     Bit 0x1000 enables AIN12.
+//     Bit 0x2000 enables AIN13.
+//     Bit 0x4000 enables AIN14.
+//     Bit 0x8000 enables AIN15.
+// Internal clock mode.
+// @param[in] enabledChannelsMask: Bitmap of AIN Channels to scan.
+// @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word.
+//     average_0_4_8_16_32=0 to disable averaging.
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV
+//     SWCNV=0: trigger measurement by driving CNVST pin low.
+//         Minimum active-low pulse duration of 5ns. (AIN14 is not available)
+//     SWCNV=1: trigger measurement on SPI CS rising edge.
+//         CS must be held low for minimum of 17 SCLK cycles.
+//         CNVST pin is not used. (AIN14 is available)
+// @return number of ScanRead() words needed to retrieve the data.
+// For internal clock modes, the data format always includes the channel address.
+//     misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanCustomInternalClock(void)
+{
+    
+    //----------------------------------------
+    // count nWords = number of set bits in enabledChannelsMask
+    uint16_t bitMask;
+    int nWords = 0;
+    for (bitMask = 0x8000; bitMask != 0; bitMask = bitMask / 2)
+    {
+        if (enabledChannelsMask & bitMask)
+        {
+            nWords++;
+        }
+    }
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = nWords;
+    
+    //----------------------------------------
+    // Internal Clock Mode
+    isExternalClock = 0;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_0111_CustomInternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only register ADC_CONFIGURATION
+    ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0
+    const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL
+    const int AVGON_LSB  =  9; const int AVGON_BITS  = 0x01; // ADC_CONFIGURATION.AVGON
+    const int NAVG_LSB   =  7; const int NAVG_BITS   = 0x03; // ADC_CONFIGURATION.NAVG[1:0]
+    const int NSCAN_LSB  =  5; const int NSCAN_BITS  = 0x03; // ADC_CONFIGURATION.NSCAN[1:0]
+    const int SPM_LSB    =  3; const int SPM_BITS    = 0x03; // ADC_CONFIGURATION.SPM[1:0]
+    const int ECHO_LSB   =  2; const int ECHO_BITS   = 0x01; // ADC_CONFIGURATION.ECHO
+    
+    //----------------------------------------
+    // define write-only registers CSCAN0,CSCAN1
+    CSCAN0 = 0xA000;            //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x
+    const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15
+    const int CHSCAN14_LSB =  9; // CSCAN0.CHSCAN14
+    const int CHSCAN13_LSB =  8; // CSCAN0.CHSCAN13
+    const int CHSCAN12_LSB =  7; // CSCAN0.CHSCAN12
+    const int CHSCAN11_LSB =  6; // CSCAN0.CHSCAN11
+    const int CHSCAN10_LSB =  5; // CSCAN0.CHSCAN10
+    const int CHSCAN9_LSB  =  4; // CSCAN0.CHSCAN9
+    const int CHSCAN8_LSB  =  3; // CSCAN0.CHSCAN8
+    CSCAN1 = 0xA800;            //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x
+    const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7
+    const int CHSCAN6_LSB =  9; // CSCAN1.CHSCAN6
+    const int CHSCAN5_LSB =  8; // CSCAN1.CHSCAN5
+    const int CHSCAN4_LSB =  7; // CSCAN1.CHSCAN4
+    const int CHSCAN3_LSB =  6; // CSCAN1.CHSCAN3
+    const int CHSCAN2_LSB =  5; // CSCAN1.CHSCAN2
+    const int CHSCAN1_LSB =  4; // CSCAN1.CHSCAN1
+    const int CHSCAN0_LSB =  3; // CSCAN1.CHSCAN0
+    
+    //----------------------------------------
+    // if average, ADC CONFIGURATION register set AVG and NAVG[1:0]
+    // (applicable to internal clock mode only)
+    // if average, ADC CONFIGURATION register set AVG ON BIT TO 1
+    // if average, ADC CONFIGURATION register set NAVG[1:0] TO N
+    if (average_0_4_8_16_32 == 4) {
+        // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((0 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 8) {
+        // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((1 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 16) {
+        // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((2 & NAVG_BITS) << NAVG_LSB);
+    } else if (average_0_4_8_16_32 == 32) {
+        // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3)
+        ADC_CONFIGURATION |=   ((1 & AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+        ADC_CONFIGURATION |=   ((3 & NAVG_BITS) << NAVG_LSB);
+    } else {
+        // Disable Averaging (AVGON=0, NAVG[1:0]=0)
+        ADC_CONFIGURATION &= ~ ((    AVGON_BITS) << AVGON_LSB);
+        ADC_CONFIGURATION &= ~ ((    NAVG_BITS) << NAVG_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC CONFIGURATION register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_CONFIGURATION);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // SET CSCAN0 CSCAN1 REGISTERS from enabledChannelsMask
+    CSCAN0 = 0xA000 | (((enabledChannelsMask >> 8) & 0xFF) << 3); // CSCAN0.CHSCAN[15:8]
+    CSCAN1 = 0xA800 | (((enabledChannelsMask) & 0xFF) << 3); // CSCAN1.CHSCAN[7:0]
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN0);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN1);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0111_CustomInternalClock = 7
+    //~ const int SCAN_0111_CustomInternalClock = 7; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_0111_CustomInternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SWCNV if CNVST pin is not used
+    // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT
+    // (applicable to internal clock mode only)
+    // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available)
+    // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available)
+    if (swcnv_0_1) {
+        ADC_MODE_CONTROL |=   ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB);
+    } else {
+        ADC_MODE_CONTROL &= ~ ((            SWCNV_BITS) << SWCNV_LSB);
+    }
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    if (swcnv_0_1) {
+      // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles.
+      // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17".
+      SPIwrite24bits(ADC_MODE_CONTROL, 0);
+    } else {
+      SPIwrite16bits(ADC_MODE_CONTROL);
+    }
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_1000_CustomExternalClock
+//
+// Measure selected ADC channels in sequence from AIN0 to AIN15,
+//     using only the channels enabled by enabledChannelsMask.
+//     Bit 0x0001 enables AIN0.
+//     Bit 0x0002 enables AIN1.
+//     Bit 0x0004 enables AIN2.
+//     Bit 0x0008 enables AIN3.
+//     Bit 0x0010 enables AIN4.
+//     Bit 0x0020 enables AIN5.
+//     Bit 0x0040 enables AIN6.
+//     Bit 0x0080 enables AIN7.
+//     Bit 0x0100 enables AIN8.
+//     Bit 0x0200 enables AIN9.
+//     Bit 0x0400 enables AIN10.
+//     Bit 0x0800 enables AIN11.
+//     Bit 0x1000 enables AIN12.
+//     Bit 0x2000 enables AIN13.
+//     Bit 0x4000 enables AIN14.
+//     Bit 0x8000 enables AIN15.
+// External clock mode.
+// @param[in] enabledChannelsMask: Bitmap of AIN Channels to scan.
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID
+// @return number of ScanRead() words needed to retrieve the data.
+// For external clock modes, the data format depends on CHAN_ID.
+//     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+//     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanCustomExternalClock(void)
+{
+    
+    //----------------------------------------
+    // count nWords = number of set bits in enabledChannelsMask
+    uint16_t bitMask;
+    int nWords = 0;
+    for (bitMask = 0x8000; bitMask != 0; bitMask = bitMask / 2)
+    {
+        if (enabledChannelsMask & bitMask)
+        {
+            nWords++;
+        }
+    }
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = nWords;
+    
+    //----------------------------------------
+    // External Clock Mode
+    isExternalClock = 1;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_1000_CustomExternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // define write-only registers CSCAN0,CSCAN1
+    CSCAN0 = 0xA000;            //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x
+    const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15
+    const int CHSCAN14_LSB =  9; // CSCAN0.CHSCAN14
+    const int CHSCAN13_LSB =  8; // CSCAN0.CHSCAN13
+    const int CHSCAN12_LSB =  7; // CSCAN0.CHSCAN12
+    const int CHSCAN11_LSB =  6; // CSCAN0.CHSCAN11
+    const int CHSCAN10_LSB =  5; // CSCAN0.CHSCAN10
+    const int CHSCAN9_LSB  =  4; // CSCAN0.CHSCAN9
+    const int CHSCAN8_LSB  =  3; // CSCAN0.CHSCAN8
+    CSCAN1 = 0xA800;            //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x
+    const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7
+    const int CHSCAN6_LSB =  9; // CSCAN1.CHSCAN6
+    const int CHSCAN5_LSB =  8; // CSCAN1.CHSCAN5
+    const int CHSCAN4_LSB =  7; // CSCAN1.CHSCAN4
+    const int CHSCAN3_LSB =  6; // CSCAN1.CHSCAN3
+    const int CHSCAN2_LSB =  5; // CSCAN1.CHSCAN2
+    const int CHSCAN1_LSB =  4; // CSCAN1.CHSCAN1
+    const int CHSCAN0_LSB =  3; // CSCAN1.CHSCAN0
+    
+    //----------------------------------------
+    // SET CSCAN0 CSCAN1 REGISTERS from enabledChannelsMask
+    CSCAN0 = 0xA000 | (((enabledChannelsMask >> 8) & 0xFF) << 3); // CSCAN0.CHSCAN[15:8]
+    CSCAN1 = 0xA800 | (((enabledChannelsMask) & 0xFF) << 3); // CSCAN1.CHSCAN[7:0]
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN0);
+    SPIoutputCS(1); // drive CS high
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(CSCAN1);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_1000_CustomExternalClock = 8
+    //~ const int SCAN_1000_CustomExternalClock = 8; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_1000_CustomExternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT
+    // (applicable to external clock mode only)
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    ADC_MODE_CONTROL |=   ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB);
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// SCAN_1001_SampleSetExternalClock
+//
+// Measure ADC channels in an arbitrary pattern.
+//     Channels can be visited in any order, with repetition allowed.
+// External clock mode.
+// @pre enabledChannelsPatternLength_1_256: number of channel selections
+// @pre enabledChannelsPattern: array containing channel selection pattern
+//     In the array, one channel select per byte.
+//     In the SPI interface, immediately after SAMPLESET register is written,
+//     each byte encodes two channelNumber selections.
+//     The high 4 bits encode the first channelNumber.
+//     (((enabledChannelsPattern[0]) & 0x0F) << 4) | ((enabledChannelsPattern[1]) & 0x0F)
+//     If it is an odd number of channels, additional nybbles will be ignored.
+//     CS will be asserted low during the entire SAMPLESET pattern selection.
+// @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby
+// @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID
+// @return number of ScanRead() words needed to retrieve the data.
+// For external clock modes, the data format depends on CHAN_ID.
+//     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+//     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+//
+int MAX11131::ScanSampleSetExternalClock(void)
+{
+    
+    //----------------------------------------
+    // number of words to read
+    NumWords = ((enabledChannelsPatternLength_1_256 != 0) ? enabledChannelsPatternLength_1_256 : 256 );
+    
+    //----------------------------------------
+    // External Clock Mode
+    isExternalClock = 1;
+    
+    //----------------------------------------
+    // update device driver global variable
+    ScanMode = SCAN_1001_SampleSetExternalClock;
+    
+    //----------------------------------------
+    // define write-only register ADC_MODE_CONTROL
+    ADC_MODE_CONTROL = 0;       //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0
+    const int SCAN_LSB    = 11; const int SCAN_BITS    = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command)
+    const int CHSEL_LSB   =  7; const int CHSEL_BITS   = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15
+    const int RESET_LSB   =  5; const int RESET_BITS   = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    const int PM_LSB      =  3; const int PM_BITS      = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    const int CHAN_ID_LSB =  2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID
+    const int SWCNV_LSB   =  1; const int SWCNV_BITS   = 0x01; //!< ADC_MODE_CONTROL.SWCNV
+    
+    //----------------------------------------
+    // Initialize shadow of write-only register SAMPLESET.
+    // Do not write to SAMPLESET at this time.
+    // A write to SAMPLESET must be followed by specified number of pattern entry words.
+    // See ScanSampleSetExternalClock function for details.
+    SAMPLESET = 0xB000;         //!< mosiData16 0xB000..0xB7FF format: 1 0 1 1 0 SEQ_LENGTH[7:0] x x x
+    const int SAMPLESET_LSB   =  3; const int SAMPLESET_BITS   = 0xFF; // SAMPLESET.SEQ_LENGTH[7:0]
+    
+    //----------------------------------------
+    // SampleSet register set SEQ_DEPTH[7:0] TO SET CHANNEL CAPTURE DEPTH; FOLLOW SampleSet REGISTER WITH CHANNEL PATTERN OF THE SAME SIZE AS SEQUENCE DEPTH
+    // NOTE: SAMPLESET.SEQ_LENGTH[7:0] is the number of channel entries in the pattern.
+    // NOTE: Each channel entry is 4 bits. The first 4 bits are the first channel in the sequence.
+    // NOTE: Channels can be repeated in any arbitrary order.
+    // NOTE: The channel entry pattern is sent immediately after writing SAMPLESET.
+    // NOTE: Keep CS low during the entire SAMPLESET pattern entry.
+    const int seq_length_minus_one_0_255 = enabledChannelsPatternLength_1_256 - 1;
+    SAMPLESET = 0xB000;
+    //SAMPLESET &= ~ ((                             SAMPLESET_BITS) << SAMPLESET_LSB);
+    SAMPLESET |=   ((seq_length_minus_one_0_255 & SAMPLESET_BITS) << SAMPLESET_LSB);
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(SAMPLESET); // SAMPLESET must be followed by several more bytes, length specified by SEQ_LENGTH[7:0]
+    // pack enabledChannelsPattern[index] into nybbles
+    SPIoutputCS(1); // drive CS high
+    // NOTE: Send the sampleset pattern, with 4 entries packed into each 16-bit SPI word. Pad unused entries with 0.
+    SPI_MOSI_Semantic = 2; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    // NOTE: Keep CS low during the entire SAMPLESET pattern entry.
+    int entryIndex;
+    for (entryIndex = 0; entryIndex < enabledChannelsPatternLength_1_256; entryIndex += 4)
+    {
+        uint16_t pack4channels = 0;
+        pack4channels |= (((enabledChannelsPattern[entryIndex + 0]) & 0x0F) << 12);
+        if ((entryIndex + 1) < enabledChannelsPatternLength_1_256) {
+            pack4channels |= (((enabledChannelsPattern[entryIndex + 1]) & 0x0F) << 8);
+        }
+        if ((entryIndex + 2) < enabledChannelsPatternLength_1_256) {
+            pack4channels |= (((enabledChannelsPattern[entryIndex + 2]) & 0x0F) << 4);
+        }
+        if ((entryIndex + 3) < enabledChannelsPatternLength_1_256) {
+            pack4channels |=   ((enabledChannelsPattern[entryIndex + 3]) & 0x0F);
+        }
+        SPIwrite16bits(pack4channels);
+    }
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1   Apply a soft reset when changing from internal to external clock mode.
+    ADC_MODE_CONTROL &= ~ ((    RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    ADC_MODE_CONTROL |=   ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_1001_SampleSetExternalClock = 9
+    //~ const int SCAN_1001_SampleSetExternalClock = 9; // replaced local const with enum
+    ADC_MODE_CONTROL |=   ((SCAN_1001_SampleSetExternalClock & SCAN_BITS) << SCAN_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL register set CHSEL[3:0] TO channel number
+    ADC_MODE_CONTROL |=   ((0 & CHSEL_BITS) << CHSEL_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS
+    ADC_MODE_CONTROL |=   ((PowerManagement_0_2 & PM_BITS) << PM_LSB);
+    
+    //----------------------------------------
+    // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT
+    // (applicable to external clock mode only)
+    // For external clock modes, the data format returned depends on the CHAN_ID bit.
+    //     when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    //     when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0]
+    // For internal clock modes, the data format always includes the channel address.
+    //     misoData16 = CH[3:0] DATA[11:0]
+    ADC_MODE_CONTROL |=   ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB);
+    
+    //----------------------------------------
+    // SPI write ADC MODE CONTROL register
+    // Send SPI configuration to device
+    SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern
+    SPIoutputCS(0); // drive CS low
+    SPIwrite16bits(ADC_MODE_CONTROL);
+    SPIoutputCS(1); // drive CS high
+    
+    //----------------------------------------
+    // return number of words to read
+    return NumWords;
+}
+
+//----------------------------------------
+// Example configure and perform some measurements in ScanManual mode.
+// @param[out] pd_mean = address for double mean (avearge)
+// @param[out] pd_variance = address for double variance (variance)
+// @param[out] pd_stddev = address for double stddev (standard deviation)
+// @param[out] pd_Sx = address for double Sx (sum of all X)
+// @param[out] pd_Sxx = address for double Sxx (sum of squares of each X)
+void MAX11131::Example_ScanManual(int channelNumber_0_15, int nWords, 
+  double* pd_mean, double* pd_variance, double* pd_stddev, 
+  double* pd_Sx, double* pd_Sxx)
+{
+    
+    //----------------------------------------
+    // configure and perform some measurements in ScanManual mode
+    Init();
+    channelNumber_0_15 = channelNumber_0_15; // Analog Input Channel Select AIN0..
+    PowerManagement_0_2 = 0; // Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved
+    chan_id_0_1 = 1; // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x
+    // const int nWords = 100;
+    double Sx = 0;
+    double Sxx = 0;
+    int index;
+    ScanManual();
+    for (index = 0; index < nWords; index++)
+    {
+        int16_t misoData16 = ScanRead();
+        // For internal clock modes, the data format always includes the channel address.
+        //     misoData16 = CH[3:0] DATA[11:0]
+        int16_t value_u12 = (misoData16 & 0x0FFF);
+        int channelId = ((misoData16 >> 12) & 0x000F);
+        Sx = Sx + value_u12;
+        Sxx = Sxx + ((double)value_u12 * value_u12);
+    }
+    if (pd_Sx != 0) {
+        *(pd_Sx) = Sx;
+    }
+    if (pd_Sxx != 0) {
+        *(pd_Sxx) = Sxx;
+    }
+    if (pd_mean != 0) {
+        *(pd_mean) = Sx / nWords;
+    }
+    if (nWords >= 2)
+    {
+        if (pd_variance != 0) {
+            // TODO1: is this variance calculation too naive to work reliably?
+            // see https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
+            *(pd_variance) = (Sxx - ( Sx * Sx / nWords) ) / (nWords - 1);
+        }
+        if (pd_stddev != 0) {
+            *(pd_stddev) = sqrt( *(pd_variance) );
+        }
+    }
+}
+
+
+// End of file
+