Maxim Integrated / MAX11410

Dependents:   MAX11410BOB_24bit_ADC MAX11410BOB_Serial_Tester

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX11410.cpp Source File

MAX11410.cpp

00001 // /*******************************************************************************
00002 // * Copyright (C) 2020 Maxim Integrated Products, Inc., All Rights Reserved.
00003 // *
00004 // * Permission is hereby granted, free of charge, to any person obtaining a
00005 // * copy of this software and associated documentation files (the "Software"),
00006 // * to deal in the Software without restriction, including without limitation
00007 // * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 // * and/or sell copies of the Software, and to permit persons to whom the
00009 // * Software is furnished to do so, subject to the following conditions:
00010 // *
00011 // * The above copyright notice and this permission notice shall be included
00012 // * in all copies or substantial portions of the Software.
00013 // *
00014 // * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 // * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 // * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 // * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 // * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 // * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 // * OTHER DEALINGS IN THE SOFTWARE.
00021 // *
00022 // * Except as contained in this notice, the name of Maxim Integrated
00023 // * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 // * Products, Inc. Branding Policy.
00025 // *
00026 // * The mere transfer of this software does not imply any licenses
00027 // * of trade secrets, proprietary technology, copyrights, patents,
00028 // * trademarks, maskwork rights, or any other form of intellectual
00029 // * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 // * ownership rights.
00031 // *******************************************************************************
00032 // */
00033 // *********************************************************************
00034 // @file MAX11410.cpp
00035 // *********************************************************************
00036 // Device Driver file
00037 // DO NOT EDIT; except areas designated "CUSTOMIZE". Automatically generated file.
00038 // generated by XMLSystemOfDevicesToMBED.py
00039 // System Name = ExampleSystem
00040 // System Description = Device driver example
00041 
00042 #include "MAX11410.h"
00043 
00044 // Device Name = MAX11410
00045 // Device Description = 1.9ksps, Low-Power, Serial SPI 24-Bit, 10-Channel, Differential/Single-Ended Input, SAR ADC
00046 // Device DeviceBriefDescription = 24-bit 1.9ksps Delta-Sigma ADC
00047 // Device Manufacturer = Maxim Integrated
00048 // Device PartNumber = MAX11410ATI+
00049 // Device RegValue_Width = DataWidth16bit_HL
00050 //
00051 // ADC MaxOutputDataRate = 1.9ksps
00052 // ADC NumChannels = 10
00053 // ADC ResolutionBits = 24
00054 //
00055 // SPI CS = ActiveLow
00056 // SPI FrameStart = CS
00057 // SPI CPOL = 0
00058 // SPI CPHA = 0
00059 // SPI MOSI and MISO Data are both stable on Rising edge of SCLK
00060 // SPI SCLK Idle Low
00061 // SPI SCLKMaxMHz = 8
00062 // SPI SCLKMinMHz = 0
00063 //
00064 
00065 // CODE GENERATOR: class constructor definition
00066 MAX11410::MAX11410(SPI &spi, DigitalOut &cs_pin, // SPI interface
00067                  // CODE GENERATOR: class constructor definition gpio InputPin pins
00068                  // CODE GENERATOR: class constructor definition gpio OutputPin pins
00069                  // CODE GENERATOR: class constructor definition ic_variant
00070                  MAX11410_ic_t ic_variant)
00071     // CODE GENERATOR: class constructor initializer list
00072     : m_spi(spi), m_cs_pin(cs_pin), // SPI interface
00073     // CODE GENERATOR: class constructor initializer list gpio InputPin pins
00074     // CODE GENERATOR: class constructor initializer list gpio OutputPin pins
00075     // CODE GENERATOR: class constructor initializer list ic_variant
00076     m_ic_variant(ic_variant)
00077 {
00078     // CODE GENERATOR: class constructor definition SPI interface initialization
00079     //
00080     // SPI CS = ActiveLow
00081     // SPI FrameStart = CS
00082     m_SPI_cs_state = 1;
00083     if (m_cs_pin.is_connected()) { // avoid mbed runtime error if pin is NC not connected
00084         m_cs_pin = m_SPI_cs_state;
00085     }
00086 
00087     // SPI CPOL = 0
00088     // SPI CPHA = 0
00089     // SPI MOSI and MISO Data are both stable on Rising edge of SCLK
00090     // SPI SCLK Idle Low
00091     m_SPI_dataMode = 0; //SPI_MODE0; // CPOL=0,CPHA=0: Rising Edge stable; SCLK idle Low
00092     m_spi.format(8,m_SPI_dataMode);         // int bits_must_be_8, int mode=0_3 CPOL=0,CPHA=0
00093 
00094     // SPI SCLKMaxMHz = 8
00095     // SPI SCLKMinMHz = 0
00096     //#define SPI_SCLK_Hz 48000000 // 48MHz
00097     //#define SPI_SCLK_Hz 24000000 // 24MHz
00098     //#define SPI_SCLK_Hz 12000000 // 12MHz
00099     //#define SPI_SCLK_Hz 6000000 // 6MHz
00100     //#define SPI_SCLK_Hz 4000000 // 4MHz
00101     //#define SPI_SCLK_Hz 2000000 // 2MHz
00102     //#define SPI_SCLK_Hz 1000000 // 1MHz
00103     m_SPI_SCLK_Hz = 8000000; // 8MHz; MAX11410 limit is 8MHz
00104     m_spi.frequency(m_SPI_SCLK_Hz);
00105 
00106 }
00107 
00108 // CODE GENERATOR: class destructor definition
00109 MAX11410::~MAX11410()
00110 {
00111     // do nothing
00112 }
00113 
00114 // CODE GENERATOR: spi_frequency setter definition
00115 /// set SPI SCLK frequency
00116 void MAX11410::spi_frequency(int spi_sclk_Hz)
00117 {
00118     m_SPI_SCLK_Hz = spi_sclk_Hz;
00119     m_spi.frequency(m_SPI_SCLK_Hz);
00120 }
00121 
00122 // CODE GENERATOR: omit global g_MAX11410_device
00123 // CODE GENERATOR: extern function declarations
00124 // CODE GENERATOR: extern function requirement MAX11410::SPIoutputCS
00125 // Assert SPI Chip Select
00126 // SPI chip-select for MAX11410
00127 //
00128 inline void MAX11410::SPIoutputCS(int isLogicHigh)
00129 {
00130     // CODE GENERATOR: extern function definition for function SPIoutputCS
00131     // CODE GENERATOR: extern function definition for standard SPI interface function SPIoutputCS(int isLogicHigh)
00132     m_SPI_cs_state = isLogicHigh;
00133     if (m_cs_pin.is_connected()) { // avoid mbed runtime error if pin is NC not connected
00134         m_cs_pin = m_SPI_cs_state;
00135     }
00136 }
00137 
00138 // CODE GENERATOR: extern function requirement MAX11410::SPIwrite16bits
00139 // SPI write 16 bits
00140 // SPI interface to MAX11410 shift 16 bits mosiData into MAX11410 DIN
00141 //
00142 void MAX11410::SPIwrite16bits(int16_t mosiData16)
00143 {
00144     // CODE GENERATOR: extern function definition for function SPIwrite16bits
00145     // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function SPIwrite16bits(int16_t mosiData16)
00146     size_t byteCount = 2;
00147     static char mosiData[2];
00148     static char misoData[2];
00149     mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte
00150     mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte
00151     //
00152     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00153     //~ noInterrupts();
00154     //
00155     //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
00156     //
00157     unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
00158     //~ m_spi.transfer(mosiData8_FF0000);
00159     //~ m_spi.transfer(mosiData16_00FF00);
00160     //~ m_spi.transfer(mosiData16_0000FF);
00161     //
00162     //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
00163     //
00164     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00165     //~ interrupts();
00166     // Optional Diagnostic function to print SPI transactions
00167     if (onSPIprint)
00168     {
00169         onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData);
00170     }
00171     //
00172     // VERIFY: SPIwrite24bits print diagnostic information
00173     //cmdLine.serial().printf(" MOSI->"));
00174     //cmdLine.serial().printf(" 0x"));
00175     //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
00176     //cmdLine.serial().printf(" 0x"));
00177     //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
00178     //cmdLine.serial().printf(" 0x"));
00179     //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
00180     // hex dump mosiData[0..byteCount-1]
00181 #if 0 // HAS_MICROUSBSERIAL
00182     cmdLine_microUSBserial.serial().printf("\r\nSPI");
00183     if (byteCount > 7) {
00184         cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
00185     }
00186     cmdLine_microUSBserial.serial().printf(" MOSI->");
00187     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00188     {
00189         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00190     }
00191     // hex dump misoData[0..byteCount-1]
00192     cmdLine_microUSBserial.serial().printf(" MISO<-");
00193     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00194     {
00195         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00196     }
00197     cmdLine_microUSBserial.serial().printf(" ");
00198 #endif
00199 #if 0 // HAS_DAPLINK_SERIAL
00200     cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
00201     if (byteCount > 7) {
00202         cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
00203     }
00204     cmdLine_DAPLINKserial.serial().printf(" MOSI->");
00205     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00206     {
00207         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00208     }
00209     // hex dump misoData[0..byteCount-1]
00210     cmdLine_DAPLINKserial.serial().printf(" MISO<-");
00211     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00212     {
00213         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00214     }
00215     cmdLine_DAPLINKserial.serial().printf(" ");
00216 #endif
00217     // VERIFY: DIAGNOSTIC: print MAX5715 device register write
00218     // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
00219     // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF);
00220     //
00221     // int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF;
00222     // return misoData16;
00223 }
00224 
00225 // CODE GENERATOR: extern function requirement MAX11410::SPIreadWrite16bits
00226 // SPI read and write 16 bits
00227 // SPI interface to MAX11410 shift 16 bits mosiData16 into MAX11410 DIN
00228 // while simultaneously capturing 16 bits miso data from MAX11410 DOUT
00229 //
00230 int16_t MAX11410::SPIreadWrite16bits(int16_t mosiData16)
00231 {
00232     // CODE GENERATOR: extern function definition for function SPIreadWrite16bits
00233     // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function SPIreadWrite16bits(int16_t mosiData16)
00234     size_t byteCount = 2;
00235     static char mosiData[2];
00236     static char misoData[2];
00237     mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte
00238     mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte
00239     //
00240     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00241     //~ noInterrupts();
00242     //
00243     //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
00244     //
00245     unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
00246     //~ m_spi.transfer(mosiData8_FF0000);
00247     //~ m_spi.transfer(mosiData16_00FF00);
00248     //~ m_spi.transfer(mosiData16_0000FF);
00249     //
00250     //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
00251     //
00252     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00253     //~ interrupts();
00254     // Optional Diagnostic function to print SPI transactions
00255     if (onSPIprint)
00256     {
00257         onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData);
00258     }
00259     //
00260     // VERIFY: SPIwrite24bits print diagnostic information
00261     //cmdLine.serial().printf(" MOSI->"));
00262     //cmdLine.serial().printf(" 0x"));
00263     //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
00264     //cmdLine.serial().printf(" 0x"));
00265     //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
00266     //cmdLine.serial().printf(" 0x"));
00267     //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
00268     // hex dump mosiData[0..byteCount-1]
00269 #if 0 // HAS_MICROUSBSERIAL
00270     cmdLine_microUSBserial.serial().printf("\r\nSPI");
00271     if (byteCount > 7) {
00272         cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
00273     }
00274     cmdLine_microUSBserial.serial().printf(" MOSI->");
00275     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00276     {
00277         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00278     }
00279     // hex dump misoData[0..byteCount-1]
00280     cmdLine_microUSBserial.serial().printf(" MISO<-");
00281     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00282     {
00283         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00284     }
00285     cmdLine_microUSBserial.serial().printf(" ");
00286 #endif
00287 #if 0 // HAS_DAPLINK_SERIAL
00288     cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
00289     if (byteCount > 7) {
00290         cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
00291     }
00292     cmdLine_DAPLINKserial.serial().printf(" MOSI->");
00293     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00294     {
00295         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00296     }
00297     // hex dump misoData[0..byteCount-1]
00298     cmdLine_DAPLINKserial.serial().printf(" MISO<-");
00299     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00300     {
00301         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00302     }
00303     cmdLine_DAPLINKserial.serial().printf(" ");
00304 #endif
00305     // VERIFY: DIAGNOSTIC: print MAX5715 device register write
00306     // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
00307     // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF);
00308     //
00309     //int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF;
00310     int misoData16 = (misoData[0] << 8) | misoData[1];
00311     return misoData16;
00312 }
00313 
00314 // CODE GENERATOR: extern function requirement MAX11410::SPIreadWrite32bits
00315 // SPI read and write 32 bits
00316 // SPI interface to MAX11410 shift 32 bits mosiData into MAX11410 DIN
00317 // while simultaneously capturing 32 bits miso data from MAX11410 DOUT
00318 //
00319 int32_t MAX11410::SPIreadWrite32bits(int32_t mosiData32)
00320 {
00321     // CODE GENERATOR: extern function definition for function SPIreadWrite32bits
00322     // TODO1: CODE GENERATOR: extern function definition for standard SPI interface function SPIreadWrite32bits(int32_t mosiData32)
00323     size_t byteCount = 4;
00324     static char mosiData[4];
00325     static char misoData[4];
00326     mosiData[0] = (char)((mosiData32 >> 24) & 0xFF); // MSByte
00327     mosiData[1] = (char)((mosiData32 >> 16) & 0xFF);
00328     mosiData[2] = (char)((mosiData32 >>  8) & 0xFF);
00329     mosiData[3] = (char)((mosiData32 >>  0) & 0xFF); // LSByte
00330     //
00331     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00332     //~ noInterrupts();
00333     //
00334     //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin
00335     //
00336     unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount);
00337     //~ m_spi.transfer(mosiData8_FF0000);
00338     //~ m_spi.transfer(mosiData16_00FF00);
00339     //~ m_spi.transfer(mosiData16_0000FF);
00340     //
00341     //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin
00342     //
00343     // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts()
00344     //~ interrupts();
00345     // Optional Diagnostic function to print SPI transactions
00346     if (onSPIprint)
00347     {
00348         onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData);
00349     }
00350     //
00351     // VERIFY: SPIwrite24bits print diagnostic information
00352     //cmdLine.serial().printf(" MOSI->"));
00353     //cmdLine.serial().printf(" 0x"));
00354     //Serial.print( (mosiData8_FF0000 & 0xFF), HEX);
00355     //cmdLine.serial().printf(" 0x"));
00356     //Serial.print( (mosiData16_00FF00 & 0xFF), HEX);
00357     //cmdLine.serial().printf(" 0x"));
00358     //Serial.print( (mosiData16_0000FF & 0xFF), HEX);
00359     // hex dump mosiData[0..byteCount-1]
00360 #if 0 // HAS_MICROUSBSERIAL
00361     cmdLine_microUSBserial.serial().printf("\r\nSPI");
00362     if (byteCount > 7) {
00363         cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount);
00364     }
00365     cmdLine_microUSBserial.serial().printf(" MOSI->");
00366     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00367     {
00368         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00369     }
00370     // hex dump misoData[0..byteCount-1]
00371     cmdLine_microUSBserial.serial().printf(" MISO<-");
00372     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00373     {
00374         cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00375     }
00376     cmdLine_microUSBserial.serial().printf(" ");
00377 #endif
00378 #if 0 // HAS_DAPLINK_SERIAL
00379     cmdLine_DAPLINKserial.serial().printf("\r\nSPI");
00380     if (byteCount > 7) {
00381         cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount);
00382     }
00383     cmdLine_DAPLINKserial.serial().printf(" MOSI->");
00384     for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++)
00385     {
00386         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]);
00387     }
00388     // hex dump misoData[0..byteCount-1]
00389     cmdLine_DAPLINKserial.serial().printf(" MISO<-");
00390     for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++)
00391     {
00392         cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]);
00393     }
00394     cmdLine_DAPLINKserial.serial().printf(" ");
00395 #endif
00396     // VERIFY: DIAGNOSTIC: print MAX5715 device register write
00397     // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF);
00398     // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF);
00399     //
00400     //int misoData32 = (misoData32_FF000000 << 24) | (misoData32_FF0000 << 16) | (misoData32_0000FF00 << 8) | misoData32_000000FF;
00401     int misoData32 = (misoData[0] << 24) | (misoData[1] << 16) | (misoData[2] << 8) | misoData[3];
00402     return misoData32;
00403 }
00404 
00405 // CODE GENERATOR: class member function definitions
00406 //----------------------------------------
00407 // Menu item '!'
00408 // Initialize device
00409 //
00410 // @test Init() expect 1
00411 //
00412 // @test group POR // verify initial register values
00413 // @test group PORverbose // verify initial register values
00414 // @test group PORverbose tinyTester.print("PART_ID value")
00415 // @test group POR RegRead(MAX11410::CMD_r001_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xddd_PART_ID, buffer) expect 1 expect-buffer 0x000F02
00416 //
00417 // @test group PORverbose tinyTester.print("POR value 0x04 CMD_r000_0100_dddd_xddd_GP0_CTRL")
00418 // @test group POR RegRead(MAX11410::CMD_r000_0100_dddd_xddd_GP0_CTRL, buffer) expect 1 expect-buffer 0x00
00419 //
00420 // @test group PORverbose tinyTester.print("POR value 0x05 CMD_r000_0101_dddd_xddd_GP1_CTRL")
00421 // @test group POR RegRead(MAX11410::CMD_r000_0101_dddd_xddd_GP1_CTRL, buffer) expect 1 expect-buffer 0x00
00422 //
00423 // @test group PORverbose tinyTester.print("POR value 0x07 CMD_r000_0111_xddd_dddd_GP_SEQ_ADDR")
00424 // @test group POR RegRead(MAX11410::CMD_r000_0111_xddd_dddd_GP_SEQ_ADDR, buffer) expect 1 expect-buffer 0x00003a
00425 //
00426 // @test group PORverbose tinyTester.print("POR value 0x08 CMD_r000_1000_x0dd_dddd_FILTER")
00427 // @test group POR RegRead(MAX11410::CMD_r000_1000_x0dd_dddd_FILTER, buffer) expect 1 expect-buffer 0x00
00428 //
00429 // @test group PORverbose tinyTester.print("POR value 0x09 CMD_r000_1001_dddd_dddd_CTRL")
00430 // @test group POR RegRead(MAX11410::CMD_r000_1001_dddd_dddd_CTRL, buffer) expect 1 expect-buffer 0x000001
00431 //
00432 // @test group PORverbose tinyTester.print("POR value 0x0a CMD_r000_1010_dddd_dddd_SOURCE")
00433 // @test group POR RegRead(MAX11410::CMD_r000_1010_dddd_dddd_SOURCE, buffer) expect 1 expect-buffer 0x00
00434 //
00435 // @test group PORverbose tinyTester.print("POR value 0x0b CMD_r000_1011_dddd_dddd_MUX_CTRL0")
00436 // @test group POR RegRead(MAX11410::CMD_r000_1011_dddd_dddd_MUX_CTRL0, buffer) expect 1 expect-buffer 0x0000ff
00437 //
00438 // @test group PORverbose tinyTester.print("POR value 0x0c CMD_r000_1100_dddd_dddd_MUX_CTRL1")
00439 // @test group POR RegRead(MAX11410::CMD_r000_1100_dddd_dddd_MUX_CTRL1, buffer) expect 1 expect-buffer 0x0000ff
00440 //
00441 // @test group PORverbose tinyTester.print("POR value 0x0d CMD_r000_1101_dddd_dddd_MUX_CTRL2")
00442 // @test group POR RegRead(MAX11410::CMD_r000_1101_dddd_dddd_MUX_CTRL2, buffer) expect 1 expect-buffer 0x00
00443 //
00444 // @test group PORverbose tinyTester.print("POR value 0x0e CMD_r000_1110_00ss_0ggg_PGA")
00445 // @test group POR RegRead(MAX11410::CMD_r000_1110_00ss_0ggg_PGA, buffer) expect 1 expect-buffer 0x00
00446 //
00447 // @future test     CMD_r000_1111_dddd_dddd_WAIT_EXT = 0x0f, //!< 0b0001111
00448 // @future test     CMD_r001_0000_xxxx_xxxx_WAIT_START = 0x10, //!< 0b0010000
00449 //
00450 // @test group RES1KA2A3TOGND // measure a 1kohm resistor between (AIN2,AIN3) and AGND to verify ref2_v (disabled by default)
00451 // @test group RES1KA2A3TOGNDMORE // measure a 1kohm resistor between (AIN2,AIN3) and AGND to verify ref2_v in more detail
00452 // @test group RES1KA2A3TOGNDMORE tinyTester.print("measure a 1kohm resistor between (AIN2,AIN3) and AGND to verify ref2_v")
00453 // @test group RES1KA2A3TOGND tinyTester.settle_time_msec = 1000 // default 250
00454 // @test group RES1KA2A3TOGND RegWrite(0x0C, 0xF3) expect 1 // *mux_ctrl1=0xf3 drives current source from AIN3
00455 //
00456 // @test group RES1KA2A3TOGNDMORE RegWrite(0x0A, 0x03) expect 1 // *source=0x03 idac_mode=100uA, 1k resistor 0.1V
00457 // @test group RES1KA2A3TOGNDMORE tinyTester.print("idac_mode=100uA, 1k resistor 0.1V")
00458 // @test group RES1KA2A3TOGNDMORE tinyTester.Wait_Output_Settling()
00459 // @test group RES1KA2A3TOGNDMORE Measure_Voltage(2,10) expect 0.1
00460 // @test group RES1KA2A3TOGNDMORE AINcode[2] expect (uint32_t)337731 within 33773 // idac_mode=100uA, 1k resistor 0.1V
00461 //
00462 // @test group RES1KA2A3TOGNDMORE RegWrite(0x0A, 0x0D) expect 1 // *source=0x0d idac_mode=800uA, 1k resistor 0.8V
00463 // @test group RES1KA2A3TOGNDMORE tinyTester.print("idac_mode=800uA, 1k resistor 0.8V")
00464 // @test group RES1KA2A3TOGNDMORE tinyTester.Wait_Output_Settling()
00465 // @test group RES1KA2A3TOGNDMORE Measure_Voltage(2,10) expect 0.8
00466 // @test group RES1KA2A3TOGNDMORE AINcode[2] expect (uint32_t)2724467 within 33773 // idac_mode=800uA, 1k resistor 0.8V
00467 //
00468 // @test group RES1KA2A3TOGND RegWrite(0x0A, 0x0B) expect 1 // *source=0x0b idac_mode=400uA, 1k resistor 0.4V
00469 // @test group RES1KA2A3TOGNDMORE tinyTester.print("idac_mode=400uA, 1k resistor 0.4V")
00470 // @test group RES1KA2A3TOGND tinyTester.Wait_Output_Settling()
00471 // @test group RES1KA2A3TOGND Measure_Voltage(2,10) expect 0.4
00472 // @test group RES1KA2A3TOGNDMORE AINcode[2] expect (uint32_t)1343163 within 33773 // idac_mode=400uA, 1k resistor 0.4V
00473 //
00474 // @test tinyTester.print("check filter register is writeable")
00475 // @future test tinyTester.print("this is a real mess dealing with the custom types")
00476 // @test RegWrite(0x08, 0x34) expect 1
00477 // @future test tinyTester.print("error: no matching function for call to 'MaximTinyTester::FunctionCall_Expect(const char [18], uint8_t (&)(MAX11410::CMD_enum_t, uint32_t), MAX11410::CMD_enum_t, uint32_t, int)'")
00478 // @future test RegWrite(CMD_r000_1000_x0dd_dddd_FILTER, 0x34) expect 1
00479 // @future test RegWrite(CMD_enum_t::CMD_r000_1000_x0dd_dddd_FILTER, 0x34) expect 1
00480 // @future test RegWrite(MAX11410::CMD_enum_t::CMD_r000_1000_x0dd_dddd_FILTER, 0x34) expect 1
00481 //
00482 // @test tinyTester.print("check filter register is readable")
00483 // @test RegRead(0x08, buffer) expect 1 expect-buffer 0x34
00484 // @future test RegRead(MAX11410::CMD_enum_t::CMD_r000_1000_x0dd_dddd_FILTER, &buffer) expect 1 expect-buffer 0x34
00485 //
00486 // @test tinyTester.settle_time_msec = 250 // default 250
00487 // @test tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
00488 // @test tinyTester.input_timeout_time_msec = 250 // default 250
00489 // @test tinyTester.settle_time_msec = 20 // default 250
00490 // @test tinyTester.blink_time_msec = 20 // quickly speed through the software verification
00491 // @test tinyTester.input_timeout_time_msec = 100 // default 250
00492 //
00493 // @test tinyTester.Wait_Output_Settling()
00494 //
00495 // @future test tinyTester.DigitalIn_Read_Expect_WarnOnly(DigitalIn& digitalInPin, const char* pinName, int expect_result, const char *expect_description)
00496 //
00497 // @return 1 on success; 0 on failure
00498 uint8_t MAX11410::Init(void)
00499 {
00500     
00501     //----------------------------------------
00502     // AIN0-AIN1 reference voltage, in Volts
00503     ref0_v = 2.500;
00504     
00505     //----------------------------------------
00506     // REF1P-REF1N reference resistance, in Ohms
00507     ref1_v = 4999;
00508     
00509     //----------------------------------------
00510     // REF2P-REF2N reference voltage, in Volts
00511     ref2_v = 2.500;
00512     
00513     //----------------------------------------
00514     // AVDD-AGND supply voltage, in Volts
00515     avdd_v = 3.300;
00516     
00517     //----------------------------------------
00518     // RTD Resistance measurement; Thermocouple Cold Junction, in Ohms
00519     rtd_ohm = 1000.0;
00520     
00521     //----------------------------------------
00522     // Temperature calculated from RTD Resistance; Thermocouple Cold Junction, in degrees C
00523     rtd_degc = 25.0;
00524     
00525     //----------------------------------------
00526     // shadow of register ctrl CMD_r000_1001_dddd_dddd_CTRL
00527     ctrl = 0x01;
00528     
00529     //----------------------------------------
00530     // set by Configure_PGA gain index register pga CMD_r000_1110_00ss_0ggg_PGA
00531     pgaGain = 1;
00532     
00533     //----------------------------------------
00534     // When driver polls status of a pin signal or a register status bit,
00535     // and there is no device physically connected, the driver must
00536     // be able to halt and report failure if too many tries. Each attempt
00537     // counts down until loop_limit is reached or exceeded.
00538     //
00539     // If driver seems to hang or takes too long to decide that device
00540     // is not connected, reduce the futility countdown limit value.
00541     //
00542     // If driver sometimes works but sometimes intermittently fails to
00543     // recognize device is attached, increase the futility countdown limit.
00544     loop_limit = 30;
00545     
00546     //----------------------------------------
00547     // timing delay after enable RTD bias current in Measure_RTD()
00548     rtd_ms = 100;
00549     
00550     //----------------------------------------
00551     // filter register configuration in Measure_RTD() -- 0x34 LINEF_11_SINC4 RATE_0100 output data rate 60SPS
00552     rtd_filter = 0x34;
00553     
00554     //----------------------------------------
00555     // ctrl register configuration in Measure_RTD() -- 0x40 unipolar, 0x01 REF_SEL_001_REF1P_REF1N
00556     rtd_ctrl = 0x41;
00557     
00558     //----------------------------------------
00559     // source register configuration in Measure_RTD() -- 0x0B IDAC_MODE_1011_400uA
00560     rtd_source = 0x0B;
00561     
00562     //----------------------------------------
00563     // pga register configuration in Measure_RTD() -- 0x21 SIG_PATH_10_PGA GAIN_001_2
00564     rtd_pga = 0x21;
00565     
00566     //----------------------------------------
00567     // filter register configuration in Measure_Voltage() -- 0x34 LINEF_11_SINC4 RATE_0100 output data rate 60SPS
00568     v_filter = 0x34;
00569     
00570     //----------------------------------------
00571     // ctrl register configuration in Measure_Voltage() -- 0x02 bipolar REF_SEL_010_REF2P_REF2N
00572     v_ctrl = 0x02;
00573     
00574     //----------------------------------------
00575     // pga register configuration in Measure_Voltage() -- 0x00 SIG_PATH_00_BUFFERED GAIN_000_1
00576     v_pga = 0x00;
00577     
00578     //----------------------------------------
00579     // list of registers to be read by menu item * with no arguments
00580     static MAX11410::MAX11410_CMD_enum_t readAllStatusListValues[] = {
00581     MAX11410::CMD_r000_0000_xxxx_xxdd_PD,
00582     MAX11410::CMD_r000_0001_xddd_xxdd_CONV_START,
00583     MAX11410::CMD_r000_0010_xddd_dddd_SEQ_START,
00584     MAX11410::CMD_r000_0011_xxxx_xddd_CAL_START,
00585     MAX11410::CMD_r000_0100_dddd_xddd_GP0_CTRL,
00586     MAX11410::CMD_r000_0101_dddd_xddd_GP1_CTRL,
00587     MAX11410::CMD_r000_0110_xddd_xxdd_GP_CONV,
00588     MAX11410::CMD_r000_0111_xddd_dddd_GP_SEQ_ADDR,
00589     MAX11410::CMD_r000_1000_x0dd_dddd_FILTER,
00590     MAX11410::CMD_r000_1001_dddd_dddd_CTRL,
00591     MAX11410::CMD_r000_1010_dddd_dddd_SOURCE,
00592     MAX11410::CMD_r000_1011_dddd_dddd_MUX_CTRL0,
00593     MAX11410::CMD_r000_1100_dddd_dddd_MUX_CTRL1,
00594     MAX11410::CMD_r000_1101_dddd_dddd_MUX_CTRL2,
00595     MAX11410::CMD_r000_1110_00ss_0ggg_PGA,
00596     MAX11410::CMD_r000_1111_dddd_dddd_WAIT_EXT,
00597     MAX11410::CMD_r001_0000_xxxx_xxxx_WAIT_START,
00598     };
00599     readAllStatusList = readAllStatusListValues;
00600     
00601     //----------------------------------------
00602     // number of registers to be read by menu item * with no arguments
00603     readAllStatusListLen = 17;
00604     
00605     //----------------------------------------
00606     // Device ID Validation
00607     const uint32_t part_id_expect = 0x000F02;
00608     uint32_t part_id_readback;
00609     RegRead(CMD_r001_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xddd_PART_ID, &part_id_readback);
00610     if (part_id_readback != part_id_expect) return 0;
00611     
00612     //----------------------------------------
00613     // write8 0x00 PD = 0x03 (Reset Registers; enter Standby mode)
00614     RegWrite(CMD_r000_0000_xxxx_xxdd_PD, PD_11_Reset);
00615     
00616     //----------------------------------------
00617     // write8 0x00 PD = 0x00 (NOP)
00618     RegWrite(CMD_r000_0000_xxxx_xxdd_PD, PD_00_Normal);
00619     
00620     //----------------------------------------
00621     // success
00622     return 1;
00623 }
00624 
00625 //----------------------------------------
00626 // Return the physical voltage corresponding to conversion result,
00627 // for unipolar mode.
00628 // Does not perform any offset or gain correction.
00629 //
00630 // @pre CTRL::U_BN = 1 -- Unipolar mode
00631 // @pre CTRL::FORMAT = x
00632 // @pre VRef = Voltage of REF input, in Volts
00633 // @param[in] value_u24: raw 24-bit MAX11410 code (right justified).
00634 // @return physical voltage corresponding to MAX11410 code.
00635 //
00636 // @test group UNIPOLAR // Verify function VoltageOfCode_Unipolar
00637 // @test group UNIPOLAR tinyTester.blink_time_msec = 20 // quickly speed through the software verification
00638 // @test group UNIPOLAR Configure_CTRL_REF(2) expect 1 // These tests require REF2 = 2.500V
00639 // @test group UNIPOLAR Configure_PGA(0,0) expect 1 // These tests require PGA gain=1
00640 // @test group UNIPOLAR VoltageOfCode_Unipolar(0xFFFFFF) expect 2.500 within 0.030 // Full Scale
00641 // @test group UNIPOLAR VoltageOfCode_Unipolar(0xFFFFFE) expect 2.500              // Full Scale
00642 // @test group UNIPOLAR VoltageOfCode_Unipolar(0xCCCCCC) expect 2.000              // Two Volts
00643 // @test group UNIPOLAR VoltageOfCode_Unipolar(0xC00000) expect 1.875              // 75% Scale
00644 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x800000) expect 1.250              // Mid Scale
00645 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x666666) expect 1.000              // One Volt
00646 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x400000) expect 0.625              // 25% Scale
00647 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x0A3D70) expect 0.100              // 100mV
00648 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x000064) expect 0.000014901162     // 100 LSB
00649 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x00000A) expect 0.0000014901162    // Ten LSB
00650 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x000003) expect 0.00000044703483   // Three LSB
00651 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x000002) expect 0.00000029802326   // Two LSB
00652 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x000001) expect 0.00000014901162   // One LSB
00653 // @test group UNIPOLAR VoltageOfCode_Unipolar(0x000000) expect 0.0                // Zero Scale
00654 // @test group UNIPOLAR tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
00655 //
00656 double MAX11410::VoltageOfCode_Unipolar(uint32_t value_u24)
00657 {
00658     
00659     //----------------------------------------
00660     // Linear map min and max endpoints
00661     double VRef = ref2_v;
00662     uint8_t ref_sel = (ctrl & 0x03); // MAX11410_REF_SEL_enum_t
00663     switch(ref_sel)
00664     {
00665     case REF_SEL_000_AIN0_AIN1:     VRef = ref0_v; break;
00666     case REF_SEL_001_REF1P_REF1N:   VRef = ref1_v; break;
00667     case REF_SEL_010_REF2P_REF2N:   VRef = ref2_v; break;
00668     case REF_SEL_011_AVDD_AGND:     VRef = avdd_v; break;
00669     case REF_SEL_100_AIN0_AGND:     VRef = ref0_v; break;
00670     case REF_SEL_101_REF1P_AGND:    VRef = ref1_v; break;
00671     case REF_SEL_110_REF2P_AGND:    VRef = ref2_v; break;
00672     case REF_SEL_111_AVDD_AGND:     VRef = avdd_v; break;
00673     }
00674     double MaxScaleVoltage = VRef; // voltage of maximum code 0xffffff
00675     double MinScaleVoltage = 0.0; // voltage of minimum code 0x000
00676     const uint32_t FULL_SCALE_CODE_24BIT = 0xffffff;
00677     const uint32_t MaxCode = FULL_SCALE_CODE_24BIT;
00678     const uint32_t MinCode = 0x000;
00679     double codeFraction = ((double)value_u24 - MinCode) / (MaxCode - MinCode + 1);
00680     return (MinScaleVoltage + ((MaxScaleVoltage - MinScaleVoltage) * codeFraction)) / pgaGain;
00681 }
00682 
00683 //----------------------------------------
00684 // Return the physical voltage corresponding to conversion result,
00685 // when conversion format is Bipolar mode, offset binary.
00686 // Does not perform any offset or gain correction.
00687 //
00688 // @pre CTRL::U_BN = 0 -- Bipolar mode
00689 // @pre CTRL::FORMAT = 1 -- offset binary
00690 // @pre VRef = Voltage of REF input, in Volts
00691 // @param[in] value_u24: raw 24-bit MAX11410 code (right justified).
00692 // @return physical voltage corresponding to MAX11410 code.
00693 //
00694 // @test group BIPOB // Verify function VoltageOfCode_Bipolar_OffsetBinary
00695 // @test group BIPOB tinyTester.blink_time_msec = 20 // quickly speed through the software verification
00696 // @test group BIPOB Configure_CTRL_REF(2) expect 1 // These tests require REF2 = 2.500V
00697 // @test group BIPOB Configure_PGA(0,0) expect 1 // These tests require PGA gain=1
00698 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0xFFFFFF) expect 2.5 within 0.030  // Full Scale
00699 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0xFFFFFE) expect 2.5               // Full Scale
00700 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0xC00000) expect 1.25              // Mid Scale
00701 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x800003) expect 0.00000894069671  // Three LSB
00702 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x800002) expect 0.00000596046447  // Two LSB
00703 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x800001) expect 0.0000029802326   // One LSB
00704 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x800000) expect 0.0               // Zero Scale
00705 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x7FFFFF) expect -0.0000029802326  // Negative One LSB
00706 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x7FFFFE) expect -0.0000059604644  // Negative Two LSB
00707 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x7FFFFD) expect -0.0000089406967  // Negative Three LSB
00708 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x400000) expect -1.25             // Negative Mid Scale
00709 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x000001) expect -2.5              // Negative Full Scale
00710 // @test group BIPOB VoltageOfCode_Bipolar_OffsetBinary(0x000000) expect -2.5              // Negative Full Scale
00711 // @test group BIPOB tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
00712 //
00713 double MAX11410::VoltageOfCode_Bipolar_OffsetBinary(uint32_t value_u24)
00714 {
00715     
00716     //----------------------------------------
00717     // Linear map min and max endpoints
00718     double VRef = ref2_v;
00719     uint8_t ref_sel = (ctrl & 0x03); // MAX11410_REF_SEL_enum_t
00720     switch(ref_sel)
00721     {
00722     case REF_SEL_000_AIN0_AIN1:     VRef = ref0_v; break;
00723     case REF_SEL_001_REF1P_REF1N:   VRef = ref1_v; break;
00724     case REF_SEL_010_REF2P_REF2N:   VRef = ref2_v; break;
00725     case REF_SEL_011_AVDD_AGND:     VRef = avdd_v; break;
00726     case REF_SEL_100_AIN0_AGND:     VRef = ref0_v; break;
00727     case REF_SEL_101_REF1P_AGND:    VRef = ref1_v; break;
00728     case REF_SEL_110_REF2P_AGND:    VRef = ref2_v; break;
00729     case REF_SEL_111_AVDD_AGND:     VRef = avdd_v; break;
00730     }
00731     double MaxScaleVoltage = 2 * VRef; // voltage of maximum code 0x7fffff
00732     double MinScaleVoltage = 0; // voltage of minimum code 0x800000;
00733     // const uint32_t FULL_SCALE_CODE_24BIT = 0x7fffff;
00734     // const uint32_t MaxCode = FULL_SCALE_CODE_24BIT;
00735     const int32_t CodeSpan = 0x1000000;
00736     const uint32_t MinCode = 0x800000;
00737     double codeFraction = ((double)value_u24 - MinCode) / CodeSpan;
00738     return (MinScaleVoltage + ((MaxScaleVoltage - MinScaleVoltage) * codeFraction)) / pgaGain;
00739 }
00740 
00741 //----------------------------------------
00742 // Return the physical voltage corresponding to conversion result,
00743 // when conversion format is Bipolar mode, 2's complement.
00744 // Does not perform any offset or gain correction.
00745 //
00746 // @pre CTRL::U_BN = 0 -- Bipolar mode
00747 // @pre CTRL::FORMAT = 0 -- 2's complement
00748 // @pre VRef = Voltage of REF input, in Volts
00749 // @param[in] value_u24: raw 24-bit MAX11410 code (right justified).
00750 // @return physical voltage corresponding to MAX11410 code.
00751 //
00752 // @test group BIP2C // Verify function VoltageOfCode_Bipolar_2sComplement
00753 // @test group BIP2C tinyTester.blink_time_msec = 20 // quickly speed through the software verification
00754 // @test group BIP2C Configure_CTRL_REF(2) expect 1 // These tests require REF2 = 2.500V
00755 // @test group BIP2C Configure_PGA(0,0) expect 1 // These tests require PGA gain=1
00756 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x7FFFFF) expect 2.500 within 0.030 // Full Scale
00757 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x7FFFFE) expect 2.500              // Full Scale
00758 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x666666) expect 2.000              // Two Volts
00759 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x600000) expect 1.875              // 75% Scale
00760 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x400000) expect 1.250              // Mid Scale
00761 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x333333) expect 1.000              // One Volt
00762 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x200000) expect 0.625              // 25% Scale
00763 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x051eb8) expect 0.100              // 100mV
00764 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x000003) expect 0.00000894069671   // Three LSB
00765 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x000002) expect 0.00000596046447   // Two LSB
00766 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x000001) expect 0.0000029802326    // One LSB
00767 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x000000) expect 0.0                // Zero Scale
00768 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xFFFFFF) expect -0.0000029802326   // Negative One LSB
00769 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xFFFFFE) expect -0.0000059604644   // Negative Two LSB
00770 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xFFFFFD) expect -0.0000089406967   // Negative Three LSB
00771 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xFAE148) expect -0.100             // Negative 100mV
00772 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xE00000) expect -0.625             // Negative 25% Scale
00773 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xCCCCCD) expect -1.000             // Negative One Volt
00774 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xC00000) expect -1.250             // Negative Mid Scale
00775 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0xA00000) expect -1.875             // Negative 75% Scale
00776 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x99999A) expect -2.000             // Negative Two Volts
00777 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x800001) expect -2.500             // Negative Full Scale
00778 // @test group BIP2C VoltageOfCode_Bipolar_2sComplement(0x800000) expect -2.500             // Negative Full Scale
00779 // @test group BIP2C tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
00780 //
00781 double MAX11410::VoltageOfCode_Bipolar_2sComplement(uint32_t value_u24)
00782 {
00783     
00784     //----------------------------------------
00785     // Linear map min and max endpoints
00786     double VRef = ref2_v;
00787     uint8_t ref_sel = (ctrl & 0x03); // MAX11410_REF_SEL_enum_t
00788     switch(ref_sel)
00789     {
00790     case REF_SEL_000_AIN0_AIN1:     VRef = ref0_v; break;
00791     case REF_SEL_001_REF1P_REF1N:   VRef = ref1_v; break;
00792     case REF_SEL_010_REF2P_REF2N:   VRef = ref2_v; break;
00793     case REF_SEL_011_AVDD_AGND:     VRef = avdd_v; break;
00794     case REF_SEL_100_AIN0_AGND:     VRef = ref0_v; break;
00795     case REF_SEL_101_REF1P_AGND:    VRef = ref1_v; break;
00796     case REF_SEL_110_REF2P_AGND:    VRef = ref2_v; break;
00797     case REF_SEL_111_AVDD_AGND:     VRef = avdd_v; break;
00798     }
00799     double MaxScaleVoltage = 2 * VRef; // voltage of maximum code 0x7fffff
00800     double MinScaleVoltage = 0; // voltage of minimum code 0x800000
00801     // const int32_t FULL_SCALE_CODE_24BIT_2S_COMPLEMENT = 0x7fffff;
00802     const int32_t SIGN_BIT_24BIT_2S_COMPLEMENT = 0x800000;
00803     if (value_u24 >= SIGN_BIT_24BIT_2S_COMPLEMENT) { value_u24 = value_u24 - (2 * SIGN_BIT_24BIT_2S_COMPLEMENT); }
00804     // const int32_t MaxCode = FULL_SCALE_CODE_24BIT_2S_COMPLEMENT;
00805     const int32_t CodeSpan = 0x1000000;
00806     const int32_t MinCode = 0;
00807     double codeFraction = ((double)((int32_t)value_u24) - MinCode) / CodeSpan;
00808     return (MinScaleVoltage + ((MaxScaleVoltage - MinScaleVoltage) * codeFraction)) / pgaGain;
00809 }
00810 
00811 //----------------------------------------
00812 // Return the physical voltage corresponding to conversion result,
00813 // when conversion format is determined by the CTRL register.
00814 // Does not perform any offset or gain correction.
00815 //
00816 // @pre CTRL::U_BN and CTRL::FORMAT = 0 select offset binary, 2's complement, or straight binary
00817 // @pre VRef = Voltage of REF input, in Volts
00818 // @param[in] value_u24: raw 24-bit MAX11410 code (right justified).
00819 // @return physical voltage corresponding to MAX11410 code.
00820 double MAX11410::VoltageOfCode(uint32_t value_u24)
00821 {
00822     
00823     //----------------------------------------
00824     // Determine format from CTRL register U_BN and FORMAT
00825     uint8_t u_bn_bitmask = (1 << 6);
00826     uint8_t format_bitmask = (1 << 5);
00827     if ((ctrl & u_bn_bitmask) != 0)
00828     {
00829         return VoltageOfCode_Unipolar(value_u24);
00830     }
00831     if ((ctrl & format_bitmask) != 0)
00832     {
00833         return VoltageOfCode_Bipolar_OffsetBinary(value_u24);
00834     }
00835     return VoltageOfCode_Bipolar_2sComplement(value_u24);
00836 }
00837 
00838 //----------------------------------------
00839 // Write a MAX11410 register.
00840 //
00841 // CMDOP_1aaa_aaaa_ReadRegister bit is cleared 0 indicating a write operation.
00842 //
00843 // MAX11410 register length can be determined by function RegSize.
00844 //
00845 // For 8-bit register size:
00846 //
00847 //     SPI 16-bit transfer
00848 //
00849 //     SPI MOSI = 0aaa_aaaa_dddd_dddd
00850 //
00851 //     SPI MISO = xxxx_xxxx_xxxx_xxxx
00852 //
00853 // For 16-bit register size:
00854 //
00855 //     SPI 24-bit or 32-bit transfer
00856 //
00857 //     SPI MOSI = 0aaa_aaaa_dddd_dddd_dddd_dddd
00858 //
00859 //     SPI MISO = xxxx_xxxx_xxxx_xxxx_xxxx_xxxx
00860 //
00861 // For 24-bit register size:
00862 //
00863 //     SPI 32-bit transfer
00864 //
00865 //     SPI MOSI = 0aaa_aaaa_dddd_dddd_dddd_dddd_dddd_dddd
00866 //
00867 //     SPI MISO = xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx
00868 //
00869 // @return 1 on success; 0 on failure
00870 uint8_t MAX11410::RegWrite(MAX11410_CMD_enum_t commandByte, uint32_t regData)
00871 {
00872     
00873     //----------------------------------------
00874     // switch based on register address size RegSize(commandByte)
00875     commandByte = (MAX11410_CMD_enum_t)((commandByte &~ CMDOP_1aaa_aaaa_ReadRegister) & 0xFF);
00876     switch(RegSize(commandByte))
00877     {
00878         case 8:  // 8-bit register size
00879             {
00880                 // SPI 16-bit transfer
00881                 // SPI MOSI = 0aaa_aaaa_dddd_dddd
00882                 // SPI MISO = xxxx_xxxx_xxxx_xxxx
00883                 int16_t mosiData16 = ((int16_t)commandByte << 8) | ((int16_t)regData & 0xFF);
00884                 SPIoutputCS(0);
00885                 SPIwrite16bits(mosiData16);
00886                 SPIoutputCS(1);
00887                 //
00888                 if (commandByte == CMD_r000_1110_00ss_0ggg_PGA)
00889                 {
00890                     // update pgaGain with 1, 2, 4, 8, 16, 32, 64, or 128 based on gain index
00891                     static uint8_t pgaGainTable[8] = {1, 2, 4, 8, 16, 32, 64, 128};
00892                     pgaGain = (((regData >> 4) & 2) == SIG_PATH_10_PGA) 
00893                         ? pgaGainTable[(uint8_t)(regData & 7)] 
00894                         : 1;
00895                 }
00896                 if (commandByte == CMD_r000_0011_xxxx_xddd_CAL_START)
00897                 {
00898                     // after RegWrite CMD_r000_0011_xxxx_xddd_CAL_START, poll status until 0x000004 CAL_RDY
00899                     RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
00900                     switch(regData & 0x07)
00901                     {
00902                     case 2: // CAL_TYPE_010_reserved = 0x02, //!< 0b010
00903                     case 3: // CAL_TYPE_011_reserved = 0x03, //!< 0b011
00904                         break; // do not wait for status
00905                     case 1: // CAL_TYPE_001_PGA_GAIN = 0x01, //!< 0b001
00906                         //
00907                         // Note: this case may fall through, by design.
00908 #if __GNUC__
00909 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
00910 #endif
00911                         if (pgaGain == 1) break; // do not wait for status
00912                         // fall through to case 0,4,5,6,7
00913 #if __GNUC__
00914 #pragma GCC diagnostic pop
00915 #endif
00916                         // Note: this case may fall through, by design.
00917                     case 0: // CAL_TYPE_000_SELF_CAL = 0x00, //!< 0b000
00918                     case 4: // CAL_TYPE_100_SYS_OFF_A = 0x04, //!< 0b100
00919                     case 5: // CAL_TYPE_101_SYS_GAIN_A = 0x05, //!< 0b101
00920                     case 6: // CAL_TYPE_110_SYS_OFF_B = 0x06, //!< 0b110
00921                     case 7: // CAL_TYPE_111_SYS_GAIN_B = 0x07, //!< 0b111
00922                         {
00923                             // wait for status CAL_RDY
00924                             // Worst-case (longest) calibration time = 2 x 1 sample/second = 2 seconds
00925                             for (int futility_countdown = loop_limit;
00926                                 ((futility_countdown > 0) &&
00927                                 ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000004_CAL_RDY) == 0));
00928                                 futility_countdown--)
00929                             {
00930                                 for (int futility_countdown_inner = 32767;
00931                                     ((futility_countdown_inner > 0) &&
00932                                     ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000004_CAL_RDY) == 0));
00933                                     futility_countdown_inner--)
00934                                 {
00935                                     RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
00936                                 }
00937                             }
00938                         }
00939                         break;
00940                     }
00941                 }
00942             }
00943             break;
00944         case 16:  // 16-bit register size
00945             {
00946                 // SPI 24-bit or 32-bit transfer
00947                 // SPI MOSI = 0aaa_aaaa_dddd_dddd_dddd_dddd
00948                 // SPI MISO = xxxx_xxxx_xxxx_xxxx_xxxx_xxxx
00949                 // SPI MOSI = 0aaa_aaaa_dddd_dddd_dddd_dddd_0000_0000
00950                 // SPI MISO = xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx
00951                 int32_t mosiData32 = ((int32_t)commandByte << 24) | (((int32_t)regData & 0xFFFF) << 8);
00952                 SPIoutputCS(0);
00953                 SPIreadWrite32bits(mosiData32);
00954                 SPIoutputCS(1);
00955             }
00956             break;
00957         case 24:  // 24-bit register size
00958             {
00959                 // SPI 32-bit transfer
00960                 // SPI MOSI = 0aaa_aaaa_dddd_dddd_dddd_dddd_dddd_dddd
00961                 // SPI MISO = xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx
00962                 int32_t mosiData32 = ((int32_t)commandByte << 24) | ((int32_t)regData & 0x00FFFFFF);
00963                 SPIoutputCS(0);
00964                 SPIreadWrite32bits(mosiData32);
00965                 SPIoutputCS(1);
00966             }
00967             break;
00968     }
00969     
00970     //----------------------------------------
00971     // success
00972     return 1;
00973 }
00974 
00975 //----------------------------------------
00976 // Read an 8-bit MAX11410 register
00977 //
00978 // CMDOP_1aaa_aaaa_ReadRegister bit is set 1 indicating a read operation.
00979 //
00980 // MAX11410 register length can be determined by function RegSize.
00981 //
00982 // For 8-bit register size:
00983 //
00984 //     SPI 16-bit transfer
00985 //
00986 //     SPI MOSI = 1aaa_aaaa_0000_0000
00987 //
00988 //     SPI MISO = xxxx_xxxx_dddd_dddd
00989 //
00990 // For 16-bit register size:
00991 //
00992 //     SPI 24-bit or 32-bit transfer
00993 //
00994 //     SPI MOSI = 1aaa_aaaa_0000_0000_0000_0000
00995 //
00996 //     SPI MISO = xxxx_xxxx_dddd_dddd_dddd_dddd
00997 //
00998 // For 24-bit register size:
00999 //
01000 //     SPI 32-bit transfer
01001 //
01002 //     SPI MOSI = 1aaa_aaaa_0000_0000_0000_0000_0000_0000
01003 //
01004 //     SPI MISO = xxxx_xxxx_dddd_dddd_dddd_dddd_dddd_dddd
01005 //
01006 //
01007 // @return 1 on success; 0 on failure
01008 uint8_t MAX11410::RegRead(MAX11410_CMD_enum_t commandByte, uint32_t* ptrRegData)
01009 {
01010     
01011     //----------------------------------------
01012     // switch based on register address size RegSize(regAddress)
01013     commandByte = (MAX11410_CMD_enum_t)((commandByte &~ CMDOP_1aaa_aaaa_ReadRegister) & 0xFF);
01014     switch(RegSize(commandByte))
01015     {
01016         case 8:  // 8-bit register size
01017             {
01018                 // SPI 16-bit transfer
01019                 // SPI MOSI = 1aaa_aaaa_0000_0000
01020                 // SPI MISO = xxxx_xxxx_dddd_dddd
01021                 int16_t mosiData16 = ((CMDOP_1aaa_aaaa_ReadRegister | (int16_t)commandByte) << 8) | ((int16_t)0);
01022                 SPIoutputCS(0);
01023                 int16_t misoData16 = SPIreadWrite16bits(mosiData16);
01024                 SPIoutputCS(1);
01025                 (*ptrRegData) = (misoData16 & 0x00FF);
01026             }
01027             break;
01028         case 16:  // 16-bit register size
01029             {
01030                 // SPI 24-bit or 32-bit transfer
01031                 // SPI MOSI = 1aaa_aaaa_0000_0000_0000_0000
01032                 // SPI MISO = xxxx_xxxx_dddd_dddd_dddd_dddd
01033                 // SPI MOSI = 1aaa_aaaa_0000_0000_0000_0000_0000_0000
01034                 // SPI MISO = xxxx_xxxx_dddd_dddd_dddd_dddd_xxxx_xxxx
01035                 int32_t mosiData32 = ((CMDOP_1aaa_aaaa_ReadRegister | (int32_t)commandByte) << 24);
01036                 SPIoutputCS(0);
01037                 int32_t misoData32 = SPIreadWrite32bits(mosiData32);
01038                 SPIoutputCS(1);
01039                 (*ptrRegData) = ((misoData32 >> 8) & 0x00FFFF);
01040             }
01041             break;
01042         case 24:  // 24-bit register size
01043             {
01044                 // SPI 32-bit transfer
01045                 // SPI MOSI = 1aaa_aaaa_0000_0000_0000_0000_0000_0000
01046                 // SPI MISO = xxxx_xxxx_dddd_dddd_dddd_dddd_dddd_dddd
01047                 int32_t mosiData32 = ((CMDOP_1aaa_aaaa_ReadRegister | (int32_t)commandByte) << 24);
01048                 SPIoutputCS(0);
01049                 int32_t misoData32 = SPIreadWrite32bits(mosiData32);
01050                 SPIoutputCS(1);
01051                 (*ptrRegData) = (misoData32 & 0x00FFFFFF);
01052             }
01053             break;
01054     }
01055     
01056     //----------------------------------------
01057     // success
01058     return 1;
01059 }
01060 
01061 //----------------------------------------
01062 // Return the size of a MAX11410 register
01063 //
01064 // @return 8 for 8-bit, 16 for 16-bit, 24 for 24-bit, else 0 for undefined register size
01065 uint8_t MAX11410::RegSize(MAX11410_CMD_enum_t commandByte)
01066 {
01067     
01068     //----------------------------------------
01069     // switch based on register address value regAddress
01070     commandByte = (MAX11410_CMD_enum_t)((commandByte &~ CMDOP_1aaa_aaaa_ReadRegister) & 0xFF);
01071     switch(commandByte)
01072     {
01073         default:
01074             return 0;  // undefined register size
01075         case CMD_r000_0000_xxxx_xxdd_PD:
01076         case CMD_r000_0001_xddd_xxdd_CONV_START:
01077         case CMD_r000_0010_xddd_dddd_SEQ_START:
01078         case CMD_r000_0011_xxxx_xddd_CAL_START:
01079         case CMD_r000_0100_dddd_xddd_GP0_CTRL:
01080         case CMD_r000_0101_dddd_xddd_GP1_CTRL:
01081         case CMD_r000_0110_xddd_xxdd_GP_CONV:
01082         case CMD_r000_0111_xddd_dddd_GP_SEQ_ADDR:
01083         case CMD_r000_1000_x0dd_dddd_FILTER:
01084         case CMD_r000_1001_dddd_dddd_CTRL:
01085         case CMD_r000_1010_dddd_dddd_SOURCE:
01086         case CMD_r000_1011_dddd_dddd_MUX_CTRL0:
01087         case CMD_r000_1100_dddd_dddd_MUX_CTRL1:
01088         case CMD_r000_1101_dddd_dddd_MUX_CTRL2:
01089         case CMD_r000_1110_00ss_0ggg_PGA:
01090         case CMD_r000_1111_dddd_dddd_WAIT_EXT:
01091         case CMD_r001_0000_xxxx_xxxx_WAIT_START:
01092             return 8;  // 8-bit register size
01093         case CMD_r001_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xddd_PART_ID:
01094         case CMD_r001_0010_xxxx_xxxx_dddd_xxdd_dddd_dddd_SYSC_SEL:
01095         case CMD_r001_0011_dddd_dddd_dddd_dddd_dddd_dddd_SYS_OFF_A:
01096         case CMD_r001_0100_dddd_dddd_dddd_dddd_dddd_dddd_SYS_OFF_B:
01097         case CMD_r001_0101_dddd_dddd_dddd_dddd_dddd_dddd_SYS_GAIN_A:
01098         case CMD_r001_0110_dddd_dddd_dddd_dddd_dddd_dddd_SYS_GAIN_B:
01099         case CMD_r001_0111_dddd_dddd_dddd_dddd_dddd_dddd_SELF_OFF:
01100         case CMD_r001_1000_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_1:
01101         case CMD_r001_1001_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_2:
01102         case CMD_r001_1010_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_4:
01103         case CMD_r001_1011_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_8:
01104         case CMD_r001_1100_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_16:
01105         case CMD_r001_1101_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_32:
01106         case CMD_r001_1110_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_64:
01107         case CMD_r001_1111_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_128:
01108         case CMD_r010_0000_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH0:
01109         case CMD_r010_0001_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH1:
01110         case CMD_r010_0010_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH2:
01111         case CMD_r010_0011_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH3:
01112         case CMD_r010_0100_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH4:
01113         case CMD_r010_0101_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH5:
01114         case CMD_r010_0110_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH6:
01115         case CMD_r010_0111_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH7:
01116         case CMD_r010_1000_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH0:
01117         case CMD_r010_1001_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH1:
01118         case CMD_r010_1010_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH2:
01119         case CMD_r010_1011_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH3:
01120         case CMD_r010_1100_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH4:
01121         case CMD_r010_1101_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH5:
01122         case CMD_r010_1110_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH6:
01123         case CMD_r010_1111_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH7:
01124         case CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0:
01125         case CMD_r011_0001_dddd_dddd_dddd_dddd_dddd_dddd_DATA1:
01126         case CMD_r011_0010_dddd_dddd_dddd_dddd_dddd_dddd_DATA2:
01127         case CMD_r011_0011_dddd_dddd_dddd_dddd_dddd_dddd_DATA3:
01128         case CMD_r011_0100_dddd_dddd_dddd_dddd_dddd_dddd_DATA4:
01129         case CMD_r011_0101_dddd_dddd_dddd_dddd_dddd_dddd_DATA5:
01130         case CMD_r011_0110_dddd_dddd_dddd_dddd_dddd_dddd_DATA6:
01131         case CMD_r011_0111_dddd_dddd_dddd_dddd_dddd_dddd_DATA7:
01132         case CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS:
01133         case CMD_r011_1001_dddd_dddd_dddd_dddd_dxxd_dddd_STATUS_IE:
01134             return 24;  // 24-bit register size
01135         case CMD_r011_1010_xaaa_aaaa_dddd_dddd_UC_0:
01136         case CMD_r011_1011_xaaa_aaaa_dddd_dddd_UC_1:
01137         case CMD_r011_1100_xaaa_aaaa_dddd_dddd_UC_2:
01138         case CMD_r011_1101_xaaa_aaaa_dddd_dddd_UC_3:
01139         case CMD_r011_1110_xaaa_aaaa_dddd_dddd_UC_4:
01140         case CMD_r011_1111_xaaa_aaaa_dddd_dddd_UC_5:
01141         case CMD_r100_0000_xaaa_aaaa_dddd_dddd_UC_6:
01142         case CMD_r100_0001_xaaa_aaaa_dddd_dddd_UC_7:
01143         case CMD_r100_0010_xaaa_aaaa_dddd_dddd_UC_8:
01144         case CMD_r100_0011_xaaa_aaaa_dddd_dddd_UC_9:
01145         case CMD_r100_0100_xaaa_aaaa_dddd_dddd_UC_10:
01146         case CMD_r100_0101_xaaa_aaaa_dddd_dddd_UC_11:
01147         case CMD_r100_0110_xaaa_aaaa_dddd_dddd_UC_12:
01148         case CMD_r100_0111_xaaa_aaaa_dddd_dddd_UC_13:
01149         case CMD_r100_1000_xaaa_aaaa_dddd_dddd_UC_14:
01150         case CMD_r100_1001_xaaa_aaaa_dddd_dddd_UC_15:
01151         case CMD_r100_1010_xaaa_aaaa_dddd_dddd_UC_16:
01152         case CMD_r100_1011_xaaa_aaaa_dddd_dddd_UC_17:
01153         case CMD_r100_1100_xaaa_aaaa_dddd_dddd_UC_18:
01154         case CMD_r100_1101_xaaa_aaaa_dddd_dddd_UC_19:
01155         case CMD_r100_1110_xaaa_aaaa_dddd_dddd_UC_20:
01156         case CMD_r100_1111_xaaa_aaaa_dddd_dddd_UC_21:
01157         case CMD_r101_0000_xaaa_aaaa_dddd_dddd_UC_22:
01158         case CMD_r101_0001_xaaa_aaaa_dddd_dddd_UC_23:
01159         case CMD_r101_0010_xaaa_aaaa_dddd_dddd_UC_24:
01160         case CMD_r101_0011_xaaa_aaaa_dddd_dddd_UC_25:
01161         case CMD_r101_0100_xaaa_aaaa_dddd_dddd_UC_26:
01162         case CMD_r101_0101_xaaa_aaaa_dddd_dddd_UC_27:
01163         case CMD_r101_0110_xaaa_aaaa_dddd_dddd_UC_28:
01164         case CMD_r101_0111_xaaa_aaaa_dddd_dddd_UC_29:
01165         case CMD_r101_1000_xaaa_aaaa_dddd_dddd_UC_30:
01166         case CMD_r101_1001_xaaa_aaaa_dddd_dddd_UC_31:
01167         case CMD_r101_1010_xaaa_aaaa_dddd_dddd_UC_32:
01168         case CMD_r101_1011_xaaa_aaaa_dddd_dddd_UC_33:
01169         case CMD_r101_1100_xaaa_aaaa_dddd_dddd_UC_34:
01170         case CMD_r101_1101_xaaa_aaaa_dddd_dddd_UC_35:
01171         case CMD_r101_1110_xaaa_aaaa_dddd_dddd_UC_36:
01172         case CMD_r101_1111_xaaa_aaaa_dddd_dddd_UC_37:
01173         case CMD_r110_0000_xaaa_aaaa_dddd_dddd_UC_38:
01174         case CMD_r110_0001_xaaa_aaaa_dddd_dddd_UC_39:
01175         case CMD_r110_0010_xaaa_aaaa_dddd_dddd_UC_40:
01176         case CMD_r110_0011_xaaa_aaaa_dddd_dddd_UC_41:
01177         case CMD_r110_0100_xaaa_aaaa_dddd_dddd_UC_42:
01178         case CMD_r110_0101_xaaa_aaaa_dddd_dddd_UC_43:
01179         case CMD_r110_0110_xaaa_aaaa_dddd_dddd_UC_44:
01180         case CMD_r110_0111_xaaa_aaaa_dddd_dddd_UC_45:
01181         case CMD_r110_1000_xaaa_aaaa_dddd_dddd_UC_46:
01182         case CMD_r110_1001_xaaa_aaaa_dddd_dddd_UC_47:
01183         case CMD_r110_1010_xaaa_aaaa_dddd_dddd_UC_48:
01184         case CMD_r110_1011_xaaa_aaaa_dddd_dddd_UC_49:
01185         case CMD_r110_1100_xaaa_aaaa_dddd_dddd_UC_50:
01186         case CMD_r110_1101_xaaa_aaaa_dddd_dddd_UC_51:
01187         case CMD_r110_1110_xaaa_aaaa_dddd_dddd_UC_52:
01188         case CMD_r110_1111_xxxx_xxxx_xaaa_aaaa_UCADDR:
01189             return 16;  // 16-bit register size
01190     }
01191 }
01192 
01193 //----------------------------------------
01194 // Decode operation from commandByte
01195 //
01196 // @return operation such as idle, read register, write register, etc.
01197 MAX11410::MAX11410_CMDOP_enum_t MAX11410::DecodeCommand(MAX11410_CMD_enum_t commandByte)
01198 {
01199     
01200     //----------------------------------------
01201     // decode operation from command byte
01202     switch (commandByte & 0x80)
01203     {
01204     default:
01205     case CMDOP_0aaa_aaaa_WriteRegister:
01206         return CMDOP_0aaa_aaaa_WriteRegister;
01207     case CMDOP_1aaa_aaaa_ReadRegister:
01208         return CMDOP_1aaa_aaaa_ReadRegister;
01209     }
01210 }
01211 
01212 //----------------------------------------
01213 // Return the address field of a MAX11410 register
01214 //
01215 // @return register address field as given in datasheet
01216 uint8_t MAX11410::RegAddrOfCommand(MAX11410_CMD_enum_t commandByte)
01217 {
01218     
01219     //----------------------------------------
01220     // extract register address value from command byte
01221     return (uint8_t)((commandByte &~ CMDOP_1aaa_aaaa_ReadRegister) & 0xFF);
01222 }
01223 
01224 //----------------------------------------
01225 // Test whether a command byte is a register read command
01226 //
01227 // @return true if command byte is a register read command
01228 uint8_t MAX11410::IsRegReadCommand(MAX11410_CMD_enum_t commandByte)
01229 {
01230     
01231     //----------------------------------------
01232     // Test whether a command byte is a register read command
01233     return (commandByte & CMDOP_1aaa_aaaa_ReadRegister) ? 1 : 0;
01234 }
01235 
01236 //----------------------------------------
01237 // Test whether a command byte is a register write command
01238 //
01239 // @return true if command byte is a register write command
01240 uint8_t MAX11410::IsRegWriteCommand(MAX11410_CMD_enum_t commandByte)
01241 {
01242     
01243     //----------------------------------------
01244     // Test whether a command byte is a register write command
01245     return (commandByte & CMDOP_1aaa_aaaa_ReadRegister) ? 0 : 1;
01246 }
01247 
01248 //----------------------------------------
01249 // Return the name of a MAX11410 register
01250 //
01251 // @return null-terminated constant C string containing register name or empty string
01252 const char* MAX11410::RegName(MAX11410_CMD_enum_t commandByte)
01253 {
01254     
01255     //----------------------------------------
01256     // switch based on register address value regAddress
01257     commandByte = (MAX11410_CMD_enum_t)((commandByte &~ CMDOP_1aaa_aaaa_ReadRegister) & 0xFF);
01258     switch(commandByte)
01259     {
01260         default:
01261             return "";  // undefined register
01262         case CMD_r000_0000_xxxx_xxdd_PD: return "PD";
01263         case CMD_r000_0001_xddd_xxdd_CONV_START: return "CONV_START";
01264         case CMD_r000_0010_xddd_dddd_SEQ_START: return "SEQ_START";
01265         case CMD_r000_0011_xxxx_xddd_CAL_START: return "CAL_START";
01266         case CMD_r000_0100_dddd_xddd_GP0_CTRL: return "GP0_CTRL";
01267         case CMD_r000_0101_dddd_xddd_GP1_CTRL: return "GP1_CTRL";
01268         case CMD_r000_0110_xddd_xxdd_GP_CONV: return "GP_CONV";
01269         case CMD_r000_0111_xddd_dddd_GP_SEQ_ADDR: return "GP_SEQ_ADDR";
01270         case CMD_r000_1000_x0dd_dddd_FILTER: return "FILTER";
01271         case CMD_r000_1001_dddd_dddd_CTRL: return "CTRL";
01272         case CMD_r000_1010_dddd_dddd_SOURCE: return "SOURCE";
01273         case CMD_r000_1011_dddd_dddd_MUX_CTRL0: return "MUX_CTRL0";
01274         case CMD_r000_1100_dddd_dddd_MUX_CTRL1: return "MUX_CTRL1";
01275         case CMD_r000_1101_dddd_dddd_MUX_CTRL2: return "MUX_CTRL2";
01276         case CMD_r000_1110_00ss_0ggg_PGA: return "PGA";
01277         case CMD_r000_1111_dddd_dddd_WAIT_EXT: return "WAIT_EXT";
01278         case CMD_r001_0000_xxxx_xxxx_WAIT_START: return "WAIT_START";
01279         case CMD_r001_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xddd_PART_ID: return "PART_ID";
01280         case CMD_r001_0010_xxxx_xxxx_dddd_xxdd_dddd_dddd_SYSC_SEL: return "SYSC_SEL";
01281         case CMD_r001_0011_dddd_dddd_dddd_dddd_dddd_dddd_SYS_OFF_A: return "SYS_OFF_A";
01282         case CMD_r001_0100_dddd_dddd_dddd_dddd_dddd_dddd_SYS_OFF_B: return "SYS_OFF_B";
01283         case CMD_r001_0101_dddd_dddd_dddd_dddd_dddd_dddd_SYS_GAIN_A: return "SYS_GAIN_A";
01284         case CMD_r001_0110_dddd_dddd_dddd_dddd_dddd_dddd_SYS_GAIN_B: return "SYS_GAIN_B";
01285         case CMD_r001_0111_dddd_dddd_dddd_dddd_dddd_dddd_SELF_OFF: return "SELF_OFF";
01286         case CMD_r001_1000_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_1: return "SELF_GAIN_1";
01287         case CMD_r001_1001_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_2: return "SELF_GAIN_2";
01288         case CMD_r001_1010_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_4: return "SELF_GAIN_4";
01289         case CMD_r001_1011_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_8: return "SELF_GAIN_8";
01290         case CMD_r001_1100_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_16: return "SELF_GAIN_16";
01291         case CMD_r001_1101_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_32: return "SELF_GAIN_32";
01292         case CMD_r001_1110_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_64: return "SELF_GAIN_64";
01293         case CMD_r001_1111_dddd_dddd_dddd_dddd_dddd_dddd_SELF_GAIN_128: return "SELF_GAIN_128";
01294         // Condense register names LTHRESH0..LTHRESH7 from CMD_r010_0000_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH0
01295         case CMD_r010_0000_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH0:
01296         case CMD_r010_0001_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH1:
01297         case CMD_r010_0010_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH2:
01298         case CMD_r010_0011_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH3:
01299         case CMD_r010_0100_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH4:
01300         case CMD_r010_0101_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH5:
01301         case CMD_r010_0110_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH6:
01302         case CMD_r010_0111_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH7:
01303             {
01304                 // Condense register names "LTHRESH#" from CMD_r010_0000_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH0
01305                 int index = commandByte - CMD_r010_0000_dddd_dddd_dddd_dddd_dddd_dddd_LTHRESH0;
01306                 static char retValueString[] = "LTHRESH#";
01307                 retValueString[7] = (index % 10) + '0';
01308                 return retValueString;
01309             };
01310         // Condense register names UTHRESH0..UTHRESH7 from CMD_r010_1000_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH0
01311         case CMD_r010_1000_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH0:
01312         case CMD_r010_1001_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH1:
01313         case CMD_r010_1010_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH2:
01314         case CMD_r010_1011_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH3:
01315         case CMD_r010_1100_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH4:
01316         case CMD_r010_1101_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH5:
01317         case CMD_r010_1110_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH6:
01318         case CMD_r010_1111_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH7:
01319             {
01320                 // Condense register names "UTHRESH#" from CMD_r010_1000_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH0
01321                 int index = commandByte - CMD_r010_1000_dddd_dddd_dddd_dddd_dddd_dddd_UTHRESH0;
01322                 static char retValueString[] = "UTHRESH#";
01323                 retValueString[7] = (index % 10) + '0';
01324                 return retValueString;
01325             };
01326         // Condense register names DATA0..DATA7 from CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0
01327         case CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0:
01328         case CMD_r011_0001_dddd_dddd_dddd_dddd_dddd_dddd_DATA1:
01329         case CMD_r011_0010_dddd_dddd_dddd_dddd_dddd_dddd_DATA2:
01330         case CMD_r011_0011_dddd_dddd_dddd_dddd_dddd_dddd_DATA3:
01331         case CMD_r011_0100_dddd_dddd_dddd_dddd_dddd_dddd_DATA4:
01332         case CMD_r011_0101_dddd_dddd_dddd_dddd_dddd_dddd_DATA5:
01333         case CMD_r011_0110_dddd_dddd_dddd_dddd_dddd_dddd_DATA6:
01334         case CMD_r011_0111_dddd_dddd_dddd_dddd_dddd_dddd_DATA7:
01335             {
01336                 // Condense register names "DATA#" from CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0
01337                 int index = commandByte - CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0;
01338                 static char retValueString[] = "DATA#";
01339                 retValueString[4] = (index % 10) + '0';
01340                 return retValueString;
01341             };
01342         case CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS: return "STATUS";
01343         case CMD_r011_1001_dddd_dddd_dddd_dddd_dxxd_dddd_STATUS_IE: return "STATUS_IE";
01344         // Condense register names UC_00..UC_52 from CMD_r011_1010_xaaa_aaaa_dddd_dddd_UC_0
01345         case CMD_r011_1010_xaaa_aaaa_dddd_dddd_UC_0:
01346         case CMD_r011_1011_xaaa_aaaa_dddd_dddd_UC_1:
01347         case CMD_r011_1100_xaaa_aaaa_dddd_dddd_UC_2:
01348         case CMD_r011_1101_xaaa_aaaa_dddd_dddd_UC_3:
01349         case CMD_r011_1110_xaaa_aaaa_dddd_dddd_UC_4:
01350         case CMD_r011_1111_xaaa_aaaa_dddd_dddd_UC_5:
01351         case CMD_r100_0000_xaaa_aaaa_dddd_dddd_UC_6:
01352         case CMD_r100_0001_xaaa_aaaa_dddd_dddd_UC_7:
01353         case CMD_r100_0010_xaaa_aaaa_dddd_dddd_UC_8:
01354         case CMD_r100_0011_xaaa_aaaa_dddd_dddd_UC_9:
01355         case CMD_r100_0100_xaaa_aaaa_dddd_dddd_UC_10:
01356         case CMD_r100_0101_xaaa_aaaa_dddd_dddd_UC_11:
01357         case CMD_r100_0110_xaaa_aaaa_dddd_dddd_UC_12:
01358         case CMD_r100_0111_xaaa_aaaa_dddd_dddd_UC_13:
01359         case CMD_r100_1000_xaaa_aaaa_dddd_dddd_UC_14:
01360         case CMD_r100_1001_xaaa_aaaa_dddd_dddd_UC_15:
01361         case CMD_r100_1010_xaaa_aaaa_dddd_dddd_UC_16:
01362         case CMD_r100_1011_xaaa_aaaa_dddd_dddd_UC_17:
01363         case CMD_r100_1100_xaaa_aaaa_dddd_dddd_UC_18:
01364         case CMD_r100_1101_xaaa_aaaa_dddd_dddd_UC_19:
01365         case CMD_r100_1110_xaaa_aaaa_dddd_dddd_UC_20:
01366         case CMD_r100_1111_xaaa_aaaa_dddd_dddd_UC_21:
01367         case CMD_r101_0000_xaaa_aaaa_dddd_dddd_UC_22:
01368         case CMD_r101_0001_xaaa_aaaa_dddd_dddd_UC_23:
01369         case CMD_r101_0010_xaaa_aaaa_dddd_dddd_UC_24:
01370         case CMD_r101_0011_xaaa_aaaa_dddd_dddd_UC_25:
01371         case CMD_r101_0100_xaaa_aaaa_dddd_dddd_UC_26:
01372         case CMD_r101_0101_xaaa_aaaa_dddd_dddd_UC_27:
01373         case CMD_r101_0110_xaaa_aaaa_dddd_dddd_UC_28:
01374         case CMD_r101_0111_xaaa_aaaa_dddd_dddd_UC_29:
01375         case CMD_r101_1000_xaaa_aaaa_dddd_dddd_UC_30:
01376         case CMD_r101_1001_xaaa_aaaa_dddd_dddd_UC_31:
01377         case CMD_r101_1010_xaaa_aaaa_dddd_dddd_UC_32:
01378         case CMD_r101_1011_xaaa_aaaa_dddd_dddd_UC_33:
01379         case CMD_r101_1100_xaaa_aaaa_dddd_dddd_UC_34:
01380         case CMD_r101_1101_xaaa_aaaa_dddd_dddd_UC_35:
01381         case CMD_r101_1110_xaaa_aaaa_dddd_dddd_UC_36:
01382         case CMD_r101_1111_xaaa_aaaa_dddd_dddd_UC_37:
01383         case CMD_r110_0000_xaaa_aaaa_dddd_dddd_UC_38:
01384         case CMD_r110_0001_xaaa_aaaa_dddd_dddd_UC_39:
01385         case CMD_r110_0010_xaaa_aaaa_dddd_dddd_UC_40:
01386         case CMD_r110_0011_xaaa_aaaa_dddd_dddd_UC_41:
01387         case CMD_r110_0100_xaaa_aaaa_dddd_dddd_UC_42:
01388         case CMD_r110_0101_xaaa_aaaa_dddd_dddd_UC_43:
01389         case CMD_r110_0110_xaaa_aaaa_dddd_dddd_UC_44:
01390         case CMD_r110_0111_xaaa_aaaa_dddd_dddd_UC_45:
01391         case CMD_r110_1000_xaaa_aaaa_dddd_dddd_UC_46:
01392         case CMD_r110_1001_xaaa_aaaa_dddd_dddd_UC_47:
01393         case CMD_r110_1010_xaaa_aaaa_dddd_dddd_UC_48:
01394         case CMD_r110_1011_xaaa_aaaa_dddd_dddd_UC_49:
01395         case CMD_r110_1100_xaaa_aaaa_dddd_dddd_UC_50:
01396         case CMD_r110_1101_xaaa_aaaa_dddd_dddd_UC_51:
01397         case CMD_r110_1110_xaaa_aaaa_dddd_dddd_UC_52:
01398             {
01399                 // Condense register names "UC_##" from CMD_r011_1010_xaaa_aaaa_dddd_dddd_UC_0
01400                 int index = commandByte - CMD_r011_1010_xaaa_aaaa_dddd_dddd_UC_0;
01401                 static char retValueString[] = "UC_00";
01402                 retValueString[3] = (index / 10) + '0';
01403                 retValueString[4] = (index % 10) + '0';
01404                 return retValueString;
01405             };
01406         case CMD_r110_1111_xxxx_xxxx_xaaa_aaaa_UCADDR: return "UCADDR";
01407     }
01408 }
01409 
01410 //----------------------------------------
01411 // Menu item 'XF'
01412 //
01413 // FILTER Select Filter and Rate.
01414 // Sets conversion rate based on RATE, LINEF, and CONV_TYPE value. See Table 9a through Table 9d for details.
01415 // For CONV_TYPE_01_Continuous, linef=LINEF_11_SINC4, rate=RATE_0100 selects output data rate 60SPS.
01416 //
01417 // @param[in] linef = filter type, default=MAX11410::LINEF_enum_t::LINEF_11_SINC4
01418 // @param[in] rate = output data rate selection, default=MAX11410::RATE_enum_t::RATE_0100
01419 //
01420 // @return 1 on success; 0 on failure
01421 uint8_t MAX11410::Configure_FILTER(uint8_t linef, uint8_t rate)
01422 {
01423     
01424     //----------------------------------------
01425     // write8 0x08 FILTER
01426     RegWrite(CMD_r000_1000_x0dd_dddd_FILTER, (uint8_t)(0
01427         | (((uint8_t)linef &  3) << 4)
01428         | (((uint8_t)rate  & 15) << 0)
01429         ));
01430     
01431     //----------------------------------------
01432     // success
01433     return 1;
01434 }
01435 
01436 //----------------------------------------
01437 // Menu item 'XP'
01438 //
01439 // PGA Select Gain and Signal Path.
01440 //
01441 // @param[in] sigpath = signal path, default=MAX11410::SIG_PATH_enum_t::SIG_PATH_00_BUFFERED
01442 // @param[in] gain = gain selection, default=MAX11410::GAIN_enum_t::GAIN_000_1
01443 //
01444 // @return 1 on success; 0 on failure
01445 uint8_t MAX11410::Configure_PGA(uint8_t sigpath, uint8_t gain)
01446 {
01447     
01448     //----------------------------------------
01449     // write8 0x0E PGA
01450     RegWrite(CMD_r000_1110_00ss_0ggg_PGA, (uint8_t)(0
01451         | (((uint8_t)sigpath & 2) << 4)
01452         | (((uint8_t)gain    & 7) << 0)
01453         ));
01454     
01455     //----------------------------------------
01456     // success
01457     return 1;
01458 }
01459 
01460 //----------------------------------------
01461 // Menu item 'XC'
01462 //
01463 // CTRL Select clock, format, and reference.
01464 //
01465 // @param[in] extclk = external clock enable, default=0
01466 // @param[in] u_bn = unipolar input range enable, default=0
01467 // @param[in] format = offset binary format enable, default=0
01468 // @param[in] refbufp_en = REFP reference buffer enable, default=0
01469 // @param[in] refbufn_en = REFN reference buffer enable, default=0
01470 // @param[in] ref_sel = reference selection, default=MAX11410::REF_SEL_enum_t::REF_SEL_001_REF1P_REF1N
01471 //
01472 // @return 1 on success; 0 on failure
01473 uint8_t MAX11410::Configure_CTRL(uint8_t extclk, uint8_t u_bn, uint8_t format, uint8_t refbufp_en, uint8_t refbufn_en, uint8_t ref_sel)
01474 {
01475     
01476     //----------------------------------------
01477     // shadow of register CMD_r000_1001_dddd_dddd_CTRL
01478     ctrl = (uint8_t)(0
01479         | (((uint8_t)extclk     & 1) << 7)
01480         | (((uint8_t)u_bn       & 1) << 6)
01481         | (((uint8_t)format     & 1) << 5)
01482         | (((uint8_t)refbufp_en & 1) << 4)
01483         | (((uint8_t)refbufn_en & 1) << 3)
01484         | (((uint8_t)ref_sel    & 7) << 0)
01485         );
01486     
01487     //----------------------------------------
01488     // write8 0x09 CTRL
01489     RegWrite(CMD_r000_1001_dddd_dddd_CTRL, ctrl);
01490     
01491     //----------------------------------------
01492     // success
01493     return 1;
01494 }
01495 
01496 //----------------------------------------
01497 // Menu item 'XR'
01498 //
01499 // CTRL select reference, without changing the other fields.
01500 //
01501 // @pre ctrl = shadow of CTRL register
01502 // @param[in] ref_sel = reference selection, default=MAX11410::REF_SEL_enum_t::REF_SEL_001_REF1P_REF1N
01503 //
01504 // @return 1 on success; 0 on failure
01505 uint8_t MAX11410::Configure_CTRL_REF(uint8_t ref_sel)
01506 {
01507     
01508     //----------------------------------------
01509     // shadow of register CMD_r000_1001_dddd_dddd_CTRL
01510     ctrl = (ctrl & ((uint8_t)(~ 7) << 0))
01511         | (((uint8_t)ref_sel    & 7) << 0);
01512     
01513     //----------------------------------------
01514     // write8 0x09 CTRL
01515     RegWrite(CMD_r000_1001_dddd_dddd_CTRL, ctrl);
01516     
01517     //----------------------------------------
01518     // success
01519     return 1;
01520 }
01521 
01522 //----------------------------------------
01523 // Menu item 'XS'
01524 //
01525 // SOURCE Configure voltage bias source, current source, burnout mode
01526 //
01527 // @param[in] vbias_mode = bias voltage mode, default=MAX11410::VBIAS_MODE_enum_t::VBIAS_MODE_00_Active
01528 // @param[in] brn_mode = burnout source mode, default=MAX11410::BRN_MODE_enum_t::BRN_MODE_00_disabled
01529 // @param[in] idac_mode = current source value, default=MAX11410::IDAC_MODE_enum_t::IDAC_MODE_0000_10uA
01530 //
01531 // @return 1 on success; 0 on failure
01532 uint8_t MAX11410::Configure_SOURCE(uint8_t vbias_mode, uint8_t brn_mode, uint8_t idac_mode)
01533 {
01534     
01535     //----------------------------------------
01536     // write8 0x0A SOURCE
01537     RegWrite(CMD_r000_1010_dddd_dddd_SOURCE, (uint8_t)(0
01538         | (((uint8_t)vbias_mode &  3) << 6)
01539         | (((uint8_t)brn_mode   &  3) << 4)
01540         | (((uint8_t)idac_mode  & 15) << 0)
01541         ));
01542     
01543     //----------------------------------------
01544     // success
01545     return 1;
01546 }
01547 
01548 //----------------------------------------
01549 // Menu item 'XM'
01550 //
01551 // MUX_CTRL0 Select pins for analog input AINP and AINN
01552 //
01553 // @param[in] ainp = channel high side, default=MAX11410::AINP_SEL_enum_t::AINP_SEL_0000_AIN0
01554 // @param[in] ainn = channel low side, default=MAX11410::AINN_SEL_enum_t::AINN_SEL_1010_GND
01555 //
01556 // @return 1 on success; 0 on failure
01557 uint8_t MAX11410::Configure_MUX_CTRL0(uint8_t ainp, uint8_t ainn)
01558 {
01559     
01560     //----------------------------------------
01561     // write8 0x0B MUX_CTRL0
01562     RegWrite(CMD_r000_1011_dddd_dddd_MUX_CTRL0, (uint8_t)(0
01563         | (((uint8_t)ainp & 15) << 4)
01564         | (((uint8_t)ainn & 15) << 0)
01565         ));
01566     
01567     //----------------------------------------
01568     // success
01569     return 1;
01570 }
01571 
01572 //----------------------------------------
01573 // Menu item 'XI'
01574 //
01575 // MUX_CTRL1 Select pins for current source
01576 //
01577 // @param[in] idac1_sel = channel high side, default=MAX11410::IDAC1_SEL_enum_t::IDAC1_SEL_1111_unconnected
01578 // @param[in] idac0_sel = channel low side, default=MAX11410::IDAC0_SEL_enum_t::IDAC0_SEL_1111_unconnected
01579 //
01580 // @return 1 on success; 0 on failure
01581 uint8_t MAX11410::Configure_MUX_CTRL1(uint8_t idac1_sel, uint8_t idac0_sel)
01582 {
01583     
01584     //----------------------------------------
01585     // write8 0x0C MUX_CTRL1
01586     RegWrite(CMD_r000_1100_dddd_dddd_MUX_CTRL1, (uint8_t)(0
01587         | (((uint8_t)idac1_sel & 15) << 4)
01588         | (((uint8_t)idac0_sel & 15) << 0)
01589         ));
01590     
01591     //----------------------------------------
01592     // success
01593     return 1;
01594 }
01595 
01596 //----------------------------------------
01597 // Menu item 'XV'
01598 //
01599 // MUX_CTRL2 Select pins for voltage bias source
01600 //
01601 // @param[in] vbias_ain7_ain0_bitmap = bit map of AIN7..AIN0 enables for voltage bias, default=0
01602 //
01603 // @return 1 on success; 0 on failure
01604 uint8_t MAX11410::Configure_MUX_CTRL2(uint8_t vbias_ain7_ain0_bitmap)
01605 {
01606     
01607     //----------------------------------------
01608     // write8 0x0D MUX_CTRL2
01609     RegWrite(CMD_r000_1101_dddd_dddd_MUX_CTRL2, vbias_ain7_ain0_bitmap);
01610     
01611     //----------------------------------------
01612     // success
01613     return 1;
01614 }
01615 
01616 //----------------------------------------
01617 // Menu item 'X0'
01618 //
01619 // CAL_START Calibrate Self Offset and Gain.
01620 //
01621 // @return 1 on success; 0 on failure
01622 uint8_t MAX11410::Calibrate_Self_Offset_Gain(void)
01623 {
01624     
01625     //----------------------------------------
01626     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01627     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_000_SELF_CAL);
01628     
01629     //----------------------------------------
01630     // success
01631     return 1;
01632 }
01633 
01634 //----------------------------------------
01635 // Menu item 'X1'
01636 //
01637 // CAL_START Calibrate Selected PGA.
01638 //
01639 // @return 1 on success; 0 on failure
01640 uint8_t MAX11410::Calibrate_PGA_Gain(void)
01641 {
01642     
01643     //----------------------------------------
01644     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01645     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_001_PGA_GAIN);
01646     
01647     //----------------------------------------
01648     // success
01649     return 1;
01650 }
01651 
01652 //----------------------------------------
01653 // CAL_START Calibrate System Offset A.
01654 //
01655 // @return 1 on success; 0 on failure
01656 uint8_t MAX11410::Calibrate_System_Offset_A(void)
01657 {
01658     
01659     //----------------------------------------
01660     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01661     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_100_SYS_OFF_A);
01662     
01663     //----------------------------------------
01664     // success
01665     return 1;
01666 }
01667 
01668 //----------------------------------------
01669 // CAL_START Calibrate System Gain A.
01670 //
01671 // @return 1 on success; 0 on failure
01672 uint8_t MAX11410::Calibrate_System_Gain_A(void)
01673 {
01674     
01675     //----------------------------------------
01676     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01677     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_101_SYS_GAIN_A);
01678     
01679     //----------------------------------------
01680     // success
01681     return 1;
01682 }
01683 
01684 //----------------------------------------
01685 // CAL_START Calibrate System Offset B.
01686 //
01687 // @return 1 on success; 0 on failure
01688 uint8_t MAX11410::Calibrate_System_Offset_B(void)
01689 {
01690     
01691     //----------------------------------------
01692     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01693     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_110_SYS_OFF_B);
01694     
01695     //----------------------------------------
01696     // success
01697     return 1;
01698 }
01699 
01700 //----------------------------------------
01701 // CAL_START Calibrate System Gain B.
01702 //
01703 // @return 1 on success; 0 on failure
01704 uint8_t MAX11410::Calibrate_System_Gain_B(void)
01705 {
01706     
01707     //----------------------------------------
01708     // write8 0x03 CAL_START -- RegWrite will poll status until CAL_RDY
01709     RegWrite(CMD_r000_0011_xxxx_xddd_CAL_START, (uint8_t)CAL_TYPE_111_SYS_GAIN_B);
01710     
01711     //----------------------------------------
01712     // success
01713     return 1;
01714 }
01715 
01716 //----------------------------------------
01717 // Menu item '$' -> AINcode[0], AINcode[1], AINcode[2], AINcode[3], AINcode[4], AINcode[5], AINcode[6], AINcode[7], AINcode[8], AINcode[9], AINcode[10]
01718 //
01719 // Measure all ADC channels in sequence.
01720 // Diagnostic output pulse on GP0 for each channel's measurement.
01721 // Diagnostic output pulse on GP1 for entire loop.
01722 //
01723 // @post AINcode[0..10]: measurement result LSB code
01724 //
01725 // @return 1 on success; 0 on failure
01726 uint8_t MAX11410::Read_All_Voltages(void)
01727 {
01728     
01729     //----------------------------------------
01730     // scan AIN0..AIN9
01731     //
01732     // diagnostic GPIO pulse on MAX11410 GP1 pin (0xc3 = logic 0, 0xc4 = logic 1)
01733     RegWrite(CMD_r000_0101_dddd_xddd_GP1_CTRL, 0xc3); // GP1 = 0
01734     //
01735     const MAX11410_AINN_SEL_enum_t ainn = AINN_SEL_1010_GND;
01736     for(uint8_t ainp =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_0000_AIN0; ainp <=  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD; ainp++)
01737     {
01738         // diagnostic GPIO pulse on MAX11410 GP0 pin (0xc3 = logic 0, 0xc4 = logic 1)
01739         RegWrite(CMD_r000_0100_dddd_xddd_GP0_CTRL, 0xc3); // GP0 = 0
01740         //
01741         Measure_Voltage((MAX11410_AINP_SEL_enum_t)ainp, ainn);
01742         // @post AINcode[ainp]: measurement result LSB code
01743         //
01744         // diagnostic GPIO pulse on MAX11410 GP0 pin (0xc3 = logic 0, 0xc4 = logic 1)
01745         RegWrite(CMD_r000_0100_dddd_xddd_GP0_CTRL, 0xc4); // GP0 = 1
01746         //
01747     }
01748     // diagnostic GPIO pulse on MAX11410 GP1 pin (0xc3 = logic 0, 0xc4 = logic 1)
01749     RegWrite(CMD_r000_0101_dddd_xddd_GP1_CTRL, 0xc4); // GP1 = 1
01750     //
01751     
01752     //----------------------------------------
01753     // success
01754     return 1;
01755 }
01756 
01757 //----------------------------------------
01758 // Menu item 'V'
01759 // Trigger Measurement for voltage input.
01760 //
01761 // Example code for typical voltage measurement.
01762 //
01763 // @pre external connection REF2P-REF2N is a reference voltage
01764 // @pre VRef = Voltage of REF input, in Volts
01765 // @pre v_filter = filter register configuration, 0x34 for LINEF_11_SINC4 RATE_0100 output data rate 60SPS
01766 // @pre v_ctrl = ctrl register configuration, 0x02 for bipolar REF_SEL_010_REF2P_REF2N
01767 // @pre v_pga = pga register configuration, 0x00 for SIG_PATH_00_BUFFERED GAIN_000_1
01768 // @param[in] ainp = channel high side, default=AINP_SEL_0000_AIN0
01769 // @param[in] ainn = channel low side, default=AINN_SEL_1010_GND
01770 // @post AINcode[ainp]: measurement result LSB code
01771 //
01772 // Output data rate (sample rate) is determined by filter register.
01773 // filter register configuration in Measure_Voltage CONV_TYPE_01_Continuous
01774 // v_filter=0x00 -- LINEF_00_50Hz_60Hz_FIR  RATE_0000 |  1.1SPS
01775 // v_filter=0x01 -- LINEF_00_50Hz_60Hz_FIR  RATE_0001 |  2.1SPS
01776 // v_filter=0x02 -- LINEF_00_50Hz_60Hz_FIR  RATE_0010 |  4.2SPS
01777 // v_filter=0x03 -- LINEF_00_50Hz_60Hz_FIR  RATE_0011 |  8.4SPS
01778 // v_filter=0x04 -- LINEF_00_50Hz_60Hz_FIR  RATE_0100 | 16.8SPS
01779 // v_filter=0x10 -- LINEF_01_50Hz_FIR       RATE_0000 |  1.3SPS
01780 // v_filter=0x11 -- LINEF_01_50Hz_FIR       RATE_0001 |  2.7SPS
01781 // v_filter=0x12 -- LINEF_01_50Hz_FIR       RATE_0010 |  5.3SPS
01782 // v_filter=0x13 -- LINEF_01_50Hz_FIR       RATE_0011 | 10.7SPS
01783 // v_filter=0x14 -- LINEF_01_50Hz_FIR       RATE_0100 | 21.3SPS
01784 // v_filter=0x15 -- LINEF_01_50Hz_FIR       RATE_0101 | 40.0SPS
01785 // v_filter=0x20 -- LINEF_10_60Hz_FIR       RATE_0000 |   1.3SPS
01786 // v_filter=0x21 -- LINEF_10_60Hz_FIR       RATE_0001 |   2.7SPS
01787 // v_filter=0x22 -- LINEF_10_60Hz_FIR       RATE_0010 |   5.3SPS
01788 // v_filter=0x23 -- LINEF_10_60Hz_FIR       RATE_0011 |  10.7SPS
01789 // v_filter=0x24 -- LINEF_10_60Hz_FIR       RATE_0100 |  21.3SPS
01790 // v_filter=0x25 -- LINEF_10_60Hz_FIR       RATE_0101 |  40.0SPS
01791 // v_filter=0x30 -- LINEF_11_SINC4          RATE_0000 |    4SPS
01792 // v_filter=0x31 -- LINEF_11_SINC4          RATE_0001 |   10SPS
01793 // v_filter=0x32 -- LINEF_11_SINC4          RATE_0010 |   20SPS
01794 // v_filter=0x33 -- LINEF_11_SINC4          RATE_0011 |   40SPS
01795 // v_filter=0x34 --*LINEF_11_SINC4          RATE_0100 |   60SPS
01796 // v_filter=0x35 -- LINEF_11_SINC4          RATE_0101 |  120SPS
01797 // v_filter=0x36 -- LINEF_11_SINC4          RATE_0110 |  240SPS
01798 // v_filter=0x37 -- LINEF_11_SINC4          RATE_0111 |  480SPS
01799 // v_filter=0x38 -- LINEF_11_SINC4          RATE_1000 |  960SPS
01800 // v_filter=0x39 -- LINEF_11_SINC4          RATE_1001 | 1920SPS
01801 //
01802 // @return ideal voltage calculated from raw LSB code and reference voltage
01803 double MAX11410::Measure_Voltage(MAX11410_AINP_SEL_enum_t ainp, MAX11410_AINN_SEL_enum_t ainn)
01804 {
01805     
01806     //----------------------------------------
01807     // restrict channel selection to valid index range
01808     if ((uint8_t)ainp >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
01809     {
01810         ainp =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
01811     }
01812     
01813     //----------------------------------------
01814     // restrict channel selection to valid index range
01815     if ((uint8_t)ainn >  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND)
01816     {
01817         ainn =  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND;
01818     }
01819     
01820     //----------------------------------------
01821     // write8 0x0B MUX_CTRL0 = 0x0A to select AINP=AIN0 and AINN=GND
01822     Configure_MUX_CTRL0((uint8_t)ainp, (uint8_t)ainn);
01823     
01824     //----------------------------------------
01825     // write8 0x09 CTRL to select reference and Data Format (Unipolar or Bipolar)
01826     RegWrite(CMD_r000_1001_dddd_dddd_CTRL, v_ctrl);
01827     ctrl = v_ctrl;
01828     
01829     //----------------------------------------
01830     // write8 0x0E PGA and update pgaGain
01831     Configure_PGA(
01832             ((v_pga >> 4) & 2),  // sigpath
01833             ( v_pga       & 7)); // gain
01834     
01835     //----------------------------------------
01836     // write8 0x08 FILTER to select output data rate
01837     RegWrite(CMD_r000_1000_x0dd_dddd_FILTER, v_filter);
01838     
01839     //----------------------------------------
01840     // write8 0x01 CONV_START = 0x01 to set Conversion Mode = Continuous
01841     RegWrite(CMD_r000_0001_xddd_xxdd_CONV_START, 0x01);
01842     
01843     //----------------------------------------
01844     // purge old data from data0 register
01845     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)ainp & 0x0F)]);
01846     data0 = AINcode[((int)ainp & 0x0F)];
01847     
01848     //----------------------------------------
01849     // read24 0x80|0x38 STATUS (%SW 0xB8 0 0 0)
01850     RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
01851     
01852     //----------------------------------------
01853     // wait until STATUS_enum_t::STATUS_000010_DATA_RDY indicates data is available
01854     // A bad SPI interface can cause bit slippage, which makes this loop get stuck. Expect *PART_ID? = 0x000F02
01855     // while ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0) {
01856     // possible infinite loop; need a timeout or futility countdown to escape
01857     for (int futility_countdown = loop_limit;
01858         ((futility_countdown > 0) &&
01859         ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0));
01860         futility_countdown--)
01861     {
01862         RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
01863 #if 1
01864         // improve response time at the cost of more program size
01865         if (futility_countdown < (loop_limit - 5)) {
01866             wait_ms(1); // timing delay function, platform-specific
01867         }
01868         if (futility_countdown < (loop_limit - 10)) {
01869             wait_ms(2); // timing delay function, platform-specific
01870         }
01871         if (futility_countdown < (loop_limit - 15)) {
01872             wait_ms(5); // timing delay function, platform-specific
01873         }
01874         if (futility_countdown < (loop_limit - 20)) {
01875             wait_ms(10); // timing delay function, platform-specific
01876         }
01877         if (futility_countdown < (loop_limit - 25)) {
01878             wait_ms(20); // timing delay function, platform-specific
01879         }
01880         if (futility_countdown < (loop_limit - 30)) {
01881             wait_ms(50); // timing delay function, platform-specific
01882         }
01883         if (futility_countdown < (loop_limit - 35)) {
01884             wait_ms(100); // timing delay function, platform-specific
01885         }
01886 #else
01887         if (loop_limit > 5) {
01888             wait_ms(20); // timing delay function, platform-specific
01889         }
01890         if (loop_limit > 10) {
01891             wait_ms(50); // timing delay function, platform-specific
01892         }
01893         if (loop_limit > 30) {
01894             wait_ms(100); // timing delay function, platform-specific
01895         }
01896 #endif
01897     }
01898     
01899     //----------------------------------------
01900     // read24 0x80|0x30 DATA0 (%SW 0xB0 0 0 0): AINcode[ainp] = measurement
01901     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)ainp & 0x0F)]);
01902     data0 = AINcode[((int)ainp & 0x0F)];
01903     
01904     //----------------------------------------
01905     // ideal voltage calculated from raw LSB code and reference voltage
01906     return VoltageOfCode(AINcode[((int)ainp & 0x0F)]);
01907 }
01908 
01909 //----------------------------------------
01910 // Menu item 'R' -> rtd_ohm, rtd_degc
01911 // Trigger Measurement for Resistive Temperature Device (RTD).
01912 //
01913 // Example code for typical RTD measurement.
01914 //
01915 // @pre external connection REF1P-REF1N is a reference resistor
01916 // @pre ref1_v = reference resistance in ohms, default=4999
01917 // @pre rtd_filter = filter register configuration, 0x34 for LINEF_11_SINC4 RATE_0100 output data rate 60SPS
01918 // @pre rtd_ctrl = ctrl register configuration, 0x40 for ref0_v, 0x41 for ref1_v, 0x42 for ref2_v
01919 // @pre rtd_souce = souce register configuration, 0x0B for IDAC_MODE_1011_400uA
01920 // @pre rtd_pga = pga register configuration, 0x21 for SIG_PATH_10_PGA GAIN_001_2
01921 // @param[in] rtd_iout = channel RTD high side force, default=AINP_SEL_0111_AIN7
01922 // @param[in] rtd_ainp = channel RTD high side sense, default=AINP_SEL_1000_AIN8
01923 // @param[in] rtd_ainn = channel RTD low side, default=AINN_SEL_1001_AIN9
01924 // @post AINcode[rtd_ainp]: measurement result LSB code
01925 // @post rtd_ohm: measurement result resistance in Ohms
01926 // @post rtd_degc: Temperature calculated from RTD Resistance; Thermocouple Cold Junction, in degrees C
01927 //
01928 // Output data rate (sample rate) is determined by filter register.
01929 // filter register configuration in Measure_RTD CONV_TYPE_01_Continuous
01930 // rtd_filter=0x00 -- LINEF_00_50Hz_60Hz_FIR  RATE_0000 |  1.1SPS
01931 // rtd_filter=0x01 -- LINEF_00_50Hz_60Hz_FIR  RATE_0001 |  2.1SPS
01932 // rtd_filter=0x02 -- LINEF_00_50Hz_60Hz_FIR  RATE_0010 |  4.2SPS
01933 // rtd_filter=0x03 -- LINEF_00_50Hz_60Hz_FIR  RATE_0011 |  8.4SPS
01934 // rtd_filter=0x04 -- LINEF_00_50Hz_60Hz_FIR  RATE_0100 | 16.8SPS
01935 // rtd_filter=0x10 -- LINEF_01_50Hz_FIR       RATE_0000 |  1.3SPS
01936 // rtd_filter=0x11 -- LINEF_01_50Hz_FIR       RATE_0001 |  2.7SPS
01937 // rtd_filter=0x12 -- LINEF_01_50Hz_FIR       RATE_0010 |  5.3SPS
01938 // rtd_filter=0x13 -- LINEF_01_50Hz_FIR       RATE_0011 | 10.7SPS
01939 // rtd_filter=0x14 -- LINEF_01_50Hz_FIR       RATE_0100 | 21.3SPS
01940 // rtd_filter=0x15 -- LINEF_01_50Hz_FIR       RATE_0101 | 40.0SPS
01941 // rtd_filter=0x20 -- LINEF_10_60Hz_FIR       RATE_0000 |   1.3SPS
01942 // rtd_filter=0x21 -- LINEF_10_60Hz_FIR       RATE_0001 |   2.7SPS
01943 // rtd_filter=0x22 -- LINEF_10_60Hz_FIR       RATE_0010 |   5.3SPS
01944 // rtd_filter=0x23 -- LINEF_10_60Hz_FIR       RATE_0011 |  10.7SPS
01945 // rtd_filter=0x24 -- LINEF_10_60Hz_FIR       RATE_0100 |  21.3SPS
01946 // rtd_filter=0x25 -- LINEF_10_60Hz_FIR       RATE_0101 |  40.0SPS
01947 // rtd_filter=0x30 -- LINEF_11_SINC4          RATE_0000 |    4SPS
01948 // rtd_filter=0x31 -- LINEF_11_SINC4          RATE_0001 |   10SPS
01949 // rtd_filter=0x32 -- LINEF_11_SINC4          RATE_0010 |   20SPS
01950 // rtd_filter=0x33 -- LINEF_11_SINC4          RATE_0011 |   40SPS
01951 // rtd_filter=0x34 --*LINEF_11_SINC4          RATE_0100 |   60SPS
01952 // rtd_filter=0x35 -- LINEF_11_SINC4          RATE_0101 |  120SPS
01953 // rtd_filter=0x36 -- LINEF_11_SINC4          RATE_0110 |  240SPS
01954 // rtd_filter=0x37 -- LINEF_11_SINC4          RATE_0111 |  480SPS
01955 // rtd_filter=0x38 -- LINEF_11_SINC4          RATE_1000 |  960SPS
01956 // rtd_filter=0x39 -- LINEF_11_SINC4          RATE_1001 | 1920SPS
01957 //
01958 // @return resistance calculated from raw LSB code and reference resistance
01959 double MAX11410::Measure_RTD(MAX11410_AINP_SEL_enum_t rtd_iout, MAX11410_AINP_SEL_enum_t rtd_ainp, MAX11410_AINN_SEL_enum_t rtd_ainn)
01960 {
01961     
01962     //----------------------------------------
01963     // restrict channel selection to valid index range
01964     if ((uint8_t)rtd_iout >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
01965     {
01966         rtd_iout =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
01967     }
01968     
01969     //----------------------------------------
01970     // restrict channel selection to valid index range
01971     if ((uint8_t)rtd_ainp >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
01972     {
01973         rtd_ainp =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
01974     }
01975     
01976     //----------------------------------------
01977     // restrict channel selection to valid index range
01978     if ((uint8_t)rtd_ainn >  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND)
01979     { 
01980         rtd_ainn =  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND;
01981     }
01982     
01983     //----------------------------------------
01984     // write8 0x08 FILTER to select output data rate
01985     RegWrite(CMD_r000_1000_x0dd_dddd_FILTER, rtd_filter);
01986     
01987     //----------------------------------------
01988     // write8 0x09 CTRL to select reference resistor REF1P/REF1N; Data Format = Unipolar
01989     RegWrite(CMD_r000_1001_dddd_dddd_CTRL, rtd_ctrl);
01990     ctrl = rtd_ctrl;
01991     
01992     //----------------------------------------
01993     // write8 0x0A SOURCE to select IDAC_MODE 400uA; AIN9=2.000V, AIN8(PT100)=2.040V, AIN8(PT1000)=2.400V
01994     RegWrite(CMD_r000_1010_dddd_dddd_SOURCE, rtd_source);
01995     
01996     //----------------------------------------
01997     // write8 0x0B MUX_CTRL0 = 0x89 to select AINP=AIN8 and AINN=AIN9
01998     Configure_MUX_CTRL0((uint8_t)rtd_ainp, (uint8_t)rtd_ainn);
01999     
02000     //----------------------------------------
02001     // write8 0x0C MUX_CTRL1 = 0xF7 to select IDAC1_SEL=NC, IDAC0_SEL=AIN7
02002     Configure_MUX_CTRL1((uint8_t)IDAC1_SEL_1111_unconnected, (uint8_t)rtd_iout);
02003     
02004     //----------------------------------------
02005     // write8 0x0E PGA and update pgaGain
02006     Configure_PGA(
02007             ((rtd_pga >> 4) & 2),  // sigpath
02008             ( rtd_pga       & 7)); // gain
02009     
02010     //----------------------------------------
02011     // diagnostic GPIO pulse on GP1 during RTD power-up interval rtd_ms
02012     RegWrite(CMD_r000_0101_dddd_xddd_GP1_CTRL, 0xc3); // diagnostic GPIO pulse GP1
02013             // write8 0x05 GP1_CTRL (%SW 0x05 0xc3) 11000 output 011 logic 0
02014     
02015     //----------------------------------------
02016     // timing delay after enable RTD bias current
02017     wait_ms(rtd_ms); // timing delay function, platform-specific
02018     
02019     //----------------------------------------
02020     // diagnostic GPIO pulse on GP1 during RTD power-up interval rtd_ms
02021     RegWrite(CMD_r000_0101_dddd_xddd_GP1_CTRL, 0xc4); // diagnostic GPIO pulse GP1
02022             // write8 0x05 GP1_CTRL (%SW 0x05 0xc4) 11000 output 100 logic 1
02023     
02024     //----------------------------------------
02025     // write8 0x01 CONV_START = 0x01 to set Conversion Mode = Continuous
02026     RegWrite(CMD_r000_0001_xddd_xxdd_CONV_START, 0x01);
02027     
02028     //----------------------------------------
02029     // purge old data from data0 register
02030     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)rtd_ainp & 0x0F)]);
02031     data0 = AINcode[((int)rtd_ainp & 0x0F)];
02032     
02033     //----------------------------------------
02034     // read24 0x80|0x38 STATUS (%SW 0xB8 0 0 0)
02035     RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
02036     
02037     //----------------------------------------
02038     // wait until STATUS_enum_t::STATUS_000010_DATA_RDY indicates data is available
02039     // A bad SPI interface can cause bit slippage, which makes this loop get stuck. Expect *PART_ID? = 0x000F02
02040     // while ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0) {
02041     // possible infinite loop; need a timeout or futility countdown to escape
02042     for (int futility_countdown = loop_limit;
02043         ((futility_countdown > 0) &&
02044         ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0));
02045         futility_countdown--)
02046     {
02047         RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
02048     }
02049     
02050     //----------------------------------------
02051     // read24 0x80|0x30 DATA0 (%SW 0xB0 0 0 0): AINcode[ainp] = measurement
02052     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)rtd_ainp & 0x0F)]);
02053     data0 = AINcode[((int)rtd_ainp & 0x0F)];
02054     
02055     //----------------------------------------
02056     // turn off RTD bias current to avoid self-heating (unless rtd_ms is 0)
02057     if (rtd_ms != 0)
02058     {
02059         // write8 0x0C MUX_CTRL1 = 0xFF to select IDAC1_SEL=NC, IDAC0_SEL=NC
02060         Configure_MUX_CTRL1((uint8_t)IDAC1_SEL_1111_unconnected, (uint8_t)IDAC0_SEL_1111_unconnected);
02061     }
02062     
02063     //----------------------------------------
02064     // resistance calculated from raw LSB code and ref1_v reference resistance in ohms
02065     rtd_ohm = VoltageOfCode(AINcode[((int)rtd_ainp & 0x0F)]);
02066     TemperatureOfRTD(rtd_ohm); // calculate rtd_degc
02067     return rtd_ohm;
02068 }
02069 
02070 //----------------------------------------
02071 // Return the physical temperature corresponding to measured resistance
02072 // of a PT1000 type Resistive Temperature Device (RTD).
02073 //
02074 // @param[in] rtd_ohm = RTD resistance in ohms, default=1000
02075 // @post rtd_degc: Temperature calculated from RTD Resistance; Thermocouple Cold Junction, in degrees C
02076 //
02077 // @return ideal temperature in degrees C, calculated from RTD resistance in ohms
02078 // @test group RTD_PT1000 // PT1000 type Resistive Temperature Device (RTD)
02079 // @test group RTD_PT1000 tinyTester.blink_time_msec = 20 // quickly speed through the software verification
02080 // @test group RTD_PT1000 TemperatureOfRTD_PT1000(842.94) expect -40.0 within 0.1 // PT-1000 RTD at -40C
02081 // @test group RTD_PT1000 TemperatureOfRTD_PT1000(1000.0) expect 0.0   within 0.1 // PT-1000 RTD at 0C
02082 // @test group RTD_PT1000 TemperatureOfRTD_PT1000(1097.3) expect 25.0  within 0.1 // PT-1000 RTD at 25C
02083 // @test group RTD_PT1000 TemperatureOfRTD_PT1000(1328.1) expect 85.0  within 0.1 // PT-1000 RTD at 85C
02084 // @test group RTD_PT1000 TemperatureOfRTD_PT1000(1479.5) expect 125.0 within 0.1 // PT-1000 RTD at 125C
02085 // @test group RTD_PT1000 tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
02086 //
02087 double MAX11410::TemperatureOfRTD_PT1000(double rtd_ohm)
02088 {
02089     
02090     //----------------------------------------
02091     // Temperature from RTD Resistance maths
02092     // ITS-90 PT-1000 RTD
02093     double R0 = 1000.0;
02094     double a = 3.9083e-3;
02095     double b = -5.7750e-7;
02096     // calculate T from R and R0
02097     double sqrtTerm = sqrt(R0*R0 * a*a - 4*R0*b*(R0 - rtd_ohm));
02098     double denominator = 2 * R0 * b;
02099     rtd_degc = ((-R0 * a) + (sqrtTerm)) / denominator;
02100     return rtd_degc;
02101 }
02102 
02103 //----------------------------------------
02104 // Return the physical temperature corresponding to measured resistance
02105 // of a PT100 type Resistive Temperature Device (RTD).
02106 //
02107 // @param[in] rtd_ohm = RTD resistance in ohms, default=100
02108 // @post rtd_degc: Temperature calculated from RTD Resistance; Thermocouple Cold Junction, in degrees C
02109 //
02110 // @return ideal temperature in degrees C, calculated from RTD resistance in ohms
02111 // @test group RTD_PT100 // PT100 type Resistive Temperature Device (RTD)
02112 // @test group RTD_PT100 tinyTester.blink_time_msec = 20 // quickly speed through the software verification
02113 // @test group RTD_PT100 TemperatureOfRTD_PT100(84.294) expect -40.0 within 0.1 // PT-100 RTD at -40C
02114 // @test group RTD_PT100 TemperatureOfRTD_PT100(100.00) expect 0.0   within 0.1 // PT-100 RTD at 0C
02115 // @test group RTD_PT100 TemperatureOfRTD_PT100(109.73) expect 25.0  within 0.1 // PT-100 RTD at 25C
02116 // @test group RTD_PT100 TemperatureOfRTD_PT100(132.81) expect 85.0  within 0.1 // PT-100 RTD at 85C
02117 // @test group RTD_PT100 TemperatureOfRTD_PT100(147.95) expect 125.0 within 0.1 // PT-100 RTD at 125C
02118 // @test group RTD_PT100 tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
02119 //
02120 double MAX11410::TemperatureOfRTD_PT100(double rtd_ohm)
02121 {
02122     
02123     //----------------------------------------
02124     // Temperature from RTD Resistance maths
02125     // ITS-90 PT-100 RTD
02126     double R0 = 100.0;
02127     double a = 3.9083e-3;
02128     double b = -5.7750e-7;
02129     // calculate T from R and R0
02130     double sqrtTerm = sqrt(R0*R0 * a*a - 4*R0*b*(R0 - rtd_ohm));
02131     double denominator = 2 * R0 * b;
02132     rtd_degc = ((-R0 * a) + (sqrtTerm)) / denominator;
02133     return rtd_degc;
02134 }
02135 
02136 //----------------------------------------
02137 // Return the physical temperature corresponding to measured resistance
02138 // of a PT100 or PT1000 type Resistive Temperature Device (RTD).
02139 //
02140 // @param[in] rtd_ohm = RTD resistance in ohms, default=100
02141 // @post rtd_degc: Temperature calculated from RTD Resistance; Thermocouple Cold Junction, in degrees C
02142 //
02143 // @return ideal temperature in degrees C, calculated from RTD resistance in ohms
02144 // @test group RTD // Verify function TemperatureOfRTD
02145 // @test group RTD tinyTester.blink_time_msec = 20 // quickly speed through the software verification
02146 // @test group RTD TemperatureOfRTD(84.294) expect -40.0 within 0.1 // PT-100 RTD at -40C
02147 // @test group RTD TemperatureOfRTD(100.00) expect 0.0   within 0.1 // PT-100 RTD at 0C
02148 // @test group RTD TemperatureOfRTD(109.73) expect 25.0  within 0.1 // PT-100 RTD at 25C
02149 // @test group RTD TemperatureOfRTD(132.81) expect 85.0  within 0.1 // PT-100 RTD at 85C
02150 // @test group RTD TemperatureOfRTD(147.95) expect 125.0 within 0.1 // PT-100 RTD at 125C
02151 // @test group RTD TemperatureOfRTD(842.94) expect -40.0 within 0.1 // PT-1000 RTD at -40C
02152 // @test group RTD TemperatureOfRTD(1000.0) expect 0.0   within 0.1 // PT-1000 RTD at 0C
02153 // @test group RTD TemperatureOfRTD(1097.3) expect 25.0  within 0.1 // PT-1000 RTD at 25C
02154 // @test group RTD TemperatureOfRTD(1328.1) expect 85.0  within 0.1 // PT-1000 RTD at 85C
02155 // @test group RTD TemperatureOfRTD(1479.5) expect 125.0 within 0.1 // PT-1000 RTD at 125C
02156 // @test group RTD tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
02157 //
02158 double MAX11410::TemperatureOfRTD(double rtd_ohm)
02159 {
02160     
02161     //----------------------------------------
02162     // return TemperatureOfRTD_PT100 or TemperatureOfRTD_PT1000
02163     if (rtd_ohm > 500.0)
02164     {
02165         return TemperatureOfRTD_PT1000(rtd_ohm);
02166     }
02167     else
02168     {
02169         return TemperatureOfRTD_PT100(rtd_ohm);
02170     }
02171 }
02172 
02173 //----------------------------------------
02174 // Menu item 'TM' -> tc_v, tc_delta_degc, tc_degc
02175 // Trigger Measurement for Thermocouple
02176 //
02177 // Example code for typical Thermocouple measurement.
02178 // An RTD measures the "cold junction" where TC connects to the board,
02179 // and the TC measures the temperature difference above the cold junction.
02180 //
02181 // @param[in] tc_ainp = channel of Thermocouple high side, default=AINP_SEL_0101_AIN5
02182 // @param[in] tc_ainn = channel of Thermocouple low side, default=AINN_SEL_0110_AIN6
02183 // @param[in] rtd_iout = channel RTD high side force, default=AINP_SEL_0111_AIN7
02184 // @param[in] rtd_ainp = channel RTD high side sense, default=AINP_SEL_1000_AIN8
02185 // @param[in] rtd_ainn = channel RTD low side, default=AINN_SEL_1001_AIN9
02186 // @post AINcode[tc_ainp]: measurement result LSB code
02187 // @post tc_v: raw thermocouple voltage in Volts
02188 // @post tc_delta_degc: temperature in degC above cold junction
02189 // @post tc_degc: temperature in degC
02190 //
02191 // @return 1 on success; 0 on failure
02192 double MAX11410::Measure_Thermocouple(MAX11410_AINP_SEL_enum_t tc_ainp, MAX11410_AINN_SEL_enum_t tc_ainn, MAX11410_AINP_SEL_enum_t rtd_iout, MAX11410_AINP_SEL_enum_t rtd_ainp, MAX11410_AINN_SEL_enum_t rtd_ainn)
02193 {
02194     
02195     //----------------------------------------
02196     // restrict channel selection to valid index range
02197     if ((uint8_t)tc_ainp >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
02198     {
02199         tc_ainp =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
02200     }
02201     
02202     //----------------------------------------
02203     // restrict channel selection to valid index range
02204     if ((uint8_t)tc_ainn >  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND)
02205     {
02206         tc_ainn =  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND;
02207     }
02208     
02209     //----------------------------------------
02210     // restrict channel selection to valid index range
02211     if ((uint8_t)rtd_iout >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
02212     {
02213         rtd_iout =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
02214     }
02215     
02216     //----------------------------------------
02217     // restrict channel selection to valid index range
02218     if ((uint8_t)rtd_ainp >  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD)
02219     {
02220         rtd_ainp =  /* MAX11410_AINP_SEL_enum_t:: */ AINP_SEL_1010_AVDD;
02221     }
02222     
02223     //----------------------------------------
02224     // restrict channel selection to valid index range
02225     if ((uint8_t)rtd_ainn >  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND)
02226     { 
02227         rtd_ainn =  /* MAX11410_AINN_SEL_enum_t:: */ AINN_SEL_1010_GND;
02228     }
02229     
02230     //----------------------------------------
02231     // write8 0x0B MUX_CTRL0 = 0x0A to select AINP=AIN0 and AINN=GND
02232     Configure_MUX_CTRL0((uint8_t)tc_ainp, (uint8_t)tc_ainn);
02233     
02234     //----------------------------------------
02235     // write8 0x09 CTRL to select reference REF2P/REF2N; Data Format = Bipolar 2's Complement
02236     Configure_CTRL(/*extclk*/ 0, /*u_bn*/ 0, /*format*/ 0,
02237                 /*refbufp_en*/ 0, /*refbufn_en*/ 0,
02238                 /*ref_sel*/ (uint8_t)REF_SEL_010_REF2P_REF2N);
02239     
02240     //----------------------------------------
02241     // write8 0x0E PGA
02242     Configure_PGA((uint8_t) /* MAX11410_SIG_PATH_enum_t:: */ SIG_PATH_00_BUFFERED, 
02243                 (uint8_t) /* MAX11410_GAIN_enum_t:: */ GAIN_000_1);
02244     
02245     //----------------------------------------
02246     // write8 0x08 FILTER = 0x34 to select RATE_0100, LINEF_11_SINC4 60SPS (given CONV_TYPE_01_Continuous)
02247     Configure_FILTER((uint8_t) /* MAX11410::MAX11410_LINEF_enum_t:: */ LINEF_11_SINC4,
02248                 (uint8_t) /* MAX11410::MAX11410_RATE_enum_t:: */ RATE_0100);
02249     
02250     //----------------------------------------
02251     // write8 0x01 CONV_START = 0x01 to set Conversion Mode = Continuous
02252     RegWrite(CMD_r000_0001_xddd_xxdd_CONV_START, 0x01);
02253     
02254     //----------------------------------------
02255     // purge old data from data0 register
02256     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)tc_ainp & 0x0F)]);
02257     data0 = AINcode[((int)tc_ainp & 0x0F)];
02258     
02259     //----------------------------------------
02260     // read24 0x80|0x38 STATUS (%SW 0xB8 0 0 0)
02261     RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
02262     
02263     //----------------------------------------
02264     // wait until STATUS_enum_t::STATUS_000010_DATA_RDY indicates data is available
02265     // A bad SPI interface can cause bit slippage, which makes this loop get stuck. Expect *PART_ID? = 0x000F02
02266     // while ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0) {
02267     // possible infinite loop; need a timeout or futility countdown to escape
02268     for (int futility_countdown = loop_limit;
02269         ((futility_countdown > 0) &&
02270         ((status &  /* MAX11410_STATUS_enum_t:: */ STATUS_000010_DATA_RDY) == 0));
02271         futility_countdown--)
02272     {
02273         RegRead(CMD_r011_1000_dddd_dddd_dddd_dddd_dxxx_dddd_STATUS, &status);
02274     }
02275     
02276     //----------------------------------------
02277     // read24 0x80|0x30 DATA0 (%SW 0xB0 0 0 0): AINcode[tc_ainp] = measurement
02278     RegRead(CMD_r011_0000_dddd_dddd_dddd_dddd_dddd_dddd_DATA0, &AINcode[((int)tc_ainp & 0x0F)]);
02279     data0 = AINcode[((int)tc_ainp & 0x0F)];
02280     
02281     //----------------------------------------
02282     // ideal voltage calculated from raw LSB code and reference voltage
02283     tc_v = VoltageOfCode(AINcode[((int)tc_ainp & 0x0F)]);
02284     
02285     //----------------------------------------
02286     // ideal voltage calculated from raw LSB code and reference voltage
02287     tc_delta_degc = TemperatureOfTC_TypeK(tc_v);
02288     
02289     //----------------------------------------
02290     // ideal voltage calculated from raw LSB code and reference voltage
02291     tc_degc = rtd_degc + tc_delta_degc;
02292     
02293     //----------------------------------------
02294     // ideal voltage calculated from raw LSB code and reference voltage
02295     return tc_v;
02296 }
02297 
02298 //----------------------------------------
02299 // Return the physical temperature corresponding to measured voltage
02300 // of a type K Thermocouple (TC).
02301 //
02302 // @pre {0}.rtd_degc = cold junction temperature, in degrees C
02303 // @param[in] tc_v = Thermocouple voltage in volts, default=0.0254
02304 //
02305 // @return ideal temperature in degrees C, calculated from RTD resistance in ohms
02306 // @test group TC_1 // Verify Thermocouple function TemperatureOfTC_TypeK
02307 // @test group TC_2 // Verify Thermocouple function TemperatureOfTC_TypeK in more detail
02308 // @test group TC_1 tinyTester.blink_time_msec = 20 // quickly speed through the software verification
02309 // @test group TC_1 TemperatureOfTC_TypeK(0.000e-3) expect  0.0    within 0.1 // TC_TypeK at   0C = 0.000mV
02310 // @test group TC_1 TemperatureOfTC_TypeK(0.039e-3) expect  1.0    within 0.1 // TC_TypeK at   1C = 0.039mV
02311 // @test group TC_1 TemperatureOfTC_TypeK(0.079e-3) expect  2.0    within 0.1 // TC_TypeK at   2C = 0.079mV
02312 // @test group TC_1 TemperatureOfTC_TypeK(0.119e-3) expect  3.0    within 0.1 // TC_TypeK at   3C = 0.119mV
02313 // @test group TC_2 TemperatureOfTC_TypeK(0.158e-3) expect  4.0     within 0.1 // TC_TypeK at   4C = 0.158mV
02314 // @test group TC_2 TemperatureOfTC_TypeK(0.198e-3) expect  5.0     within 0.1 // TC_TypeK at   5C = 0.198mV
02315 // @test group TC_2 TemperatureOfTC_TypeK(0.238e-3) expect  6.0     within 0.1 // TC_TypeK at   6C = 0.238mV
02316 // @test group TC_2 TemperatureOfTC_TypeK(0.2775e-3) expect  7.0    within 0.1 // TC_TypeK at   7C = 0.2775mV
02317 // @test group TC_2 TemperatureOfTC_TypeK(0.317e-3) expect  8.0     within 0.1 // TC_TypeK at   8C = 0.317mV
02318 // @test group TC_2 TemperatureOfTC_TypeK(0.357e-3) expect  9.0     within 0.1 // TC_TypeK at   9C = 0.357mV
02319 // @test group TC_1 TemperatureOfTC_TypeK(0.397e-3) expect 10.0    within 0.1 // TC_TypeK at  10C = 0.397mV
02320 // @test group TC_1 TemperatureOfTC_TypeK(0.798e-3) expect 20.0    within 0.1 // TC_TypeK at  20C = 0.798mV
02321 // @test group TC_1 TemperatureOfTC_TypeK(1.081e-3) expect 27.0    within 0.1 // TC_TypeK at  27C = 1.081mV
02322 // @test group TC_1 TemperatureOfTC_TypeK(1.203e-3) expect 30.0    within 0.1 // TC_TypeK at  30C = 1.203mV
02323 // @test group TC_1 TemperatureOfTC_TypeK(1.612e-3) expect 40.0    within 0.1 // TC_TypeK at  40C = 1.612mV
02324 // @test group TC_1 TemperatureOfTC_TypeK(2.023e-3) expect 50.0    within 0.1 // TC_TypeK at  50C = 2.023mV
02325 // @test group TC_1 TemperatureOfTC_TypeK(2.436e-3) expect 60.0    within 0.1 // TC_TypeK at  60C = 2.436mV
02326 // @test group TC_1 TemperatureOfTC_TypeK(2.851e-3) expect 70.0    within 0.1 // TC_TypeK at  70C = 2.851mV
02327 // @test group TC_1 TemperatureOfTC_TypeK(3.267e-3) expect 80.0    within 0.1 // TC_TypeK at  80C = 3.267mV
02328 // @test group TC_1 TemperatureOfTC_TypeK(3.682e-3) expect 90.0    within 0.1 // TC_TypeK at  90C = 3.682mV
02329 // @test group TC_1 TemperatureOfTC_TypeK(4.096e-3) expect 100.0   within 0.1 // TC_TypeK at  100C = 4.096mV
02330 // @test group TC_2 TemperatureOfTC_TypeK(4.509e-3) expect 110.0    within 0.1 // TC_TypeK at  110C = 4.509mV
02331 // @test group TC_2 TemperatureOfTC_TypeK(4.920e-3) expect 120.0    within 0.1 // TC_TypeK at  120C = 4.920mV
02332 // @test group TC_2 TemperatureOfTC_TypeK(5.328e-3) expect 130.0    within 0.1 // TC_TypeK at  130C = 5.328mV
02333 // @test group TC_2 TemperatureOfTC_TypeK(5.735e-3) expect 140.0    within 0.1 // TC_TypeK at  140C = 5.735mV
02334 // @test group TC_2 TemperatureOfTC_TypeK(6.138e-3) expect 150.0    within 0.1 // TC_TypeK at  150C = 6.138mV
02335 // @test group TC_2 TemperatureOfTC_TypeK(6.540e-3) expect 160.0    within 0.1 // TC_TypeK at  160C = 6.540mV
02336 // @test group TC_2 TemperatureOfTC_TypeK(6.941e-3) expect 170.0    within 0.1 // TC_TypeK at  170C = 6.941mV
02337 // @test group TC_2 TemperatureOfTC_TypeK(7.340e-3) expect 180.0    within 0.1 // TC_TypeK at  180C = 7.340mV
02338 // @test group TC_1 TemperatureOfTC_TypeK(7.739e-3) expect 190.0   within 0.1 // TC_TypeK at  190C = 7.739mV
02339 // @test group TC_1 TemperatureOfTC_TypeK(8.138e-3) expect 200.0   within 0.1 // TC_TypeK at  200C = 8.138mV
02340 // @test group TC_1 TemperatureOfTC_TypeK(8.539e-3) expect 210.0   within 0.1 // TC_TypeK at  210C = 8.539mV
02341 // @test group TC_1 TemperatureOfTC_TypeK(8.940e-3) expect 220.0   within 0.1 // TC_TypeK at  220C = 8.940mV
02342 // @test group TC_2 TemperatureOfTC_TypeK(9.343e-3) expect 230.0    within 0.1 // TC_TypeK at  230C = 9.343mV
02343 // @test group TC_2 TemperatureOfTC_TypeK(9.747e-3) expect 240.0    within 0.1 // TC_TypeK at  240C = 9.747mV
02344 // @test group TC_2 TemperatureOfTC_TypeK(10.153e-3) expect 250.0   within 0.1 // TC_TypeK at  250C = 10.153mV
02345 // @test group TC_2 TemperatureOfTC_TypeK(10.561e-3) expect 260.0   within 0.1 // TC_TypeK at  260C = 10.561mV
02346 // @test group TC_2 TemperatureOfTC_TypeK(10.971e-3) expect 270.0   within 0.1 // TC_TypeK at  270C = 10.971mV
02347 // @test group TC_2 TemperatureOfTC_TypeK(11.382e-3) expect 280.0   within 0.1 // TC_TypeK at  280C = 11.382mV
02348 // @test group TC_2 TemperatureOfTC_TypeK(11.795e-3) expect 290.0   within 0.1 // TC_TypeK at  290C = 11.795mV
02349 // @test group TC_1 TemperatureOfTC_TypeK(12.209e-3) expect 300.0  within 0.1 // TC_TypeK at  300C = 12.209mV
02350 // @test group TC_2 TemperatureOfTC_TypeK(14.293e-3) expect 350.0   within 0.1 // TC_TypeK at  350C = 14.293mV
02351 // @test group TC_1 TemperatureOfTC_TypeK(16.397e-3) expect 400.0  within 0.1 // TC_TypeK at  400C = 16.397mV
02352 // @test group TC_1 TemperatureOfTC_TypeK(18.516e-3) expect 450.0  within 0.1 // TC_TypeK at  450C = 18.516mV
02353 // @test group TC_1 TemperatureOfTC_TypeK(20.218e-3) expect 490.0  // TC_TypeK at  490C = 20.218mV
02354 // @test group TC_1 tinyTester.blink_time_msec = 75 // default 75 resume hardware self test
02355 //
02356 double MAX11410::TemperatureOfTC_TypeK(double tc_v)
02357 {
02358     
02359     //----------------------------------------
02360     // Temperature from TC_TypeK voltage maths
02361     // define standard TC_TypeK coefficients
02362     // ITS-90 Thermocouple Inverse Polynomial for a Type K thermocouple
02363     // calculate deltaT from tc_v
02364     //
02365     // Voltage range -5891uV < tc_v < 0uV, 
02366     // Temperature Range -200 deg C to 0 deg C
02367     static double coefficients_TCtypeK_V_lt_0[] = {
02368          0.00000,
02369          2.5173462e-2,
02370         -1.1662878e-6,
02371         -1.0833638e-9,
02372         -8.9773540e-13,
02373         -3.7342377e-16,
02374         -8.6632643e-20,
02375         -1.0450598e-23,
02376         -5.1920577e-28,
02377     };
02378     //
02379     // Voltage range 0uV < tc_v < 20.644uV, 
02380     // Temperature Range 0 deg C to 500 deg C
02381     static double coefficients_TCtypeK_0_lt_V_lt_20u644V[] = {
02382          0.00000,
02383          2.508355e-2,
02384          7.860106e-8,
02385         -2.503131e-10,
02386          8.315270e-14,
02387         -1.228034e-17,
02388          9.804036e-22,
02389         -4.413030e-26,
02390          1.057734e-30,
02391         -1.052755e-35,
02392     };
02393     //
02394     // Voltage range 20.6440uV < tc_v < 54.886uV, 
02395     // Temperature Range 500 deg C to 1372 deg C
02396     static double coefficients_TCtypeK_20u644V_lt_V_lt_54u886V[] = {
02397         -1.318058e2,
02398          4.830222e-2,
02399         -1.646031e-6,
02400          5.464731e-11,
02401         -9.650715e-16,
02402          8.802193e-21,
02403         -3.110810e-26,
02404     };
02405     //
02406     double deltaT = 0;
02407     double thermocouple_voltage_uV = tc_v * 1e6;
02408     if (thermocouple_voltage_uV < 0)
02409     {
02410         // Voltage range -5891uV < DMMavg < 0uV, Temperature Range -200 deg C to 0 deg C
02411         deltaT = temperatureDegC_polynomial(thermocouple_voltage_uV, 9, coefficients_TCtypeK_V_lt_0);
02412     }
02413     else if (thermocouple_voltage_uV > 20644)
02414     {
02415         // Voltage range 206440uV < DMMavg < 54886uV, Temperature Range 500 deg C to 1372 deg C
02416         deltaT = temperatureDegC_polynomial(thermocouple_voltage_uV, 7, coefficients_TCtypeK_20u644V_lt_V_lt_54u886V);
02417     }
02418     else
02419     {
02420         // Voltage range 0uV < DMMavg < 20.644uV, Temperature Range 0 deg C to 500 deg C
02421         deltaT = temperatureDegC_polynomial(thermocouple_voltage_uV, 10, coefficients_TCtypeK_0_lt_V_lt_20u644V);
02422     }
02423     return deltaT; //  + rtd_degc; // cold junction
02424 }
02425 
02426 //----------------------------------------
02427 // Calculate temperature in degrees C from input voltage,
02428 // using a given set of polynomial coefficients.
02429 // For example:
02430 //
02431 // t = coefficients[0] + coefficients[1] * DMMavg + coefficients[2] * DmMMavg**2
02432 //
02433 // @param[in] thermocouple_voltage_uV = Thermocouple voltage in microvolts
02434 //
02435 // @return ideal temperature in degrees C, calculated from polynomial coefficients
02436 //
02437 double MAX11410::temperatureDegC_polynomial(double thermocouple_voltage_uV, int num_coefficients, double coefficients[])
02438 {
02439     
02440     //----------------------------------------
02441     // Temperature from polynomial coefficients maths
02442     double temperatureDegC = 0;
02443     int index;
02444     for (index = num_coefficients-1; index >= 0; index--)
02445     {
02446         temperatureDegC = (temperatureDegC * thermocouple_voltage_uV) + coefficients[index];
02447     }
02448     return temperatureDegC;
02449 }
02450 
02451 
02452 // End of file