Maxim Integrated MAX11131 SPI 12-bit 16-channel ADC with SampleSet
Dependents: MAX11131BOB_Tester MAX11131BOB_12bit_16ch_SampleSet_SPI_ADC MAX11131BOB_Serial_Tester
MAX11131.cpp
- Committer:
- whismanoid
- Date:
- 2021-06-06
- Revision:
- 11:eaaf13fe381e
- Parent:
- 10:92aedaa14cce
File content as of revision 11:eaaf13fe381e:
// /******************************************************************************* // * Copyright (C) 2021 Maxim Integrated Products, Inc., All Rights Reserved. // * // * Permission is hereby granted, free of charge, to any person obtaining a // * copy of this software and associated documentation files (the "Software"), // * to deal in the Software without restriction, including without limitation // * the rights to use, copy, modify, merge, publish, distribute, sublicense, // * and/or sell copies of the Software, and to permit persons to whom the // * Software is furnished to do so, subject to the following conditions: // * // * The above copyright notice and this permission notice shall be included // * in all copies or substantial portions of the Software. // * // * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES // * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // * OTHER DEALINGS IN THE SOFTWARE. // * // * Except as contained in this notice, the name of Maxim Integrated // * Products, Inc. shall not be used except as stated in the Maxim Integrated // * Products, Inc. Branding Policy. // * // * The mere transfer of this software does not imply any licenses // * of trade secrets, proprietary technology, copyrights, patents, // * trademarks, maskwork rights, or any other form of intellectual // * property whatsoever. Maxim Integrated Products, Inc. retains all // * ownership rights. // ******************************************************************************* // */ // ********************************************************************* // @file MAX11131.cpp // ********************************************************************* // Device Driver file // DO NOT EDIT; except areas designated "CUSTOMIZE". Automatically generated file. // generated by XMLSystemOfDevicesToMBED.py // System Name = ExampleSystem // System Description = Device driver example #include "MAX11131.h" // Device Name = MAX11131 // Device Description = 3Msps, Low-Power, Serial SPI 12-Bit, 16-Channel, Differential/Single-Ended Input, SAR ADC // Device DeviceBriefDescription = 12-bit 3Msps 16-ch ADC // Device Manufacturer = Maxim Integrated // Device PartNumber = MAX11131ATI+ // Device RegValue_Width = DataWidth16bit_HL // // ADC MaxOutputDataRate = 3Msps // ADC NumChannels = 16 // ADC ResolutionBits = 12 // // SPI CS = ActiveLow // SPI FrameStart = CS // SPI CPOL = 1 // SPI CPHA = 1 // SPI MOSI and MISO Data are both stable on Rising edge of SCLK // SPI SCLK Idle High // SPI SCLKMaxMHz = 48 // SPI SCLKMinMHz = 0.48 // // InputPin Name = CNVST // InputPin Description = Active-Low Conversion Start Input/Analog Input 14 // InputPin Function = Trigger // // InputPin Name = REF+ // InputPin Description = External Positive Reference Input. Apply a reference voltage at REF+. Bypass to GND with a 0.47uF capacitor. // InputPin Function = Reference // // InputPin Name = REF-/AIN15 // InputPin Description = External Differential Reference Negative Input/Analog Input 15 // InputPin Function = Reference // // OutputPin Name = EOC // OutputPin Description = End of Conversion Output. Data is valid after EOC pulls low (Internal clock mode only). // OutputPin Function = Event // // SupplyPin Name = VDD // SupplyPin Description = Power-Supply Input. Bypass to GND with a 10uF in parallel with a 0.1uF capacitors. // SupplyPin VinMax = 3.6 // SupplyPin VinMin = 2.35 // SupplyPin Function = Analog // // SupplyPin Name = OVDD // SupplyPin Description = Interface Digital Power-Supply Input. Bypass to GND with a 10uF in parallel with a 0.1uF capacitors. // SupplyPin VinMax = 3.6 // SupplyPin VinMin = 1.5 // SupplyPin Function = Digital // MAX11131::MAX11131(SPI &spi, DigitalOut &cs_pin, // SPI interface DigitalOut &CNVST_pin, // Digital Trigger Input to MAX11131 device // AnalogOut &REF_plus_pin, // Reference Input to MAX11131 device // AnalogOut &REF_minus_slash_AIN15_pin, // Reference Input to MAX11131 device DigitalIn &EOC_pin, // Digital Event Output from MAX11131 device MAX11131_ic_t ic_variant) : m_spi(spi), m_cs_pin(cs_pin), // SPI interface m_CNVST_pin(CNVST_pin), // Digital Trigger Input to MAX11131 device // m_REF_plus_pin(REF_plus_pin), // Reference Input to MAX11131 device // m_REF_minus_slash_AIN15_pin(REF_minus_slash_AIN15_pin), // Reference Input to MAX11131 device m_EOC_pin(EOC_pin), // Digital Event Output from MAX11131 device m_ic_variant(ic_variant) { // SPI CS = ActiveLow // SPI FrameStart = CS m_SPI_cs_state = 1; if (m_cs_pin.is_connected()) { // avoid mbed runtime error if pin is NC not connected m_cs_pin = m_SPI_cs_state; } // SPI CPOL = 1 // SPI CPHA = 1 // SPI MOSI and MISO Data are both stable on Rising edge of SCLK // SPI SCLK Idle High m_SPI_dataMode = 3; //SPI_MODE3; // CPOL=1,CPHA=1: Rising Edge stable; SCLK idle High m_spi.format(8,m_SPI_dataMode); // int bits_must_be_8, int mode=0_3 CPOL=0,CPHA=0 // SPI SCLKMaxMHz = 48 // SPI SCLKMinMHz = 0.48 //#define SPI_SCLK_Hz 48000000 // 48MHz //#define SPI_SCLK_Hz 24000000 // 24MHz //#define SPI_SCLK_Hz 12000000 // 12MHz //#define SPI_SCLK_Hz 6000000 // 6MHz //#define SPI_SCLK_Hz 4000000 // 4MHz //#define SPI_SCLK_Hz 2000000 // 2MHz //#define SPI_SCLK_Hz 1000000 // 1MHz #if defined(TARGET_MAX32600) // MAX11131BOB_Serial_Tester on MAX32600MBED limit SCLK=6MHz m_SPI_SCLK_Hz = 6000000; // 6MHz; MAX11131 limit is 48MHz #else // all other platforms m_SPI_SCLK_Hz = 24000000; // platform limit 24MHz; MAX11131 limit is 48MHz #endif m_spi.frequency(m_SPI_SCLK_Hz); // // CNVST Trigger Input to MAX11131 device m_CNVST_pin = 1; // output logic high -- initial value in constructor // // REF_plus Reference Input to MAX11131 device // // REF_minus_slash_AIN15 Reference Input to MAX11131 device // // EOC Event Output from device } MAX11131::~MAX11131() { // do nothing } /// set SPI SCLK frequency void MAX11131::spi_frequency(int spi_sclk_Hz) { m_SPI_SCLK_Hz = spi_sclk_Hz; m_spi.frequency(m_SPI_SCLK_Hz); } // set SPI SCLK frequency for MAX11131 // void MAX11131::SPIfrequency(int spi_sclk_Hz) { m_SPI_SCLK_Hz = spi_sclk_Hz; m_spi.frequency(m_SPI_SCLK_Hz); } // get SPI SCLK frequency for MAX11131 // int MAX11131::SPIgetFrequency() { return m_SPI_SCLK_Hz; } // Assert SPI Chip Select // SPI chip-select for MAX11131 // inline void MAX11131::SPIoutputCS(int isLogicHigh) { m_SPI_cs_state = isLogicHigh; if (m_cs_pin.is_connected()) { // avoid mbed runtime error if pin is NC not connected m_cs_pin = m_SPI_cs_state; } } // SPI write 16 bits // SPI interface to MAX11131 shift 16 bits mosiData16 into MAX11131 DIN // ignoring MAX11131 DOUT // void MAX11131::SPIwrite16bits(int16_t mosiData16) { size_t byteCount = 2; static char mosiData[2]; static char misoData[2]; mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ noInterrupts(); // //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin // unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount); //~ m_spi.transfer(mosiData8_FF0000); //~ m_spi.transfer(mosiData16_00FF00); //~ m_spi.transfer(mosiData16_0000FF); // //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ interrupts(); // Optional Diagnostic function to print SPI transactions if (onSPIprint) { onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData); } // // VERIFY: SPIwrite24bits print diagnostic information //cmdLine.serial().printf(" MOSI->")); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData8_FF0000 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_00FF00 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_0000FF & 0xFF), HEX); // hex dump mosiData[0..byteCount-1] #if 0 // HAS_MICROUSBSERIAL cmdLine_microUSBserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_microUSBserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_microUSBserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_microUSBserial.serial().printf(" "); #endif #if 0 // HAS_DAPLINK_SERIAL cmdLine_DAPLINKserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_DAPLINKserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_DAPLINKserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_DAPLINKserial.serial().printf(" "); #endif // VERIFY: DIAGNOSTIC: print MAX5715 device register write // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF); // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF); // // int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF; // return misoData16; } // SPI write 17-24 bits // SPI interface to MAX11131 shift 16 bits mosiData16 into MAX11131 DIN // followed by one additional SCLK byte. // ignoring MAX11131 DOUT // void MAX11131::SPIwrite24bits(int16_t mosiData16_FFFF00, int8_t mosiData8_0000FF) { // TODO: implement SPIwrite24bits(int16_t mosiData16_FFFF00, int8_t mosiData8_0000FF) size_t byteCount = 3; static char mosiData[3]; static char misoData[3]; mosiData[0] = (char)((mosiData16_FFFF00 >> 8) & 0xFF); // MSByte mosiData[1] = (char)((mosiData16_FFFF00 >> 0) & 0xFF); // LSByte mosiData[2] = mosiData8_0000FF; // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ noInterrupts(); // //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin // unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount); //~ m_spi.transfer(mosiData8_FF0000); //~ m_spi.transfer(mosiData16_00FF00); //~ m_spi.transfer(mosiData16_0000FF); // //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ interrupts(); // Optional Diagnostic function to print SPI transactions if (onSPIprint) { onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData); } // // VERIFY: SPIwrite24bits print diagnostic information //cmdLine.serial().printf(" MOSI->")); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData8_FF0000 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_00FF00 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_0000FF & 0xFF), HEX); // hex dump mosiData[0..byteCount-1] #if 0 // HAS_MICROUSBSERIAL cmdLine_microUSBserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_microUSBserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_microUSBserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_microUSBserial.serial().printf(" "); #endif #if 0 // HAS_DAPLINK_SERIAL cmdLine_DAPLINKserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_DAPLINKserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_DAPLINKserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_DAPLINKserial.serial().printf(" "); #endif // VERIFY: DIAGNOSTIC: print MAX5715 device register write // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF); // // int misoData16 = (misoData16_FF00 << 8) | misoData16_00FF; // return misoData16; } // SPI read 16 bits while MOSI (MAX11131 DIN) is 0 // SPI interface to capture 16 bits miso data from MAX11131 DOUT // int16_t MAX11131::SPIread16bits() { int mosiData16 = 0; size_t byteCount = 2; static char mosiData[2]; static char misoData[2]; mosiData[0] = (char)((mosiData16 >> 8) & 0xFF); // MSByte mosiData[1] = (char)((mosiData16 >> 0) & 0xFF); // LSByte // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ noInterrupts(); // //~ digitalWrite(Scope_Trigger_Pin, LOW); // diagnostic Scope_Trigger_Pin // unsigned int numBytesTransferred = m_spi.write(mosiData, byteCount, misoData, byteCount); //~ m_spi.transfer(mosiData8_FF0000); //~ m_spi.transfer(mosiData16_00FF00); //~ m_spi.transfer(mosiData16_0000FF); // //~ digitalWrite(Scope_Trigger_Pin, HIGH); // diagnostic Scope_Trigger_Pin // // Arduino: begin critical section: noInterrupts() masks all interrupt sources; end critical section with interrupts() //~ interrupts(); // Optional Diagnostic function to print SPI transactions if (onSPIprint) { onSPIprint(byteCount, (uint8_t*)mosiData, (uint8_t*)misoData); } // // VERIFY: SPIwrite24bits print diagnostic information //cmdLine.serial().printf(" MOSI->")); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData8_FF0000 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_00FF00 & 0xFF), HEX); //cmdLine.serial().printf(" 0x")); //Serial.print( (mosiData16_0000FF & 0xFF), HEX); // hex dump mosiData[0..byteCount-1] #if 0 // HAS_MICROUSBSERIAL cmdLine_microUSBserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_microUSBserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_microUSBserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_microUSBserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_microUSBserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_microUSBserial.serial().printf(" "); #endif #if 0 // HAS_DAPLINK_SERIAL cmdLine_DAPLINKserial.serial().printf("\r\nSPI"); if (byteCount > 7) { cmdLine_DAPLINKserial.serial().printf(" byteCount:%d", byteCount); } cmdLine_DAPLINKserial.serial().printf(" MOSI->"); for (unsigned int byteIndex = 0; byteIndex < byteCount; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", mosiData[byteIndex]); } // hex dump misoData[0..byteCount-1] cmdLine_DAPLINKserial.serial().printf(" MISO<-"); for (unsigned int byteIndex = 0; byteIndex < numBytesTransferred; byteIndex++) { cmdLine_DAPLINKserial.serial().printf(" 0x%2.2X", misoData[byteIndex]); } cmdLine_DAPLINKserial.serial().printf(" "); #endif // VERIFY: DIAGNOSTIC: print MAX5715 device register write // TODO: MAX5715_print_register_verbose(mosiData8_FF0000, mosiData16_00FFFF); // TODO: print_verbose_SPI_diagnostic(mosiData16_FF00, mosiData16_00FF, misoData16_FF00, misoData16_00FF); // int misoData16 = (misoData[0] << 8) | misoData[1]; return misoData16; } // Assert MAX11131 CNVST convert start. // Required when using any of the InternalClock modes with SWCNV 0. // Trigger measurement by driving CNVST/AIN14 pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available) // void MAX11131::CNVSToutputPulseLow() { // m_CNVST_pin.output(); // only applicable to DigitalInOut m_CNVST_pin = 0; // output logic low wait(0.01); // pulse low delay time m_CNVST_pin = 1; // output logic high } // Wait for MAX11131 EOC pin low, indicating end of conversion. // Required when using any of the InternalClock modes. // void MAX11131::EOCinputWaitUntilLow() { // m_EOC_pin.input(); // only applicable to DigitalInOut while (m_EOC_pin != 0) { // spinlock waiting for logic low pin state } } // Return the status of the MAX11131 EOC pin. // int MAX11131::EOCinputValue() { // m_EOC_pin.input(); // only applicable to DigitalInOut return m_EOC_pin.read(); } //---------------------------------------- // Menu item '!' // Initialize device // // TODO1: #170 MAX11131 Self Test for Test Fixture Firmware // @future test group ____ // Verify function ____ (enabled by default) // // @future test group DACCodeOfVoltage // Verify function DACCodeOfVoltage (enabled by default) // @future test group DACCodeOfVoltage tinyTester.blink_time_msec = 20 // quickly speed through the software verification // @future test group DACCodeOfVoltage tinyTester.print("VRef = 2.500 MAX5171 14-bit LSB = 0.00015V") // @future test group DACCodeOfVoltage VRef = 2.500 // @future test group DACCodeOfVoltage tinyTester.err_threshold = 0.00015259720441921504 // 14-bit LSB (2.500/16383) // // // @future test group DACCodeOfVoltage DACCodeOfVoltage(2.499847412109375) expect 0x3FFF // // // // // @future test group CODE_LOAD // Verify function CODE_LOAD (enabled by default) // @future test group CODE_LOAD tinyTester.blink_time_msec = 75 // default 75 resume hardware self test // @future test group CODE_LOAD tinyTester.settle_time_msec = 250 // @future test Init() // @future test VRef expect 2.500 // Nominal Full-Scale Voltage Reference // // // tinyTester.err_threshold = 0.030; // 30mV // @future test group CODE_LOAD tinyTester.err_threshold = 0.030 // @future test group CODE_LOAD tinyTester.DigitalIn_Read_Expect_WarnOnly(UPO_pin, "UPO", 1, "UPO_pin is high after MAX5171 UPO_HIGH command") // @future test group CODE_LOAD tinyTester.AnalogIn0_Read_Expect_voltageV(1.2500) // // // // TODO1: #170 MAX11131 Self Test for Test Fixture Firmware // @future test group ____ // Verify function ____ (enabled by default) // @future test group ____ // Verify function ____ (enabled by default) // // MAX11131BOB self-test functions // //~ SelfTest_FAIL(cmdLine); // //~ cmdLine.serial().printf("test program not implemented yet"); // int16_t value_u12; // int channelId; // double voltageV = 0.5; // // // //cmdLine.serial().printf(" // 0.0: MAX11131.Init()"); // //Init(); // // // // Device Testing: ADC commands, verify with on-board ADC and SPI framing // // // @test group SPI48_3MSps // support 3MSps parts SCLK<=48MHz (enabled by default) // @test group SPI48_3MSps tinyTester.print("SPI 48MHz") // @test group SPI48_3MSps SPIfrequency(48000000); // support 3MSps parts SCLK<=48MHz // @test group SPI48_3MSps SPIgetFrequency() expect 48000000 // @test group SPI48_3MSps tinyTester.settle_time_msec = 250 // default 250 // @test group SPI48_3MSps tinyTester.Wait_Output_Settling() // @test group SPI48_3MSps SPIoutputCS(0) // @test group SPI48_3MSps SPIread16bits() // @test group SPI48_3MSps SPIoutputCS(1) // // // @test group SPI16MHz_1MSps // support 1MSps parts SCLK<=16MHz (enabled by default) // @test group SPI16MHz_1MSps tinyTester.print("SPI 16MHz") // @test group SPI16MHz_1MSps SPIfrequency(16000000); // support 1MSps parts SCLK<=16MHz // @test group SPI16MHz_1MSps SPIgetFrequency() expect 16000000 // @test group SPI16MHz_1MSps tinyTester.settle_time_msec = 250 // default 250 // @test group SPI16MHz_1MSps tinyTester.Wait_Output_Settling() // @test group SPI16MHz_1MSps SPIoutputCS(0) // @test group SPI16MHz_1MSps SPIread16bits() // @test group SPI16MHz_1MSps SPIoutputCS(1) // // // @test group SPI8MHz_500kSps // support 500kSps parts SCLK<=8MHz (enabled by default) // @test group SPI8MHz_500kSps tinyTester.print("SPI 8MHz") // @test group SPI8MHz_500kSps SPIfrequency(8000000); // support 500kSps parts SCLK<=8MHz // @test group SPI8MHz_500kSps SPIgetFrequency() expect 8000000 // @test group SPI8MHz_500kSps tinyTester.settle_time_msec = 250 // default 250 // @test group SPI8MHz_500kSps tinyTester.Wait_Output_Settling() // @test group SPI8MHz_500kSps SPIoutputCS(0) // @test group SPI8MHz_500kSps SPIread16bits() // @test group SPI8MHz_500kSps SPIoutputCS(1) // // // @test group SPI12MHz_1MSps // support 1MSps parts SCLK<=16MHz (enabled by default) // @test group SPI12MHz_1MSps tinyTester.print("SPI 12MHz") // @test group SPI12MHz_1MSps SPIfrequency(12000000); // support 1MSps parts SCLK<=16MHz // @test group SPI12MHz_1MSps SPIgetFrequency() expect 12000000 // @test group SPI12MHz_1MSps tinyTester.settle_time_msec = 250 // default 250 // @test group SPI12MHz_1MSps tinyTester.Wait_Output_Settling() // @test group SPI12MHz_1MSps SPIoutputCS(0) // @test group SPI12MHz_1MSps SPIread16bits() // @test group SPI12MHz_1MSps SPIoutputCS(1) // // // @test tinyTester.blink_time_msec = 75 // default 75 resume hardware self test // tinyTester.blink_time_msec = 75; // // MAX11131 SelfTest: MAX11131 SPI connections (Power Supply and GND, SCLK, MOSI, MISO, CS) // cmdLine.serial().printf(" // "); // cmdLine.serial().printf( // " // 1.0: Test Scan_0100_StandardExt -- verify SPI (VDD, GND, SCLK, MOSI, MISO, CS)"); // @test tinyTester.print("0.0: MAX11131.Init()") // cmdLine.serial().printf(" // MAX11131.Init()"); // Init(); // @test Init() // @test VRef expect 2.500 // Nominal Full-Scale Voltage Reference // // // @test group TEST10_SCAN_0100 // Test SCAN_0100_StandardExt -- verify VDD,GND,SCLK,MOSI,MISO,CS (enabled by default) // @test group TEST10_SCAN_0100 tinyTester.print("1.0: Test SCAN_0100_StandardExt -- verify VDD,GND,SCLK,MOSI,MISO,CS") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 tinyTester.print("0000_0000_0100_0010 ADC_MODE_CONTROL SCAN_0000") // @test group TEST10_SCAN_0100 tinyTester.print(" CHSEL=0 RESET=2 CHANID=1") // @test group TEST10_SCAN_0100 SPIwrite16bits(0x0040) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("1000_0000_0000_0000 ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIwrite16bits(0x8000) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("0010_0111_1010_0100 ADC_MODE_CONTROL SCAN_0100_StandardExt") // @test group TEST10_SCAN_0100 tinyTester.print(" CHSEL=15 RESET=1 CHANID=1") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIwrite16bits(0x27a4) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x0xxx (channel ID 0)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x0000 mask 0xF000 // expect 0x0xxx (channel ID 0) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x1xxx (channel ID 1)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x1000 mask 0xF000 // expect 0x1xxx (channel ID 1) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x2xxx (channel ID 2)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x2000 mask 0xF000 // expect 0x2xxx (channel ID 2) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x3xxx (channel ID 3)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x3000 mask 0xF000 // expect 0x3xxx (channel ID 3) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x4xxx (channel ID 4)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x4000 mask 0xF000 // expect 0x4xxx (channel ID 4) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x5xxx (channel ID 5)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x5000 mask 0xF000 // expect 0x5xxx (channel ID 5) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x6xxx (channel ID 6)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x6000 mask 0xF000 // expect 0x6xxx (channel ID 6) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x7xxx (channel ID 7)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x7000 mask 0xF000 // expect 0x7xxx (channel ID 7) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x8xxx (channel ID 8)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x8000 mask 0xF000 // expect 0x8xxx (channel ID 8) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0x9xxx (channel ID 9)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0x9000 mask 0xF000 // expect 0x9xxx (channel ID 9) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xaxxx (channel ID 10)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xA000 mask 0xF000 // expect 0xaxxx (channel ID 10) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xbxxx (channel ID 11)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xB000 mask 0xF000 // expect 0xbxxx (channel ID 11) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xcxxx (channel ID 12)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xC000 mask 0xF000 // expect 0xcxxx (channel ID 12) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xdxxx (channel ID 13)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xD000 mask 0xF000 // expect 0xdxxx (channel ID 13) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xexxx (channel ID 14)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xE000 mask 0xF000 // expect 0xexxx (channel ID 14) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // @test group TEST10_SCAN_0100 tinyTester.print("MISO --> expect 0xfxxx (channel ID 15)") // @test group TEST10_SCAN_0100 SPIoutputCS(0) // @test group TEST10_SCAN_0100 SPIread16bits() expect 0xF000 mask 0xF000 // expect 0xfxxx (channel ID 15) // @test group TEST10_SCAN_0100 SPIoutputCS(1) // // // @test group TEST4_SCAN_0100 // 4 ch=15 pm=0 id=1 -- ScanStandardExternalCloc (enabled by default) // @test group TEST4_SCAN_0100 tinyTester.print("4 ch=15 pm=0 id=1 -- ScanStandardExternalClock") // @test group TEST4_SCAN_0100 tinyTester.print("channelNumber_0_15 = 15") // @test group TEST4_SCAN_0100 channelNumber_0_15 = 15 // @test group TEST4_SCAN_0100 tinyTester.print("PowerManagement_0_2 = 0") // @test group TEST4_SCAN_0100 PowerManagement_0_2 = 0 // 0=Normal // @test group TEST4_SCAN_0100 tinyTester.print("chan_id_0_1 = 1") // @test group TEST4_SCAN_0100 chan_id_0_1 = 1 // misoData16 = CH[3:0] DATA[11:0] // @test group TEST4_SCAN_0100 tinyTester.print("ScanStandardExternalClock() expect 16") // @test group TEST4_SCAN_0100 ScanStandardExternalClock() expect 16 // Scan_0100_StandardExt // @test group TEST4_SCAN_0100 tinyTester.print("NumWords expect 16") // @test group TEST4_SCAN_0100 NumWords expect 16 // @test group TEST4_SCAN_0100 ReadAINcode() // @test group TEST4_SCAN_0100 tinyTester.print("Verify RAW_misoData16[0..15]>>12&0x000F == 0..15 channelId") // @test group TEST4_SCAN_0100 RAW_misoData16[0] expect 0x0000 mask 0xF000 // expect 0x0xxx (channel ID 0) // @test group TEST4_SCAN_0100 RAW_misoData16[1] expect 0x1000 mask 0xF000 // expect 0x1xxx (channel ID 1) // @test group TEST4_SCAN_0100 RAW_misoData16[2] expect 0x2000 mask 0xF000 // expect 0x2xxx (channel ID 2) // @test group TEST4_SCAN_0100 RAW_misoData16[3] expect 0x3000 mask 0xF000 // expect 0x3xxx (channel ID 3) // @test group TEST4_SCAN_0100 RAW_misoData16[4] expect 0x4000 mask 0xF000 // expect 0x4xxx (channel ID 4) // @test group TEST4_SCAN_0100 RAW_misoData16[5] expect 0x5000 mask 0xF000 // expect 0x5xxx (channel ID 5) // @test group TEST4_SCAN_0100 RAW_misoData16[6] expect 0x6000 mask 0xF000 // expect 0x6xxx (channel ID 6) // @test group TEST4_SCAN_0100 RAW_misoData16[7] expect 0x7000 mask 0xF000 // expect 0x7xxx (channel ID 7) // @test group TEST4_SCAN_0100 RAW_misoData16[8] expect 0x8000 mask 0xF000 // expect 0x8xxx (channel ID 8) // @test group TEST4_SCAN_0100 RAW_misoData16[9] expect 0x9000 mask 0xF000 // expect 0x9xxx (channel ID 9) // @test group TEST4_SCAN_0100 RAW_misoData16[10] expect 0xA000 mask 0xF000 // expect 0xaxxx (channel ID 10) // @test group TEST4_SCAN_0100 RAW_misoData16[11] expect 0xB000 mask 0xF000 // expect 0xbxxx (channel ID 11) // @test group TEST4_SCAN_0100 RAW_misoData16[12] expect 0xC000 mask 0xF000 // expect 0xcxxx (channel ID 12) // @test group TEST4_SCAN_0100 RAW_misoData16[13] expect 0xD000 mask 0xF000 // expect 0xdxxx (channel ID 13) // @test group TEST4_SCAN_0100 RAW_misoData16[14] expect 0xE000 mask 0xF000 // expect 0xexxx (channel ID 14) // @test group TEST4_SCAN_0100 RAW_misoData16[15] expect 0xF000 mask 0xF000 // expect 0xfxxx (channel ID 15) // // Send MOSI data Expect MISO data Description // // 1000_0000_0000_0000 xxxx_xxxx_xxxx_xxxx ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0 // // 0010_0111_1010_0100 xxxx_xxxx_xxxx_xxxx ADC_MODE_CONTROL Scan_0100_StandardExt CHSEL=15 RESET=1 CHANID=1 // // 0000_0000_0000_0000 0000_xxxx_xxxx_xxxx Channel ID tag = AIN0 expect high nybble 0 // // 0000_0000_0000_0000 0001_xxxx_xxxx_xxxx Channel ID tag = AIN1 expect high nybble 1 // // 0000_0000_0000_0000 0010_xxxx_xxxx_xxxx Channel ID tag = AIN2 expect high nybble 2 // // 0000_0000_0000_0000 0011_xxxx_xxxx_xxxx Channel ID tag = AIN3 expect high nybble 3 // // // cmdLine.serial().printf(" // MOSI <-- 1000_0000_0000_0000 ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0"); // @test tinyTester.print("1000_0000_0000_0000 ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0") // SPIoutputCS(0); // drive CS low // SPIwrite16bits(0x8000); // SPIoutputCS(1); // drive CS high // @test SPIoutputCS(0) // @test SPIwrite16bits(0x8000) // @test SPIoutputCS(1) // // // cmdLine.serial().printf( // " // MOSI <-- 0010_0111_1010_0100 ADC_MODE_CONTROL Scan_0100_StandardExt CHSEL=15 RESET=1 CHANID=1"); // @test tinyTester.print("0010_0111_1010_0100 ADC_MODE_CONTROL Scan_0100_StandardExt") // @test tinyTester.print(" CHSEL=15 RESET=1 CHANID=1") // SPIoutputCS(0); // drive CS low // SPIwrite16bits(0x27a4); // SPIoutputCS(1); // drive CS high // @test SPIoutputCS(0) // @test SPIwrite16bits(0x27a4) // @test SPIoutputCS(1) // // // @future test SPIoutputCS(0) // @future SPIread16bits() expect 0x0000 // @future SPIread16bits() expect 0x0000 mask 0xF000 // @future test SPIread16bits() expect 0x1000 mask 0xF000 // @future test SPIread16bits() expect 0x2000 mask 0xF000 // @future test SPIread16bits() expect 0x3000 mask 0xF000 // @future test SPIread16bits() expect 0x4000 mask 0xF000 // @future test SPIread16bits() expect 0x5000 mask 0xF000 // @future test SPIread16bits() expect 0x6000 mask 0xF000 // @future test SPIread16bits() expect 0x7000 mask 0xF000 // @future test SPIread16bits() expect 0x8000 mask 0xF000 // @future test SPIread16bits() expect 0x9000 mask 0xF000 // @future test SPIread16bits() expect 0xA000 mask 0xF000 // @future test SPIread16bits() expect 0xB000 mask 0xF000 // @future test SPIread16bits() expect 0xC000 mask 0xF000 // @future test SPIread16bits() expect 0xD000 mask 0xF000 // @future test SPIread16bits() expect 0xE000 mask 0xF000 // @future test SPIread16bits() expect 0xF000 mask 0xF000 // @future test SPIoutputCS(1) // // // for (int channelIndex = 0; channelIndex < 16; channelIndex++) { // //~ cmdLine.serial().printf(" // MISO --> expect 0000_xxxx_xxxx_xxxx"); // SPIoutputCS(0); // drive CS low // RAW_misoData16[channelIndex] = SPIread16bits(); // SPIoutputCS(1); // drive CS high // int expect_channelId = channelIndex; // int actual_channelId = (RAW_misoData16[channelIndex] >> 12) & 0x000F; // if (actual_channelId != expect_channelId) // { // tinyTester.FAIL(); // cmdLine.serial().printf("MISO --> 0x%4.4x", (RAW_misoData16[channelIndex] & 0xFFFF)); // cmdLine.serial().printf(" expect 0x%1.1xxxx (channel ID %d)", expect_channelId, expect_channelId); // cmdLine.serial().printf(" but got 0x%1.1xxxx", actual_channelId); // } // else // { // tinyTester.PASS(); // cmdLine.serial().printf("MISO --> 0x%4.4x", (RAW_misoData16[channelIndex] & 0xFFFF)); // cmdLine.serial().printf(" expect 0x%1.1xxxx (channel ID %d)", expect_channelId, expect_channelId); // } // } // @future test tinyTester.print("NumWords=16") // @future test NumWords=16 // @future test tinyTester.print("ReadAINcode()") // @future test ReadAINcode() // @future test tinyTester.print("TODO: expect RAW_misoData16[0..15]>>12&0x000F == 0..15 channelId") // @future test RAW_misoData16[0] expect 0x0000 mask 0xF000 // @future test RAW_misoData16[1] expect 0x1000 mask 0xF000 // @future test RAW_misoData16[2] expect 0x2000 mask 0xF000 // @future test RAW_misoData16[3] expect 0x3000 mask 0xF000 // // // // MAX11131 SelfTest: MAX11131 Supports Internal Clock Modes (CNVST, EOC) // cmdLine.serial().printf(" // "); // cmdLine.serial().printf( // " // 1.1: Test Scan_0011_StandardInt -- verify Internal Clock signals (CNVST, EOC)"); // @test group TEST11_SCAN_0011 // 1.1: Test Scan_0011_StandardInt -- verify Internal Clock CNVST,EOC (enabled by default) // @test group TEST11_SCAN_0011 tinyTester.print("1.1: Test Scan_0011_StandardInt -- verify Internal Clock CNVST,EOC") // cmdLine.serial().printf(" // MAX11131.Init()"); // @future test tinyTester.print("_______") // @test group TEST11_SCAN_0011 Init(); // @test group TEST11_SCAN_0011 SPIoutputCS(0); // drive CS low // RAW_misoData16[0] = SPIread16bits(); // @test group TEST11_SCAN_0011 group TEST11_SCAN_0011 SPIoutputCS(1); // drive CS high // // // // tinyTester.DigitalIn_Read_Expect_WarnOnly replaces SelfTest_MAX11131_EOC_expect // tinyTester.DigitalIn_Read_Expect_WarnOnly(EOCb_pin, "EOC", 1, "initial value before sending commands"); // // // // Send MOSI data Expect MISO data Description // // 1000_0000_0000_0000 xxxx_xxxx_xxxx_xxxx ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0 No Averaging // // 0001_1001_1010_0000 xxxx_xxxx_xxxx_xxxx ADC_MODE_CONTROL Scan_0011_StandardInt CHSEL=3 RESET=1 SWCNV=0 // // 0000_0000_0000_0000 0000_xxxx_xxxx_xxxx Channel ID tag = AIN0 expect high nybble 0 // // 0000_0000_0000_0000 0001_xxxx_xxxx_xxxx Channel ID tag = AIN1 expect high nybble 1 // // 0000_0000_0000_0000 0010_xxxx_xxxx_xxxx Channel ID tag = AIN2 expect high nybble 2 // // 0000_0000_0000_0000 0011_xxxx_xxxx_xxxx Channel ID tag = AIN3 expect high nybble 3 // // // cmdLine.serial().printf(" // MOSI <-- 1000_0000_0000_0000 ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0"); // @test group TEST11_SCAN_0011 tinyTester.print("1000_0000_0000_0000 ADC_CONFIGURATION REFSEL=0 SPM[1:0]=0 ECHO=0") // @test group TEST11_SCAN_0011 SPIoutputCS(0); // drive CS low // @test group TEST11_SCAN_0011 SPIwrite16bits(0x8000); // @test group TEST11_SCAN_0011 SPIoutputCS(1); // drive CS high // // // cmdLine.serial().printf( // " // MOSI <-- 0001_1001_1010_0000 ADC_MODE_CONTROL Scan_0011_StandardInt CHSEL=3 RESET=1 SWCNV=0"); // @test group TEST11_SCAN_0011 tinyTester.print("0001_1001_1010_0000 ADC_MODE_CONTROL Scan_0011_StandardInt") // @test group TEST11_SCAN_0011 tinyTester.print(" CHSEL=3 RESET=1 SWCNV=0") // @test group TEST11_SCAN_0011 SPIoutputCS(0); // drive CS low // @test group TEST11_SCAN_0011 SPIwrite16bits(0x19a0); // @test group TEST11_SCAN_0011 SPIoutputCS(1); // drive CS high // // // for (int channelIndex = 0; channelIndex < 4; channelIndex++) { // //~ cmdLine.serial().printf(" // MISO --> expect 0000_xxxx_xxxx_xxxx"); // //~ wait_ms(200); // delay // CNVSToutputPulseLow(); // //~ CNVSToutputValue(0); // //~ wait_ms(100); // delay // //~ CNVSToutputValue(1); // // EOCinputWaitUntilLow(); // infinite wait hazard, need to fail if timeout exceeded // // tinyTester.DigitalIn_Read_Expect_WarnOnly replaces SelfTest_MAX11131_EOC_expect // tinyTester.DigitalIn_Read_Expect_WarnOnly(EOCb_pin, "EOC", 0, "after CNVST pulse"); // SPIoutputCS(0); // drive CS low // RAW_misoData16[channelIndex] = SPIread16bits(); // SPIoutputCS(1); // drive CS high // // tinyTester.DigitalIn_Read_Expect_WarnOnly replaces SelfTest_MAX11131_EOC_expect // tinyTester.DigitalIn_Read_Expect_WarnOnly(EOCb_pin, "EOC", 1, "after SPI read"); // int expect_channelId = channelIndex; // int actual_channelId = (RAW_misoData16[channelIndex] >> 12) & 0x000F; // if (actual_channelId != expect_channelId) // { // tinyTester.FAIL(); // cmdLine.serial().printf("MISO --> 0x%4.4x", (RAW_misoData16[channelIndex] & 0xFFFF)); // cmdLine.serial().printf(" expect 0x%1.1xxxx (channel ID %d)", expect_channelId, expect_channelId); // cmdLine.serial().printf(" but got 0x%1.1xxxx", actual_channelId); // } // else // { // tinyTester.PASS(); // cmdLine.serial().printf("MISO --> 0x%4.4x", (RAW_misoData16[channelIndex] & 0xFFFF)); // cmdLine.serial().printf(" expect 0x%1.1xxxx (channel ID %d)", expect_channelId, expect_channelId); // } // } // // // // MAX11131 SelfTest: Test Fixture: MAX541ACPA+ to MAX32625MBED.AIN0/AIN4 // // Test Fixture: MAX541 connected to spi2 // // SPI spi2_max541(SPI2_MOSI, SPI2_MISO, SPI2_SCK); // mosi, miso, sclk spi2 TARGET_MAX32635MBED: P2_5 P2_6 P2_4 Arduino 2x3-pin header; microSD // // DigitalOut spi2_max541_cs(SPI2_SS); // TARGET_MAX32635MBED: P2_7 Arduino 2x3-pin header // // Test Fixture: MAX541 spi2 init // cmdLine.serial().printf(" // "); // cmdLine.serial().printf(" // 2.0: Test Fixture: MAX541 connected to spi2 (P2.4 P2.5 P2.7)?"); // @future test tinyTester.print("_______") // bool SelfTest_has_max541 = false; // // Check actual MAX541 reference voltage // cmdLine.serial().printf(" // Test Fixture: MAX541 midscale voltage measure with MAX32625MBED AIN0/4"); // max541.Set_Code(0x8000); // we don't know the fullscale voltage yet, so set code to midscale // tinyTester.Wait_Output_Settling(); // wait for MAX541 to settle // // // double max541_midscale_V = analogInPin_fullScaleVoltage[4] * analogIn4.read(); // TARGET_MAX32630 J1.5 AIN_4 = AIN0 / 5.0 fullscale is 6.0V // const int average_count = 100; // const double average_K = 0.25; // for (int count = 0; count < average_count; count++) { // double measurement_V = analogInPin_fullScaleVoltage[4] * analogIn4.read(); // TARGET_MAX32630 J1.5 AIN_4 = AIN0 / 5.0 fullscale is 6.0V // max541_midscale_V = ((1 - average_K) * max541_midscale_V) + (average_K * measurement_V); // } // if (max541_midscale_V > 1.0f) { // max541.VRef = 2.0 * max541_midscale_V; // cmdLine.serial().printf(" // Test Fixture: MAX541 midscale = %1.3fV, so fullscale = %1.3fV", // max541_midscale_V, max541.VRef); // // Detect whether MAX541 is really connected to MAX32625MBED.AIN0/AIN4 // voltageV = 1.0f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 0.0f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 2.7f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 1.65f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 2.0f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 0.25f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 0.5f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541) { // voltageV = 1.0f; // SelfTest_has_max541 = SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // if (SelfTest_has_max541 == false) { // // don't fail just because we're missing the test fixture... // cmdLine.serial().printf(" // Test Fixture: MAX541 not present"); // //~ g_SelfTest_nFail--; // } // // // // TODO1: MAX11131 SelfTest: if Test Fixture: drive MAX541, compare MAX32625MBED.AIN0/AIN4 and MAX11131 AIN0 // // indirectly verify the reference voltage by reading a known input voltage // if (SelfTest_has_max541) { // cmdLine.serial().printf(" // "); // cmdLine.serial().printf(" // 2.1: TODO1: Check MAX11131 reference voltage using Scan_0001_Manual"); // @future test tinyTester.print("_______") // voltageV = 1.0f; // SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // cmdLine.serial().printf(" // MAX11131.Init()"); // Init(); // // 1 ScanManual ch=0 pm=0 id=1 // channelNumber_0_15 = 0; // PowerManagement_0_2 = 0; // chan_id_0_1 = 1; // cmdLine.serial().printf(" // MAX11131.channelNumber_0_15=%d", channelNumber_0_15); // cmdLine.serial().printf(" // MAX11131.PowerManagement_0_2=%d", PowerManagement_0_2); // cmdLine.serial().printf(" // MAX11131.chan_id_0_1=%d", chan_id_0_1); // NumWords = ScanManual(); // cmdLine.serial().printf(" // MAX11131.ScanManual -- NumWords = %d", // NumWords); // NumWords = ScanManual(); // ReadAINcode(); // cmdLine.serial().printf(" // MAX11131.ReadAINcode"); // AINcode_print_value_externalClock(cmdLine, NumWords); // // // // 2.1: TODO1: Check MAX11131 reference voltage -- why we read 0xffff 2.4999V here? // // // cmdLine.serial().printf(" // MAX11131.ScanManual -- NumWords = %d", // NumWords); // // Read raw ADC codes from device into AINcode[] and RAW_misoData16[] // // @pre one of the MAX11311_Scan functions was called, setting NumWords // ReadAINcode(); // cmdLine.serial().printf(" // MAX11131.ReadAINcode"); // AINcode_print_value_externalClock(cmdLine, NumWords); // // // // 2.1: TODO1: Check MAX11131 reference voltage -- why we read 0xffff 2.4999V here? // // // // compare with mbed/Arduino AIN0-AIN3 // // MAX32625MBED.AIN4 = MAX11131.AIN0 // channelId = 0; // value_u12 = AINcode[channelId]; // voltageV = VoltageOfCode(value_u12, channelId); // // // // tinyTester.Wait_Output_Settling replaces wait_ms // tinyTester.Wait_Output_Settling(); // // tinyTester.AnalogIn0_Read_Expect_voltageV replaces SelfTest_AnalogInput_Expect_ch_V // tinyTester.err_threshold = 0.100; // tinyTester.AnalogIn0_Read_Expect_voltageV(voltageV); // // // } // // // if (SelfTest_has_max541) { // voltageV = 1.0f; // SelfTest_MAX541_Voltage(cmdLine, max541, voltageV); // } // cmdLine.serial().printf(" // "); // cmdLine.serial().printf(" // 3.1: Test Scan_0001_Manual"); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.Init()"); // Init(); // // 1 ScanManual ch=0 pm=0 id=1 // channelNumber_0_15 = 0; // PowerManagement_0_2 = 0; // chan_id_0_1 = 1; // cmdLine.serial().printf(" // MAX11131.channelNumber_0_15=%d", channelNumber_0_15); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.PowerManagement_0_2=%d", PowerManagement_0_2); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.chan_id_0_1=%d", chan_id_0_1); // @future test tinyTester.print("_______") // NumWords = ScanManual(); // cmdLine.serial().printf(" // MAX11131.ScanManual -- NumWords = %d", // NumWords); // @future test tinyTester.print("_______") // // Read raw ADC codes from device into AINcode[] and RAW_misoData16[] // // @pre one of the MAX11311_Scan functions was called, setting NumWords // ReadAINcode(); // cmdLine.serial().printf(" // MAX11131.ReadAINcode"); // @future test tinyTester.print("_______") // AINcode_print_value_externalClock(cmdLine, NumWords); // // compare with mbed/Arduino AIN0-AIN3 // // MAX32625MBED.AIN4 = MAX11131.AIN0 // channelId = 0; // value_u12 = AINcode[channelId]; // voltageV = VoltageOfCode(value_u12, channelId); // // // // tinyTester.Wait_Output_Settling replaces wait_ms // tinyTester.Wait_Output_Settling(); // // tinyTester.AnalogIn0_Read_Expect_voltageV replaces SelfTest_AnalogInput_Expect_ch_V // tinyTester.err_threshold = 0.100; // tinyTester.AnalogIn0_Read_Expect_voltageV(voltageV); // // // // // cmdLine.serial().printf(" // "); // cmdLine.serial().printf(" // 3.4: Test Scan_0100_StandardExternalClock"); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.Init()"); // Init(); // // MAX11131 > 4 // // ScanStandardExternalClock ch=9 pm=0 id=1 // // ScanRead_nWords_chanID nWords=10 // // ch=0 xu=2964 = 0x0b94 = 1.8091V // // ch=1 xu=2227 = 0x08b3 = 1.3593V // // ch=2 xu=1570 = 0x0622 = 0.9583V // // ch=3 xu=865 = 0x0361 = 0.5280V // // ch=4 xu=630 = 0x0276 = 0.3845V // // ch=5 xu=594 = 0x0252 = 0.3625V // // ch=6 xu=461 = 0x01cd = 0.2814V // // ch=7 xu=364 = 0x016c = 0.2222V // // ch=8 xu=480 = 0x01e0 = 0.2930V // // ch=9 xu=616 = 0x0268 = 0.3760V // channelNumber_0_15 = 9; // PowerManagement_0_2 = 0; // chan_id_0_1 = 1; // cmdLine.serial().printf(" // MAX11131.channelNumber_0_15=%d", channelNumber_0_15); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.PowerManagement_0_2=%d", PowerManagement_0_2); // @future test tinyTester.print("_______") // cmdLine.serial().printf(" // MAX11131.chan_id_0_1=%d", chan_id_0_1); // @future test tinyTester.print("_______") // NumWords = ScanStandardExternalClock(); // cmdLine.serial().printf(" // MAX11131.ScanStandardExternalClock -- NumWords = %d", // NumWords); // @future test tinyTester.print("_______") // // Read raw ADC codes from device into AINcode[] and RAW_misoData16[] // // @pre one of the MAX11311_Scan functions was called, setting NumWords // ReadAINcode(); // cmdLine.serial().printf(" // MAX11131.ReadAINcode"); // @future test tinyTester.print("_______") // // @post RAW_misoData16[index] contains the raw SPI Master-In,Slave-Out data // // @post AINcode[NUM_CHANNELS] contains the latest readings in LSBs // // expect NumWords == channelNumber_0_15 + 1; // // expect RAW_misoData16[index] msnybble 0,1,2,3,... // AINcode_print_value_externalClock(cmdLine, NumWords); // // compare with mbed/Arduino AIN0-AIN3 // // MAX32625MBED.AIN4 = MAX11131.AIN0 // channelId = 0; // value_u12 = AINcode[channelId]; // voltageV = VoltageOfCode(value_u12, channelId); // // tinyTester.Wait_Output_Settling replaces wait_ms // tinyTester.Wait_Output_Settling(); // // tinyTester.AnalogIn0_Read_Expect_voltageV replaces SelfTest_AnalogInput_Expect_ch_V // tinyTester.err_threshold = 0.100; // tinyTester.AnalogIn0_Read_Expect_voltageV(voltageV); // // compare MAX32625MBED.AIN5 = MAX11131.AIN1 // //channelId = 1; // //value_u12 = AINcode[channelId]; // //voltageV = VoltageOfCode(value_u12, channelId); // //SelfTest_AnalogInput_Expect_ch_V(cmdLine, 5, voltageV, 0.100); // // // void MAX11131::Init(void) { //---------------------------------------- // Nominal Full-Scale Voltage Reference VRef = 2.500; //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // define write-only register ADC_CONFIGURATION ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0 const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL const int AVGON_LSB = 9; const int AVGON_BITS = 0x01; // ADC_CONFIGURATION.AVGON const int NAVG_LSB = 7; const int NAVG_BITS = 0x03; // ADC_CONFIGURATION.NAVG[1:0] const int NSCAN_LSB = 5; const int NSCAN_BITS = 0x03; // ADC_CONFIGURATION.NSCAN[1:0] const int SPM_LSB = 3; const int SPM_BITS = 0x03; // ADC_CONFIGURATION.SPM[1:0] const int ECHO_LSB = 2; const int ECHO_BITS = 0x01; // ADC_CONFIGURATION.ECHO //---------------------------------------- // define write-only registers UNIPOLAR,BIPOLAR,RANGE UNIPOLAR = 0x8800; //!< mosiData16 0x8800..0x8FFF format: 1 0 0 0 1 UCH0/1 UCH2/3 UCH4/5 UCH6/7 UCH8/9 UCH10/11 UCH12/13 UCH14/15 PDIFF_COM x x BIPOLAR = 0x9000; //!< mosiData16 0x9000..0x97FF format: 1 0 0 1 0 BCH0/1 BCH2/3 BCH4/5 BCH6/7 BCH8/9 BCH10/11 BCH12/13 BCH14/15 x x x RANGE = 0x9800; //!< mosiData16 0x9800..0x9FFF format: 1 0 0 1 1 RANGE0/1 RANGE2/3 RANGE4/5 RANGE6/7 RANGE8/9 RANGE10/11 RANGE12/13 RANGE14/15 x x x const int AIN_0_1_LSB = 10; // UNIPOLAR.UCH0/1 BIPOLAR.BCH0/1 RANGE.RANGE0/1 const int AIN_2_3_LSB = 9; // UNIPOLAR.UCH2/3 BIPOLAR.BCH2/3 RANGE.RANGE2/3 const int AIN_4_5_LSB = 8; // UNIPOLAR.UCH4/5 BIPOLAR.BCH4/5 RANGE.RANGE4/5 const int AIN_6_7_LSB = 7; // UNIPOLAR.UCH6/7 BIPOLAR.BCH6/7 RANGE.RANGE6/7 const int AIN_8_9_LSB = 6; // UNIPOLAR.UCH8/9 BIPOLAR.BCH8/9 RANGE.RANGE8/9 const int AIN_10_11_LSB = 5; // UNIPOLAR.UCH10/11 BIPOLAR.BCH10/11 RANGE.RANGE10/11 const int AIN_12_13_LSB = 4; // UNIPOLAR.UCH12/13 BIPOLAR.BCH12/13 RANGE.RANGE12/13 const int AIN_14_15_LSB = 3; // UNIPOLAR.UCH14/15 BIPOLAR.BCH14/15 RANGE.RANGE14/15 const int PDIFF_COMM_LSB = 2; const int PDIFF_COMM_BITS = 0x01; // UNIPOLAR.PDIFF_COM // Summary of Table 8: // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) // UCH0/1=1, BCH0/1=1, RANGE0/1=0: reserved do not use // UCH0/1=0, BCH0/1=0, RANGE0/1=1: reserved do not use // UCH0/1=1, BCH0/1=0, RANGE0/1=1: reserved do not use // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) // UCH0/1=1, BCH0/1=1, RANGE0/1=1: reserved do not use // Both channels of a differential pair must be within Input Voltage Range (dynamic signal range) 0..VREF. //---------------------------------------- // define write-only registers CSCAN0,CSCAN1 CSCAN0 = 0xA000; //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15 const int CHSCAN14_LSB = 9; // CSCAN0.CHSCAN14 const int CHSCAN13_LSB = 8; // CSCAN0.CHSCAN13 const int CHSCAN12_LSB = 7; // CSCAN0.CHSCAN12 const int CHSCAN11_LSB = 6; // CSCAN0.CHSCAN11 const int CHSCAN10_LSB = 5; // CSCAN0.CHSCAN10 const int CHSCAN9_LSB = 4; // CSCAN0.CHSCAN9 const int CHSCAN8_LSB = 3; // CSCAN0.CHSCAN8 CSCAN1 = 0xA800; //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7 const int CHSCAN6_LSB = 9; // CSCAN1.CHSCAN6 const int CHSCAN5_LSB = 8; // CSCAN1.CHSCAN5 const int CHSCAN4_LSB = 7; // CSCAN1.CHSCAN4 const int CHSCAN3_LSB = 6; // CSCAN1.CHSCAN3 const int CHSCAN2_LSB = 5; // CSCAN1.CHSCAN2 const int CHSCAN1_LSB = 4; // CSCAN1.CHSCAN1 const int CHSCAN0_LSB = 3; // CSCAN1.CHSCAN0 //---------------------------------------- // Initialize shadow of write-only register SAMPLESET. // Do not write to SAMPLESET at this time. // A write to SAMPLESET must be followed by specified number of pattern entry words. // See ScanSampleSetExternalClock function for details. SAMPLESET = 0xB000; //!< mosiData16 0xB000..0xB7FF format: 1 0 1 1 0 SEQ_LENGTH[7:0] x x x const int SAMPLESET_LSB = 3; const int SAMPLESET_BITS = 0xFF; // SAMPLESET.SEQ_LENGTH[7:0] //---------------------------------------- // Reset all registers: ADC_MODE_CONTROL.RESET[1:0] = 2 ADC_MODE_CONTROL &= ~ (( RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved ADC_MODE_CONTROL |= ((2 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high #if REFSEL_0 //---------------------------------------- // Global setting for all channels: ADC_CONFIGURATION.REFSEL=0: external single-ended reference // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL: EXTERNAL SINGLE-ENDED // SELECT ADC CONFIGURATION register set REFSEL BIT TO 0 ADC_CONFIGURATION &= ~ (( REFSEL_BITS) << REFSEL_LSB); // ADC_CONFIGURATION.REFSEL=0: external single-ended reference. (For the 16-channel chips: channel AIN15 is available.) #endif // REFSEL_0 #if REFSEL_1 //---------------------------------------- // Global setting for all channels: ADC_CONFIGURATION.REFSEL=1: external differential reference (For the 16-channel chips: channel AIN15 is unavailable, the pin is assigned to REF-.) // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL // SELECT REFERENCE SINGLE-ENDED OR DIFFERENTIAL: EXTERNAL DIFFERENTIAL // SELECT ADC CONFIGURATION register set REFSEL BIT TO 1 ADC_CONFIGURATION |= ((1 & REFSEL_BITS) << REFSEL_LSB); // ADC_CONFIGURATION.REFSEL=1: external differential reference. (For the 16-channel chips: channel AIN15 is unavailable, the pin is assigned to REF-.) #endif // REFSEL_1 #if PDIFF_COMM_0 //---------------------------------------- // Global setting for all channels: PDIFF_COMM UNIPOLAR &= ~ (( PDIFF_COMM_BITS) << PDIFF_COMM_LSB); // UNIPOLAR.PDIFF_COMM=0: all single-ended channels use GND as common #endif // PDIFF_COMM_0 #if PDIFF_COMM_1 //---------------------------------------- // Global setting for all channels: PDIFF_COMM // SELECT UNIPOLAR AND register set BIT PDIFF_COM TO 1 FOR PSEUDODIFFERENTIAL SELECTION UNIPOLAR |= ((1 & PDIFF_COMM_BITS) << PDIFF_COMM_LSB); // UNIPOLAR.PDIFF_COMM=1: all single-ended channels are pseudo-differential with REF- as common #endif // PDIFF_COMM_1 #if AIN_0_1_SingleEnded //---------------------------------------- // ADC Channels AIN0, AIN1 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN0 is a Single-Ended input using Unipolar transfer function. // AIN1 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN0 voltage must always be between 0 and VREF. // AIN1 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_0_1_LSB); BIPOLAR &= ~ (1 << AIN_0_1_LSB); RANGE &= ~ (1 << AIN_0_1_LSB); // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_0_1_SingleEnded #if AIN_0_1_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN0, AIN1 = Differential Unipolar (AIN0 > AIN1) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN0, AIN1 are a Differential pair using Unipolar transfer function. // AIN0 voltage must always be between 0 and VREF. // AIN1 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_0_1_LSB); BIPOLAR &= ~ (1 << AIN_0_1_LSB); RANGE &= ~ (1 << AIN_0_1_LSB); // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_0_1_DifferentialUnipolar #if AIN_0_1_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN0, AIN1 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN0, AIN1 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN0 voltage must always be between 0 and VREF. // AIN1 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_0_1_LSB); BIPOLAR |= (1 << AIN_0_1_LSB); RANGE &= ~ (1 << AIN_0_1_LSB); // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_0_1_DifferentialBipolarFSVref #if AIN_0_1_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN0, AIN1 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN0, AIN1 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN0 voltage must always be between 0 and VREF. // AIN1 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_0_1_LSB); BIPOLAR |= (1 << AIN_0_1_LSB); RANGE |= (1 << AIN_0_1_LSB); // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_0_1_DifferentialBipolarFS2Vref #if AIN_2_3_SingleEnded //---------------------------------------- // ADC Channels AIN2, AIN3 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN2 is a Single-Ended input using Unipolar transfer function. // AIN3 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN2 voltage must always be between 0 and VREF. // AIN3 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_2_3_LSB); BIPOLAR &= ~ (1 << AIN_2_3_LSB); RANGE &= ~ (1 << AIN_2_3_LSB); // UCH2/3=0, BCH2/3=0, RANGE2/3=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_2_3_SingleEnded #if AIN_2_3_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN2, AIN3 = Differential Unipolar (AIN2 > AIN3) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN2, AIN3 are a Differential pair using Unipolar transfer function. // AIN2 voltage must always be between 0 and VREF. // AIN3 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_2_3_LSB); BIPOLAR &= ~ (1 << AIN_2_3_LSB); RANGE &= ~ (1 << AIN_2_3_LSB); // UCH2/3=1, BCH2/3=0, RANGE2/3=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_2_3_DifferentialUnipolar #if AIN_2_3_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN2, AIN3 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN2, AIN3 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN2 voltage must always be between 0 and VREF. // AIN3 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_2_3_LSB); BIPOLAR |= (1 << AIN_2_3_LSB); RANGE &= ~ (1 << AIN_2_3_LSB); // UCH2/3=0, BCH2/3=1, RANGE2/3=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_2_3_DifferentialBipolarFSVref #if AIN_2_3_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN2, AIN3 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN2, AIN3 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN2 voltage must always be between 0 and VREF. // AIN3 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_2_3_LSB); BIPOLAR |= (1 << AIN_2_3_LSB); RANGE |= (1 << AIN_2_3_LSB); // UCH2/3=0, BCH2/3=1, RANGE2/3=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_2_3_DifferentialBipolarFS2Vref #if AIN_4_5_SingleEnded //---------------------------------------- // ADC Channels AIN4, AIN5 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN4 is a Single-Ended input using Unipolar transfer function. // AIN5 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN4 voltage must always be between 0 and VREF. // AIN5 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_4_5_LSB); BIPOLAR &= ~ (1 << AIN_4_5_LSB); RANGE &= ~ (1 << AIN_4_5_LSB); // UCH4/5=0, BCH4/5=0, RANGE4/5=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_4_5_SingleEnded #if AIN_4_5_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN4, AIN5 = Differential Unipolar (AIN4 > AIN5) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN4, AIN5 are a Differential pair using Unipolar transfer function. // AIN4 voltage must always be between 0 and VREF. // AIN5 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_4_5_LSB); BIPOLAR &= ~ (1 << AIN_4_5_LSB); RANGE &= ~ (1 << AIN_4_5_LSB); // UCH4/5=1, BCH4/5=0, RANGE4/5=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_4_5_DifferentialUnipolar #if AIN_4_5_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN4, AIN5 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN4, AIN5 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN4 voltage must always be between 0 and VREF. // AIN5 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_4_5_LSB); BIPOLAR |= (1 << AIN_4_5_LSB); RANGE &= ~ (1 << AIN_4_5_LSB); // UCH4/5=0, BCH4/5=1, RANGE4/5=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_4_5_DifferentialBipolarFSVref #if AIN_4_5_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN4, AIN5 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN4, AIN5 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN4 voltage must always be between 0 and VREF. // AIN5 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_4_5_LSB); BIPOLAR |= (1 << AIN_4_5_LSB); RANGE |= (1 << AIN_4_5_LSB); // UCH4/5=0, BCH4/5=1, RANGE4/5=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_4_5_DifferentialBipolarFS2Vref #if AIN_6_7_SingleEnded //---------------------------------------- // ADC Channels AIN6, AIN7 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN6 is a Single-Ended input using Unipolar transfer function. // AIN7 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN6 voltage must always be between 0 and VREF. // AIN7 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_6_7_LSB); BIPOLAR &= ~ (1 << AIN_6_7_LSB); RANGE &= ~ (1 << AIN_6_7_LSB); // UCH6/7=0, BCH6/7=0, RANGE6/7=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_6_7_SingleEnded #if AIN_6_7_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN6, AIN7 = Differential Unipolar (AIN6 > AIN7) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN6, AIN7 are a Differential pair using Unipolar transfer function. // AIN6 voltage must always be between 0 and VREF. // AIN7 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_6_7_LSB); BIPOLAR &= ~ (1 << AIN_6_7_LSB); RANGE &= ~ (1 << AIN_6_7_LSB); // UCH6/7=1, BCH6/7=0, RANGE6/7=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_6_7_DifferentialUnipolar #if AIN_6_7_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN6, AIN7 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN6, AIN7 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN6 voltage must always be between 0 and VREF. // AIN7 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_6_7_LSB); BIPOLAR |= (1 << AIN_6_7_LSB); RANGE &= ~ (1 << AIN_6_7_LSB); // UCH6/7=0, BCH6/7=1, RANGE6/7=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_6_7_DifferentialBipolarFSVref #if AIN_6_7_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN6, AIN7 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN6, AIN7 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN6 voltage must always be between 0 and VREF. // AIN7 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_6_7_LSB); BIPOLAR |= (1 << AIN_6_7_LSB); RANGE |= (1 << AIN_6_7_LSB); // UCH6/7=0, BCH6/7=1, RANGE6/7=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_6_7_DifferentialBipolarFS2Vref #if AIN_8_9_SingleEnded //---------------------------------------- // ADC Channels AIN8, AIN9 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN8 is a Single-Ended input using Unipolar transfer function. // AIN9 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN8 voltage must always be between 0 and VREF. // AIN9 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_8_9_LSB); BIPOLAR &= ~ (1 << AIN_8_9_LSB); RANGE &= ~ (1 << AIN_8_9_LSB); // UCH8/9=0, BCH8/9=0, RANGE8/9=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_8_9_SingleEnded #if AIN_8_9_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN8, AIN9 = Differential Unipolar (AIN8 > AIN9) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN8, AIN9 are a Differential pair using Unipolar transfer function. // AIN8 voltage must always be between 0 and VREF. // AIN9 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_8_9_LSB); BIPOLAR &= ~ (1 << AIN_8_9_LSB); RANGE &= ~ (1 << AIN_8_9_LSB); // UCH8/9=1, BCH8/9=0, RANGE8/9=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_8_9_DifferentialUnipolar #if AIN_8_9_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN8, AIN9 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN8, AIN9 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN8 voltage must always be between 0 and VREF. // AIN9 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_8_9_LSB); BIPOLAR |= (1 << AIN_8_9_LSB); RANGE &= ~ (1 << AIN_8_9_LSB); // UCH8/9=0, BCH8/9=1, RANGE8/9=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_8_9_DifferentialBipolarFSVref #if AIN_8_9_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN8, AIN9 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN8, AIN9 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN8 voltage must always be between 0 and VREF. // AIN9 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_8_9_LSB); BIPOLAR |= (1 << AIN_8_9_LSB); RANGE |= (1 << AIN_8_9_LSB); // UCH8/9=0, BCH8/9=1, RANGE8/9=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_8_9_DifferentialBipolarFS2Vref #if AIN_10_11_SingleEnded //---------------------------------------- // ADC Channels AIN10, AIN11 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN10 is a Single-Ended input using Unipolar transfer function. // AIN11 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN10 voltage must always be between 0 and VREF. // AIN11 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_10_11_LSB); BIPOLAR &= ~ (1 << AIN_10_11_LSB); RANGE &= ~ (1 << AIN_10_11_LSB); // UCH10/11=0, BCH10/11=0, RANGE10/11=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_10_11_SingleEnded #if AIN_10_11_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN10, AIN11 = Differential Unipolar (AIN10 > AIN11) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN10, AIN11 are a Differential pair using Unipolar transfer function. // AIN10 voltage must always be between 0 and VREF. // AIN11 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_10_11_LSB); BIPOLAR &= ~ (1 << AIN_10_11_LSB); RANGE &= ~ (1 << AIN_10_11_LSB); // UCH10/11=1, BCH10/11=0, RANGE10/11=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_10_11_DifferentialUnipolar #if AIN_10_11_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN10, AIN11 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN10, AIN11 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN10 voltage must always be between 0 and VREF. // AIN11 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_10_11_LSB); BIPOLAR |= (1 << AIN_10_11_LSB); RANGE &= ~ (1 << AIN_10_11_LSB); // UCH10/11=0, BCH10/11=1, RANGE10/11=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_10_11_DifferentialBipolarFSVref #if AIN_10_11_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN10, AIN11 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN10, AIN11 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN10 voltage must always be between 0 and VREF. // AIN11 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_10_11_LSB); BIPOLAR |= (1 << AIN_10_11_LSB); RANGE |= (1 << AIN_10_11_LSB); // UCH10/11=0, BCH10/11=1, RANGE10/11=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_10_11_DifferentialBipolarFS2Vref #if AIN_12_13_SingleEnded //---------------------------------------- // ADC Channels AIN12, AIN13 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN12 is a Single-Ended input using Unipolar transfer function. // AIN13 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN12 voltage must always be between 0 and VREF. // AIN13 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_12_13_LSB); BIPOLAR &= ~ (1 << AIN_12_13_LSB); RANGE &= ~ (1 << AIN_12_13_LSB); // UCH12/13=0, BCH12/13=0, RANGE12/13=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_12_13_SingleEnded #if AIN_12_13_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN12, AIN13 = Differential Unipolar (AIN12 > AIN13) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN12, AIN13 are a Differential pair using Unipolar transfer function. // AIN12 voltage must always be between 0 and VREF. // AIN13 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_12_13_LSB); BIPOLAR &= ~ (1 << AIN_12_13_LSB); RANGE &= ~ (1 << AIN_12_13_LSB); // UCH12/13=1, BCH12/13=0, RANGE12/13=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_12_13_DifferentialUnipolar #if AIN_12_13_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN12, AIN13 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN12, AIN13 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN12 voltage must always be between 0 and VREF. // AIN13 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_12_13_LSB); BIPOLAR |= (1 << AIN_12_13_LSB); RANGE &= ~ (1 << AIN_12_13_LSB); // UCH12/13=0, BCH12/13=1, RANGE12/13=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_12_13_DifferentialBipolarFSVref #if AIN_12_13_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN12, AIN13 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN12, AIN13 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN12 voltage must always be between 0 and VREF. // AIN13 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_12_13_LSB); BIPOLAR |= (1 << AIN_12_13_LSB); RANGE |= (1 << AIN_12_13_LSB); // UCH12/13=0, BCH12/13=1, RANGE12/13=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_12_13_DifferentialBipolarFS2Vref #if AIN_14_15_SingleEnded //---------------------------------------- // ADC Channels AIN14, AIN15 = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN14 is a Single-Ended input using Unipolar transfer function. // AIN15 is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN14 voltage must always be between 0 and VREF. // AIN15 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR AND BIPOLAR register set PER CHANNEL UCH(X)/(X+1) AND BCH(X)/(X+1) TO 0 FOR SINGLE-ENDED SELECTION UNIPOLAR &= ~ (1 << AIN_14_15_LSB); BIPOLAR &= ~ (1 << AIN_14_15_LSB); RANGE &= ~ (1 << AIN_14_15_LSB); // UCH14/15=0, BCH14/15=0, RANGE14/15=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_14_15_SingleEnded #if AIN_14_15_DifferentialUnipolar //---------------------------------------- // ADC Channels AIN14, AIN15 = Differential Unipolar (AIN14 > AIN15) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN14, AIN15 are a Differential pair using Unipolar transfer function. // AIN14 voltage must always be between 0 and VREF. // AIN15 voltage must always be between 0 and VREF. // // SELECT UNIPOLAR register set PER CHANNEL UCH(X)/(X+1) TO 1 FOR UNIPOLAR UNIPOLAR |= (1 << AIN_14_15_LSB); BIPOLAR &= ~ (1 << AIN_14_15_LSB); RANGE &= ~ (1 << AIN_14_15_LSB); // UCH14/15=1, BCH14/15=0, RANGE14/15=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_14_15_DifferentialUnipolar #if AIN_14_15_DifferentialBipolarFSVref //---------------------------------------- // ADC Channels AIN14, AIN15 = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN14, AIN15 are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN14 voltage must always be between 0 and VREF. // AIN15 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 0 +/-VREF+/2 UNIPOLAR &= ~ (1 << AIN_14_15_LSB); BIPOLAR |= (1 << AIN_14_15_LSB); RANGE &= ~ (1 << AIN_14_15_LSB); // UCH14/15=0, BCH14/15=1, RANGE14/15=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) #endif // AIN_14_15_DifferentialBipolarFSVref #if AIN_14_15_DifferentialBipolarFS2Vref //---------------------------------------- // ADC Channels AIN14, AIN15 = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN14, AIN15 are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN14 voltage must always be between 0 and VREF. // AIN15 voltage must always be between 0 and VREF. // // SELECT BIPOLAR register set PER CHANNEL BCH(X)/(X+1) TO 1 FOR BIPOLAR FULLY DIFFERENTIAL // SELECT RANGE register set PER CHANNEL PAIR RANGE(X)/(X+1) TO 1 +/-VREF+ UNIPOLAR &= ~ (1 << AIN_14_15_LSB); BIPOLAR |= (1 << AIN_14_15_LSB); RANGE |= (1 << AIN_14_15_LSB); // UCH14/15=0, BCH14/15=1, RANGE14/15=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) #endif // AIN_14_15_DifferentialBipolarFS2Vref //---------------------------------------- // SPI write ADC CONFIGURATION register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_CONFIGURATION); SPIoutputCS(1); // drive CS high //---------------------------------------- // SPI write UNIPOLAR BIPOLAR RANGE registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(UNIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(BIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(RANGE); SPIoutputCS(1); // drive CS high //---------------------------------------- // SPI write CSCAN0 CSCAN1 registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN0); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN1); SPIoutputCS(1); // drive CS high } //---------------------------------------- // Menu item 'IS' // ADC Channels AIN(channelId), AIN(channelId+1) = Both Single-Ended, Unipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN(channelId) is a Single-Ended input using Unipolar transfer function. // AIN(channelId+1) is a Single-Ended input using Unipolar transfer function. // If PDIFF_COM_1, both are Pseudo-Differential with REF- as common. // AIN(channelId) voltage must always be between 0 and VREF. // AIN(channelId+1) voltage must always be between 0 and VREF. // void MAX11131::Reconfigure_SingleEnded(int channel_0_15) { //---------------------------------------- // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=0, RANGE(ch)/(ch+1)=0: // AIN(ch)/AIN(ch+1) two independent single-ended inputs, // unipolar code (Full Scale = VREF, LSB = VREF/4096) // const int channelPairIndex = channel_0_15 / 2; const int bitmask = (1 << (10 - channelPairIndex)); UNIPOLAR &= ~ bitmask; BIPOLAR &= ~ bitmask; RANGE &= ~ bitmask; //---------------------------------------- // SPI write UNIPOLAR BIPOLAR RANGE registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(UNIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(BIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(RANGE); SPIoutputCS(1); // drive CS high } //---------------------------------------- // Menu item 'IU' // ADC Channels AIN(channelId), AIN(channelId+1) = Differential Unipolar (AIN(channelId) > AIN(channelId+1)) // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN(channelId), AIN(channelId+1) are a Differential pair using Unipolar transfer function. // AIN(channelId) voltage must always be between 0 and VREF. // AIN(channelId+1) voltage must always be between 0 and VREF. // void MAX11131::Reconfigure_DifferentialUnipolar(int channel_0_15) { //---------------------------------------- // UCH(ch)/(ch+1)=1, BCH(ch)/(ch+1)=0, RANGE(ch)/(ch+1)=0: // AIN(ch)/AIN(ch+1) differential input pair, // unipolar code (AIN(ch)>AIN(ch+1)) (Full Scale = VREF, LSB = VREF/4096) // const int channelPairIndex = channel_0_15 / 2; const int bitmask = (1 << (10 - channelPairIndex)); UNIPOLAR |= bitmask; BIPOLAR &= ~ bitmask; RANGE &= ~ bitmask; // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) //---------------------------------------- // SPI write UNIPOLAR BIPOLAR RANGE registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(UNIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(BIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(RANGE); SPIoutputCS(1); // drive CS high } //---------------------------------------- // Menu item 'IB' // ADC Channels AIN(channelId), AIN(channelId+1) = Differential Bipolar // Full Scale = VREF // Voltage per LSB count = VREF/4096 // AIN(channelId), AIN(channelId+1) are a Differential pair using Bipolar transfer function with range (+/-)(1/2)Vref // AIN(channelId) voltage must always be between 0 and VREF. // AIN(channelId+1) voltage must always be between 0 and VREF. // void MAX11131::Reconfigure_DifferentialBipolarFSVref(int channel_0_15) { //---------------------------------------- // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=1, RANGE(ch)/(ch+1)=0: // AIN(ch)/AIN(ch+1) differential input pair (+/-)(1/2)Vref, // bipolar code (Full Scale = VREF, LSB = VREF/4096) // const int channelPairIndex = channel_0_15 / 2; const int bitmask = (1 << (10 - channelPairIndex)); UNIPOLAR &= ~ bitmask; BIPOLAR |= bitmask; RANGE &= ~ bitmask; //---------------------------------------- // SPI write UNIPOLAR BIPOLAR RANGE registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(UNIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(BIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(RANGE); SPIoutputCS(1); // drive CS high } //---------------------------------------- // Menu item 'IR' // ADC Channels AIN(channelId), AIN(channelId+1) = Differential Bipolar // Full Scale = 2 * VREF // Voltage per LSB count = VREF/2048 // AIN(channelId), AIN(channelId+1) are a Differential pair using Bipolar transfer function with range (+/-)Vref // AIN(channelId) voltage must always be between 0 and VREF. // AIN(channelId+1) voltage must always be between 0 and VREF. // void MAX11131::Reconfigure_DifferentialBipolarFS2Vref(int channel_0_15) { //---------------------------------------- // UCH(ch)/(ch+1)=0, BCH(ch)/(ch+1)=1, RANGE(ch)/(ch+1)=1: // AIN(ch)/AIN(ch+1) differential input pair (+/-)Vref, // bipolar code (Full Scale = 2VREF, LSB = VREF/2048) // const int channelPairIndex = channel_0_15 / 2; const int bitmask = (1 << (10 - channelPairIndex)); UNIPOLAR &= ~ bitmask; BIPOLAR |= bitmask; RANGE |= bitmask; // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) //---------------------------------------- // SPI write UNIPOLAR BIPOLAR RANGE registers SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(UNIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(BIPOLAR); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(RANGE); SPIoutputCS(1); // drive CS high } //---------------------------------------- // SCAN_0000_NOP // // Shift 16 bits out of ADC, without changing configuration. // Note: @return data format depends on CHAN_ID bit: // "CH[3:0] DATA[11:0]" when CHAN_ID = 1, or // "0 DATA[11:0] x x x" when CHAN_ID = 0. int16_t MAX11131::ScanRead(void) { //---------------------------------------- // Read SPI data from device while MOSI (Maxim DIN) is 0. Effectively ADC_MODE_CONTROL SCAN[3:0] = SCAN_0000_NOP = 0 SPI_MOSI_Semantic = 0; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low int16_t misoData16 = SPIread16bits(); SPIoutputCS(1); // drive CS high // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] return misoData16; } //---------------------------------------- // SCAN_0000_NOP // // Read raw ADC codes from device into AINcode[] and RAW_misoData16[]. // If internal clock mode with SWCNV=0, measurements will be triggered using CNVST pin. // // @pre one of the Scan functions was called, setting NumWords // @param[in] NumWords: number of words to be read from the FIFO // @post RAW_misoData16[index] contains the raw SPI Master-In,Slave-Out data // @post AINcode[NUM_CHANNELS] contains the latest readings in LSBs // void MAX11131::ReadAINcode(void) { //---------------------------------------- // loop index for RAW_misoData16[SAMPLESET_MAX_ENTRIES]; int index; //---------------------------------------- // If internal clock mode with SWCNV=0, trigger measurement using CNVST pin and wait for EOC pin. if (isExternalClock == 0) { if (swcnv_0_1 == 0) { // SWCNV=0: trigger measurement by driving CNVST/AIN14 pin low // for a minimum active-low pulse duration of 5ns. (AIN14 is not available) // One CNVST pulse scans all requested channels and stores the results in the FIFO. CNVSToutputPulseLow(); } // wait for EOC low (internal clock mode end of conversion) EOCinputWaitUntilLow(); } //---------------------------------------- // Read raw ADC codes from device into AINcode[] and RAW_misoData16[]. // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] switch(ScanMode) { //---------------------------------------- // read data words // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] case SCAN_0000_NOP: case SCAN_0011_StandardInternalClock: case SCAN_0101_UpperInternalClock: case SCAN_0111_CustomInternalClock: default: for (index = 0; index < NumWords; index++) { RAW_misoData16[index] = ScanRead(); // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] int16_t value_u12 = (RAW_misoData16[index] & 0x0FFF); int channelId = ((RAW_misoData16[index] >> 12) & 0x000F); AINcode[channelId] = value_u12; } break; //---------------------------------------- // read data words // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] case SCAN_0001_Manual: case SCAN_0100_StandardExternalClock: case SCAN_0110_UpperExternalClock: case SCAN_1000_CustomExternalClock: case SCAN_1001_SampleSetExternalClock: if (chan_id_0_1 != 0) { for (index = 0; index < NumWords; index++) { RAW_misoData16[index] = ScanRead(); // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] int16_t value_u12 = (RAW_misoData16[index] & 0x0FFF); int channelId = ((RAW_misoData16[index] >> 12) & 0x000F); AINcode[channelId] = value_u12; } } else { for (index = 0; index < NumWords; index++) { RAW_misoData16[index] = ScanRead(); int16_t value_u12 = ((RAW_misoData16[index] >> 3) & 0x0FFF); int channelId = channelNumber_0_15; AINcode[channelId] = value_u12; } } break; //---------------------------------------- // read data words and calculate mean, stddev case SCAN_0010_Repeat: // ScanRead_nWords_chanID_mean(NumWords); // TODO1: missing function // was this function AINcode_print_value_chanID_mean(int nWords) in main? // But this function prints to standard output so can't be inside the driver. for (index = 0; index < NumWords; index++) { RAW_misoData16[index] = ScanRead(); } break; } } //---------------------------------------- // Sign-Extend a right-aligned MAX11131 code into a signed 2's complement value. // Supports the bipolar transfer functions. // @param[in] value_u12: raw 12-bit MAX11131 code (right justified). // @return sign-extended 2's complement value. // int32_t MAX11131::TwosComplementValue(uint32_t regValue) { const uint16_t SIGN_BIT_12BIT = 0x0800; const uint16_t FULL_SCALE_CODE_12BIT = 0x0fff; if (((regValue & SIGN_BIT_12BIT) != 0) && !((regValue & (SIGN_BIT_12BIT << 1)) != 0)) { // (bSignBitNegative && !bExtendedSignBitNegative) // Twos_Complement negative value int32_t Offset_regValue = (int32_t)(regValue - (FULL_SCALE_CODE_12BIT + 1)); return Offset_regValue; } // Twos_Complement positive value or zero return (int32_t)regValue; } //---------------------------------------- // Return the physical voltage corresponding to MAX11131 code. // Does not perform any offset or gain correction. // @pre VRef = Voltage of REF input, in Volts // @param[in] value_u12: raw 12-bit MAX11131 code (right justified). // @param[in] channelId: AIN channel number. // @return physical voltage corresponding to MAX11131 code. // double MAX11131::VoltageOfCode(int16_t value_u12, int channelId) { int channelPairIndex = channelId / 2; // format: 1 0 0 0 1 UCH0/1 UCH2/3 UCH4/5 UCH6/7 UCH8/9 UCH10/11 UCH12/13 UCH14/15 PDIFF_COM x x int UCHn = (UNIPOLAR >> (10 - channelPairIndex)) & 0x01; int BCHn = (BIPOLAR >> (10 - channelPairIndex)) & 0x01; int RANGEn = (RANGE >> (10 - channelPairIndex)) & 0x01; if (UCHn) { // UCH0/1=1, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 differential input pair, unipolar code (AIN0>AIN1) (Full Scale = VREF, LSB = VREF/4096) return (value_u12 * VRef / 4096); } else { if (BCHn) { if (RANGEn) { // UCH0/1=0, BCH0/1=1, RANGE0/1=1: AIN0/AIN1 differential input pair (+/-)Vref, bipolar code (Full Scale = 2VREF, LSB = VREF/2048) return (TwosComplementValue(value_u12) * VRef / 2048); } else { // UCH0/1=0, BCH0/1=1, RANGE0/1=0: AIN0/AIN1 differential input pair (+/-)(1/2)Vref, bipolar code (Full Scale = VREF, LSB = VREF/4096) return (TwosComplementValue(value_u12) * VRef / 4096); } } else { // UCH0/1=0, BCH0/1=0, RANGE0/1=0: AIN0/AIN1 two independent single-ended inputs, unipolar code (Full Scale = VREF, LSB = VREF/4096) return (value_u12 * VRef / 4096); } } } //---------------------------------------- // SCAN_0001_Manual // // Measure ADC channel channelNumber_0_15 once. // External clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For external clock modes, the data format depends on CHAN_ID. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanManual(void) { //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // Apply a soft reset when changing from internal to external clock mode. int needFIFOreset = (isExternalClock != 1); if (needFIFOreset) { // Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL = ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high ADC_MODE_CONTROL = 0; } //---------------------------------------- // number of words to read NumWords = 1; //---------------------------------------- // External Clock Mode isExternalClock = 1; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0001_Manual; //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0001_Manual = 1 //~ const int SCAN_0001_Manual = 1; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0001_Manual & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT // (applicable to external clock mode only) // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] ADC_MODE_CONTROL |= ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB); //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0010_Repeat // // Measure ADC channel channelNumber_0_15 repeatedly with averaging. // Internal clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word. // average_0_4_8_16_32=0 to disable averaging. // @param[in] nscan_4_8_12_16: Number of ScanRead() words to report. // @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV // SWCNV=0: trigger measurement by driving CNVST pin low. // Minimum active-low pulse duration of 5ns. (AIN14 is not available) // SWCNV=1: trigger measurement on SPI CS rising edge. // CS must be held low for minimum of 17 SCLK cycles. // CNVST pin is not used. (AIN14 is available) // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanRepeat(void) { //---------------------------------------- // number of words to read NumWords = (nscan_4_8_12_16); //---------------------------------------- // Internal Clock Mode isExternalClock = 0; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0010_Repeat; //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // define write-only register ADC_CONFIGURATION ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0 const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL const int AVGON_LSB = 9; const int AVGON_BITS = 0x01; // ADC_CONFIGURATION.AVGON const int NAVG_LSB = 7; const int NAVG_BITS = 0x03; // ADC_CONFIGURATION.NAVG[1:0] const int NSCAN_LSB = 5; const int NSCAN_BITS = 0x03; // ADC_CONFIGURATION.NSCAN[1:0] const int SPM_LSB = 3; const int SPM_BITS = 0x03; // ADC_CONFIGURATION.SPM[1:0] const int ECHO_LSB = 2; const int ECHO_BITS = 0x01; // ADC_CONFIGURATION.ECHO //---------------------------------------- // if average, ADC CONFIGURATION register set AVG and NAVG[1:0] // (applicable to internal clock mode only) // if average, ADC CONFIGURATION register set AVG ON BIT TO 1 // if average, ADC CONFIGURATION register set NAVG[1:0] TO N if (average_0_4_8_16_32 == 4) { // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((0 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 8) { // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((1 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 16) { // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((2 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 32) { // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((3 & NAVG_BITS) << NAVG_LSB); } else { // Disable Averaging (AVGON=0, NAVG[1:0]=0) ADC_CONFIGURATION &= ~ (( AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); } //---------------------------------------- // ADC CONFIGURATION register set NSCAN[1:0] for scan count // (applicable to SCAN_0010_Repeat only) if (nscan_4_8_12_16 == 4) { // Set scan count 4 ADC_CONFIGURATION &= ~ (( NSCAN_BITS) << NSCAN_LSB); ADC_CONFIGURATION |= ((0 & NSCAN_BITS) << NSCAN_LSB); } else if (nscan_4_8_12_16 == 8) { // Set scan count 8 ADC_CONFIGURATION &= ~ (( NSCAN_BITS) << NSCAN_LSB); ADC_CONFIGURATION |= ((1 & NSCAN_BITS) << NSCAN_LSB); } else if (nscan_4_8_12_16 == 12) { // Set scan count 12 ADC_CONFIGURATION &= ~ (( NSCAN_BITS) << NSCAN_LSB); ADC_CONFIGURATION |= ((2 & NSCAN_BITS) << NSCAN_LSB); } else if (nscan_4_8_12_16 == 16) { // Set scan count 16 ADC_CONFIGURATION &= ~ (( NSCAN_BITS) << NSCAN_LSB); ADC_CONFIGURATION |= ((3 & NSCAN_BITS) << NSCAN_LSB); } //---------------------------------------- // SPI write ADC CONFIGURATION register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_CONFIGURATION); SPIoutputCS(1); // drive CS high //---------------------------------------- // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1 Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL &= ~ (( RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved ADC_MODE_CONTROL |= ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0010_Repeat = 2 //~ const int SCAN_0010_Repeat = 2; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0010_Repeat & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL register set SWCNV if CNVST pin is not used // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT // (applicable to internal clock mode only) // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available) // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available) if (swcnv_0_1) { ADC_MODE_CONTROL |= ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB); } else { ADC_MODE_CONTROL &= ~ (( SWCNV_BITS) << SWCNV_LSB); } //---------------------------------------- // SPI write ADC MODE CONTROL register // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low if (swcnv_0_1) { // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17". SPIwrite24bits(ADC_MODE_CONTROL, 0); } else { SPIwrite16bits(ADC_MODE_CONTROL); } SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0011_StandardInternalClock // // Measure ADC channels in sequence from AIN0 to channelNumber_0_15. // Internal clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word. // average_0_4_8_16_32=0 to disable averaging. // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV // SWCNV=0: trigger measurement by driving CNVST pin low. // Minimum active-low pulse duration of 5ns. (AIN14 is not available) // SWCNV=1: trigger measurement on SPI CS rising edge. // CS must be held low for minimum of 17 SCLK cycles. // CNVST pin is not used. (AIN14 is available) // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanStandardInternalClock(void) { //---------------------------------------- // number of words to read NumWords = (1 + channelNumber_0_15); //---------------------------------------- // Internal Clock Mode isExternalClock = 0; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0011_StandardInternalClock; //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // define write-only register ADC_CONFIGURATION ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0 const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL const int AVGON_LSB = 9; const int AVGON_BITS = 0x01; // ADC_CONFIGURATION.AVGON const int NAVG_LSB = 7; const int NAVG_BITS = 0x03; // ADC_CONFIGURATION.NAVG[1:0] const int NSCAN_LSB = 5; const int NSCAN_BITS = 0x03; // ADC_CONFIGURATION.NSCAN[1:0] const int SPM_LSB = 3; const int SPM_BITS = 0x03; // ADC_CONFIGURATION.SPM[1:0] const int ECHO_LSB = 2; const int ECHO_BITS = 0x01; // ADC_CONFIGURATION.ECHO //---------------------------------------- // if average, ADC CONFIGURATION register set AVG and NAVG[1:0] // (applicable to internal clock mode only) // if average, ADC CONFIGURATION register set AVG ON BIT TO 1 // if average, ADC CONFIGURATION register set NAVG[1:0] TO N if (average_0_4_8_16_32 == 4) { // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((0 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 8) { // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((1 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 16) { // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((2 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 32) { // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((3 & NAVG_BITS) << NAVG_LSB); } else { // Disable Averaging (AVGON=0, NAVG[1:0]=0) ADC_CONFIGURATION &= ~ (( AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); } //---------------------------------------- // SPI write ADC CONFIGURATION register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_CONFIGURATION); SPIoutputCS(1); // drive CS high //---------------------------------------- // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1 Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL &= ~ (( RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved ADC_MODE_CONTROL |= ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0011_StandardInternalClock = 3 //~ const int SCAN_0011_StandardInternalClock = 3; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0011_StandardInternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL register set SWCNV if CNVST pin is not used // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT // (applicable to internal clock mode only) // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available) // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available) if (swcnv_0_1) { ADC_MODE_CONTROL |= ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB); } else { ADC_MODE_CONTROL &= ~ (( SWCNV_BITS) << SWCNV_LSB); } //---------------------------------------- // SPI write ADC MODE CONTROL register // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low if (swcnv_0_1) { // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17". SPIwrite24bits(ADC_MODE_CONTROL, 0); } else { SPIwrite16bits(ADC_MODE_CONTROL); } SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0100_StandardExternalClock // // Measure ADC channels in sequence from AIN0 to channelNumber_0_15. // External clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For external clock modes, the data format depends on CHAN_ID. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanStandardExternalClock(void) { //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // Apply a soft reset when changing from internal to external clock mode. int needFIFOreset = (isExternalClock != 1); if (needFIFOreset) { // Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL = ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high ADC_MODE_CONTROL = 0; } //---------------------------------------- // number of words to read NumWords = (1 + channelNumber_0_15); //---------------------------------------- // External Clock Mode isExternalClock = 1; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0100_StandardExternalClock; //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0100_StandardExternalClock = 4 //~ const int SCAN_0100_StandardExternalClock = 4; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0100_StandardExternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT // (applicable to external clock mode only) // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] ADC_MODE_CONTROL |= ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB); //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0101_UpperInternalClock // // Measure ADC channels in sequence from channelNumber_0_15 to AIN15. // Internal clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word. // average_0_4_8_16_32=0 to disable averaging. // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV // SWCNV=0: trigger measurement by driving CNVST pin low. // Minimum active-low pulse duration of 5ns. (AIN14 is not available) // SWCNV=1: trigger measurement on SPI CS rising edge. // CS must be held low for minimum of 17 SCLK cycles. // CNVST pin is not used. (AIN14 is available) // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanUpperInternalClock(void) { //---------------------------------------- // number of words to read NumWords = (16 - channelNumber_0_15); //---------------------------------------- // Internal Clock Mode isExternalClock = 0; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0101_UpperInternalClock; //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // define write-only register ADC_CONFIGURATION ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0 const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL const int AVGON_LSB = 9; const int AVGON_BITS = 0x01; // ADC_CONFIGURATION.AVGON const int NAVG_LSB = 7; const int NAVG_BITS = 0x03; // ADC_CONFIGURATION.NAVG[1:0] const int NSCAN_LSB = 5; const int NSCAN_BITS = 0x03; // ADC_CONFIGURATION.NSCAN[1:0] const int SPM_LSB = 3; const int SPM_BITS = 0x03; // ADC_CONFIGURATION.SPM[1:0] const int ECHO_LSB = 2; const int ECHO_BITS = 0x01; // ADC_CONFIGURATION.ECHO //---------------------------------------- // if average, ADC CONFIGURATION register set AVG and NAVG[1:0] // (applicable to internal clock mode only) // if average, ADC CONFIGURATION register set AVG ON BIT TO 1 // if average, ADC CONFIGURATION register set NAVG[1:0] TO N if (average_0_4_8_16_32 == 4) { // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((0 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 8) { // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((1 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 16) { // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((2 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 32) { // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((3 & NAVG_BITS) << NAVG_LSB); } else { // Disable Averaging (AVGON=0, NAVG[1:0]=0) ADC_CONFIGURATION &= ~ (( AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); } //---------------------------------------- // SPI write ADC CONFIGURATION register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_CONFIGURATION); SPIoutputCS(1); // drive CS high //---------------------------------------- // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1 Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL &= ~ (( RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved ADC_MODE_CONTROL |= ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0101_UpperInternalClock = 5 //~ const int SCAN_0101_UpperInternalClock = 5; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0101_UpperInternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL register set SWCNV if CNVST pin is not used // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT // (applicable to internal clock mode only) // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available) // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available) if (swcnv_0_1) { ADC_MODE_CONTROL |= ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB); } else { ADC_MODE_CONTROL &= ~ (( SWCNV_BITS) << SWCNV_LSB); } //---------------------------------------- // SPI write ADC MODE CONTROL register // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low if (swcnv_0_1) { // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17". SPIwrite24bits(ADC_MODE_CONTROL, 0); } else { SPIwrite16bits(ADC_MODE_CONTROL); } SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0110_UpperExternalClock // // Measure ADC channels in sequence from channelNumber_0_15 to AIN15. // External clock mode. // @param[in] channelNumber_0_15: AIN Channel Number // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For external clock modes, the data format depends on CHAN_ID. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanUpperExternalClock(void) { //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // Apply a soft reset when changing from internal to external clock mode. int needFIFOreset = (isExternalClock != 1); if (needFIFOreset) { // Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL = ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high ADC_MODE_CONTROL = 0; } //---------------------------------------- // number of words to read NumWords = (16 - channelNumber_0_15); //---------------------------------------- // External Clock Mode isExternalClock = 1; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0110_UpperExternalClock; //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0110_UpperExternalClock = 6 //~ const int SCAN_0110_UpperExternalClock = 6; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0110_UpperExternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((channelNumber_0_15 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT // (applicable to external clock mode only) // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] ADC_MODE_CONTROL |= ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB); //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_0111_CustomInternalClock // // Measure selected ADC channels in sequence from AIN0 to AIN15, // using only the channels enabled by enabledChannelsMask. // Bit 0x0001 enables AIN0. // Bit 0x0002 enables AIN1. // Bit 0x0004 enables AIN2. // Bit 0x0008 enables AIN3. // Bit 0x0010 enables AIN4. // Bit 0x0020 enables AIN5. // Bit 0x0040 enables AIN6. // Bit 0x0080 enables AIN7. // Bit 0x0100 enables AIN8. // Bit 0x0200 enables AIN9. // Bit 0x0400 enables AIN10. // Bit 0x0800 enables AIN11. // Bit 0x1000 enables AIN12. // Bit 0x2000 enables AIN13. // Bit 0x4000 enables AIN14. // Bit 0x8000 enables AIN15. // Internal clock mode. // @param[in] enabledChannelsMask: Bitmap of AIN Channels to scan. // @param[in] average_0_4_8_16_32: Number of samples averaged per ScanRead() word. // average_0_4_8_16_32=0 to disable averaging. // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] swcnv_0_1: ADC_MODE_CONTROL.SWCNV // SWCNV=0: trigger measurement by driving CNVST pin low. // Minimum active-low pulse duration of 5ns. (AIN14 is not available) // SWCNV=1: trigger measurement on SPI CS rising edge. // CS must be held low for minimum of 17 SCLK cycles. // CNVST pin is not used. (AIN14 is available) // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanCustomInternalClock(void) { //---------------------------------------- // count nWords = number of set bits in enabledChannelsMask uint16_t bitMask; int nWords = 0; for (bitMask = 0x8000; bitMask != 0; bitMask = bitMask / 2) { if (enabledChannelsMask & bitMask) { nWords++; } } //---------------------------------------- // number of words to read NumWords = nWords; //---------------------------------------- // Internal Clock Mode isExternalClock = 0; //---------------------------------------- // update device driver global variable ScanMode = SCAN_0111_CustomInternalClock; //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // define write-only register ADC_CONFIGURATION ADC_CONFIGURATION = 0x8000; //!< mosiData16 0x8000..0x87FF format: 1 0 0 0 0 REFSEL AVGON NAVG[1:0] NSCAN[1:0] SPM[1:0] ECHO 0 0 const int REFSEL_LSB = 10; const int REFSEL_BITS = 0x01; // ADC_CONFIGURATION.REFSEL const int AVGON_LSB = 9; const int AVGON_BITS = 0x01; // ADC_CONFIGURATION.AVGON const int NAVG_LSB = 7; const int NAVG_BITS = 0x03; // ADC_CONFIGURATION.NAVG[1:0] const int NSCAN_LSB = 5; const int NSCAN_BITS = 0x03; // ADC_CONFIGURATION.NSCAN[1:0] const int SPM_LSB = 3; const int SPM_BITS = 0x03; // ADC_CONFIGURATION.SPM[1:0] const int ECHO_LSB = 2; const int ECHO_BITS = 0x01; // ADC_CONFIGURATION.ECHO //---------------------------------------- // define write-only registers CSCAN0,CSCAN1 CSCAN0 = 0xA000; //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15 const int CHSCAN14_LSB = 9; // CSCAN0.CHSCAN14 const int CHSCAN13_LSB = 8; // CSCAN0.CHSCAN13 const int CHSCAN12_LSB = 7; // CSCAN0.CHSCAN12 const int CHSCAN11_LSB = 6; // CSCAN0.CHSCAN11 const int CHSCAN10_LSB = 5; // CSCAN0.CHSCAN10 const int CHSCAN9_LSB = 4; // CSCAN0.CHSCAN9 const int CHSCAN8_LSB = 3; // CSCAN0.CHSCAN8 CSCAN1 = 0xA800; //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7 const int CHSCAN6_LSB = 9; // CSCAN1.CHSCAN6 const int CHSCAN5_LSB = 8; // CSCAN1.CHSCAN5 const int CHSCAN4_LSB = 7; // CSCAN1.CHSCAN4 const int CHSCAN3_LSB = 6; // CSCAN1.CHSCAN3 const int CHSCAN2_LSB = 5; // CSCAN1.CHSCAN2 const int CHSCAN1_LSB = 4; // CSCAN1.CHSCAN1 const int CHSCAN0_LSB = 3; // CSCAN1.CHSCAN0 //---------------------------------------- // if average, ADC CONFIGURATION register set AVG and NAVG[1:0] // (applicable to internal clock mode only) // if average, ADC CONFIGURATION register set AVG ON BIT TO 1 // if average, ADC CONFIGURATION register set NAVG[1:0] TO N if (average_0_4_8_16_32 == 4) { // Enable Averaging of 4 samples (AVGON=1, NAVG[1:0]=0) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((0 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 8) { // Enable Averaging of 8 samples (AVGON=1, NAVG[1:0]=1) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((1 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 16) { // Enable Averaging of 16 samples (AVGON=1, NAVG[1:0]=2) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((2 & NAVG_BITS) << NAVG_LSB); } else if (average_0_4_8_16_32 == 32) { // Enable Averaging of 32 samples (AVGON=1, NAVG[1:0]=3) ADC_CONFIGURATION |= ((1 & AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); ADC_CONFIGURATION |= ((3 & NAVG_BITS) << NAVG_LSB); } else { // Disable Averaging (AVGON=0, NAVG[1:0]=0) ADC_CONFIGURATION &= ~ (( AVGON_BITS) << AVGON_LSB); ADC_CONFIGURATION &= ~ (( NAVG_BITS) << NAVG_LSB); } //---------------------------------------- // SPI write ADC CONFIGURATION register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_CONFIGURATION); SPIoutputCS(1); // drive CS high //---------------------------------------- // SET CSCAN0 CSCAN1 REGISTERS from enabledChannelsMask CSCAN0 = 0xA000 | (((enabledChannelsMask >> 8) & 0xFF) << 3); // CSCAN0.CHSCAN[15:8] CSCAN1 = 0xA800 | (((enabledChannelsMask) & 0xFF) << 3); // CSCAN1.CHSCAN[7:0] SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN0); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN1); SPIoutputCS(1); // drive CS high //---------------------------------------- // Reset FIFO: ADC_MODE_CONTROL.RESET[1:0] = 1 Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL &= ~ (( RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved ADC_MODE_CONTROL |= ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_0111_CustomInternalClock = 7 //~ const int SCAN_0111_CustomInternalClock = 7; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_0111_CustomInternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL register set SWCNV if CNVST pin is not used // ADC MODE CONTROL REGISTER SELECT THE RIGHT SWCNV BIT // (applicable to internal clock mode only) // SWCNV=1: trigger measurement on SPI CS rising edge; CNVST pin is not used. (AIN14 is available) // SWCNV=0: trigger measurement by driving CNVST pin low for a minimum active-low pulse duration of 5ns. (AIN14 is not available) if (swcnv_0_1) { ADC_MODE_CONTROL |= ((swcnv_0_1 & SWCNV_BITS) << SWCNV_LSB); } else { ADC_MODE_CONTROL &= ~ (( SWCNV_BITS) << SWCNV_LSB); } //---------------------------------------- // SPI write ADC MODE CONTROL register // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low if (swcnv_0_1) { // If SWCNV=1 then CS must be held low for at least 17 SCLK cycles. // NOTE: Figure 7 Internal Conversions with SWCNV=1 has an error, the 17th SCLK is mislabeled as "16" should be "17". SPIwrite24bits(ADC_MODE_CONTROL, 0); } else { SPIwrite16bits(ADC_MODE_CONTROL); } SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_1000_CustomExternalClock // // Measure selected ADC channels in sequence from AIN0 to AIN15, // using only the channels enabled by enabledChannelsMask. // Bit 0x0001 enables AIN0. // Bit 0x0002 enables AIN1. // Bit 0x0004 enables AIN2. // Bit 0x0008 enables AIN3. // Bit 0x0010 enables AIN4. // Bit 0x0020 enables AIN5. // Bit 0x0040 enables AIN6. // Bit 0x0080 enables AIN7. // Bit 0x0100 enables AIN8. // Bit 0x0200 enables AIN9. // Bit 0x0400 enables AIN10. // Bit 0x0800 enables AIN11. // Bit 0x1000 enables AIN12. // Bit 0x2000 enables AIN13. // Bit 0x4000 enables AIN14. // Bit 0x8000 enables AIN15. // External clock mode. // @param[in] enabledChannelsMask: Bitmap of AIN Channels to scan. // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For external clock modes, the data format depends on CHAN_ID. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanCustomExternalClock(void) { //---------------------------------------- // count nWords = number of set bits in enabledChannelsMask uint16_t bitMask; int nWords = 0; for (bitMask = 0x8000; bitMask != 0; bitMask = bitMask / 2) { if (enabledChannelsMask & bitMask) { nWords++; } } //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // Apply a soft reset when changing from internal to external clock mode. int needFIFOreset = (isExternalClock != 1); if (needFIFOreset) { // Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL = ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high ADC_MODE_CONTROL = 0; } //---------------------------------------- // number of words to read NumWords = nWords; //---------------------------------------- // External Clock Mode isExternalClock = 1; //---------------------------------------- // update device driver global variable ScanMode = SCAN_1000_CustomExternalClock; //---------------------------------------- // define write-only registers CSCAN0,CSCAN1 CSCAN0 = 0xA000; //!< mosiData16 0xA000..0xA7FF format: 1 0 1 0 0 CHSCAN15 CHSCAN14 CHSCAN13 CHSCAN12 CHSCAN11 CHSCAN10 CHSCAN9 CHSCAN8 x x x const int CHSCAN15_LSB = 10; // CSCAN0.CHSCAN15 const int CHSCAN14_LSB = 9; // CSCAN0.CHSCAN14 const int CHSCAN13_LSB = 8; // CSCAN0.CHSCAN13 const int CHSCAN12_LSB = 7; // CSCAN0.CHSCAN12 const int CHSCAN11_LSB = 6; // CSCAN0.CHSCAN11 const int CHSCAN10_LSB = 5; // CSCAN0.CHSCAN10 const int CHSCAN9_LSB = 4; // CSCAN0.CHSCAN9 const int CHSCAN8_LSB = 3; // CSCAN0.CHSCAN8 CSCAN1 = 0xA800; //!< mosiData16 0xA800..0xAFFF format: 1 0 1 0 1 CHSCAN7 CHSCAN6 CHSCAN5 CHSCAN4 CHSCAN3 CHSCAN2 CHSCAN1 CHSCAN0 x x x const int CHSCAN7_LSB = 10; // CSCAN1.CHSCAN7 const int CHSCAN6_LSB = 9; // CSCAN1.CHSCAN6 const int CHSCAN5_LSB = 8; // CSCAN1.CHSCAN5 const int CHSCAN4_LSB = 7; // CSCAN1.CHSCAN4 const int CHSCAN3_LSB = 6; // CSCAN1.CHSCAN3 const int CHSCAN2_LSB = 5; // CSCAN1.CHSCAN2 const int CHSCAN1_LSB = 4; // CSCAN1.CHSCAN1 const int CHSCAN0_LSB = 3; // CSCAN1.CHSCAN0 //---------------------------------------- // SET CSCAN0 CSCAN1 REGISTERS from enabledChannelsMask CSCAN0 = 0xA000 | (((enabledChannelsMask >> 8) & 0xFF) << 3); // CSCAN0.CHSCAN[15:8] CSCAN1 = 0xA800 | (((enabledChannelsMask) & 0xFF) << 3); // CSCAN1.CHSCAN[7:0] SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN0); SPIoutputCS(1); // drive CS high SPIoutputCS(0); // drive CS low SPIwrite16bits(CSCAN1); SPIoutputCS(1); // drive CS high //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_1000_CustomExternalClock = 8 //~ const int SCAN_1000_CustomExternalClock = 8; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_1000_CustomExternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT // (applicable to external clock mode only) // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] ADC_MODE_CONTROL |= ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB); //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // SCAN_1001_SampleSetExternalClock // // Measure ADC channels in an arbitrary pattern. // Channels can be visited in any order, with repetition allowed. // External clock mode. // @pre enabledChannelsPatternLength_1_256: number of channel selections // @pre enabledChannelsPattern: array containing channel selection pattern // In the array, one channel select per byte. // In the SPI interface, immediately after SAMPLESET register is written, // each byte encodes two channelNumber selections. // The high 4 bits encode the first channelNumber. // (((enabledChannelsPattern[0]) & 0x0F) << 4) | ((enabledChannelsPattern[1]) & 0x0F) // If it is an odd number of channels, additional nybbles will be ignored. // CS will be asserted low during the entire SAMPLESET pattern selection. // @param[in] enabledChannelsPattern: array of channel select, one channel per byte // @param[in] PowerManagement_0_2: 0=Normal, 1=AutoShutdown, 2=AutoStandby // @param[in] chan_id_0_1: ADC_MODE_CONTROL.CHAN_ID // @return number of ScanRead() words needed to retrieve the data. // @post NumWords = number of words to be read from the FIFO // For external clock modes, the data format depends on CHAN_ID. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // int MAX11131::ScanSampleSetExternalClock(void) { //---------------------------------------- // define write-only register ADC_MODE_CONTROL ADC_MODE_CONTROL = 0; //!< mosiData16 0x0000..0x7FFF format: 0 SCAN[3:0] CHSEL[3:0] RESET[1:0] PM[1:0] CHAN_ID SWCNV 0 const int SCAN_LSB = 11; const int SCAN_BITS = 0x0F; //!< ADC_MODE_CONTROL.SCAN[3:0] ADC Scan Control (command) const int CHSEL_LSB = 7; const int CHSEL_BITS = 0x0F; //!< ADC_MODE_CONTROL.CHSEL[3:0] Analog Input Channel Select AIN0..AIN15 const int RESET_LSB = 5; const int RESET_BITS = 0x03; //!< ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved const int PM_LSB = 3; const int PM_BITS = 0x03; //!< ADC_MODE_CONTROL.PM[1:0] Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved const int CHAN_ID_LSB = 2; const int CHAN_ID_BITS = 0x01; //!< ADC_MODE_CONTROL.CHAN_ID const int SWCNV_LSB = 1; const int SWCNV_BITS = 0x01; //!< ADC_MODE_CONTROL.SWCNV //---------------------------------------- // Apply a soft reset when changing from internal to external clock mode. int needFIFOreset = (isExternalClock != 1); if (needFIFOreset) { // Apply a soft reset when changing from internal to external clock mode. ADC_MODE_CONTROL = ((1 & RESET_BITS) << RESET_LSB); // ADC_MODE_CONTROL.RESET[1:0] Reset 0=Normal 1=ResetFIFO 2=ResetAllRegisters 3=reserved // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high ADC_MODE_CONTROL = 0; } //---------------------------------------- // number of words to read NumWords = ((enabledChannelsPatternLength_1_256 != 0) ? enabledChannelsPatternLength_1_256 : 256 ); //---------------------------------------- // External Clock Mode isExternalClock = 1; //---------------------------------------- // update device driver global variable ScanMode = SCAN_1001_SampleSetExternalClock; //---------------------------------------- // Initialize shadow of write-only register SAMPLESET. // Do not write to SAMPLESET at this time. // A write to SAMPLESET must be followed by specified number of pattern entry words. // See ScanSampleSetExternalClock function for details. SAMPLESET = 0xB000; //!< mosiData16 0xB000..0xB7FF format: 1 0 1 1 0 SEQ_LENGTH[7:0] x x x const int SAMPLESET_LSB = 3; const int SAMPLESET_BITS = 0xFF; // SAMPLESET.SEQ_LENGTH[7:0] //---------------------------------------- // SampleSet register set SEQ_DEPTH[7:0] TO SET CHANNEL CAPTURE DEPTH; FOLLOW SampleSet REGISTER WITH CHANNEL PATTERN OF THE SAME SIZE AS SEQUENCE DEPTH // NOTE: SAMPLESET.SEQ_LENGTH[7:0] is the number of channel entries in the pattern. // NOTE: Each channel entry is 4 bits. The first 4 bits are the first channel in the sequence. // NOTE: Channels can be repeated in any arbitrary order. // NOTE: The channel entry pattern is sent immediately after writing SAMPLESET. // NOTE: Keep CS low during the entire SAMPLESET pattern entry. const int seq_length_minus_one_0_255 = enabledChannelsPatternLength_1_256 - 1; SAMPLESET = 0xB000; //SAMPLESET &= ~ (( SAMPLESET_BITS) << SAMPLESET_LSB); SAMPLESET |= ((seq_length_minus_one_0_255 & SAMPLESET_BITS) << SAMPLESET_LSB); SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(SAMPLESET); // SAMPLESET must be followed by several more bytes, length specified by SEQ_LENGTH[7:0] // pack enabledChannelsPattern[index] into nybbles SPIoutputCS(1); // drive CS high // NOTE: Send the sampleset pattern, with 4 entries packed into each 16-bit SPI word. Pad unused entries with 0. SPI_MOSI_Semantic = 2; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low // NOTE: Keep CS low during the entire SAMPLESET pattern entry. int entryIndex; for (entryIndex = 0; entryIndex < enabledChannelsPatternLength_1_256; entryIndex += 4) { uint16_t pack4channels = 0; pack4channels |= (((enabledChannelsPattern[entryIndex + 0]) & 0x0F) << 12); if ((entryIndex + 1) < enabledChannelsPatternLength_1_256) { pack4channels |= (((enabledChannelsPattern[entryIndex + 1]) & 0x0F) << 8); } if ((entryIndex + 2) < enabledChannelsPatternLength_1_256) { pack4channels |= (((enabledChannelsPattern[entryIndex + 2]) & 0x0F) << 4); } if ((entryIndex + 3) < enabledChannelsPatternLength_1_256) { pack4channels |= ((enabledChannelsPattern[entryIndex + 3]) & 0x0F); } SPIwrite16bits(pack4channels); } SPIoutputCS(1); // drive CS high //---------------------------------------- // ADC MODE CONTROL register set SCAN[3:0] TO SCAN_1001_SampleSetExternalClock = 9 //~ const int SCAN_1001_SampleSetExternalClock = 9; // replaced local const with enum ADC_MODE_CONTROL |= ((SCAN_1001_SampleSetExternalClock & SCAN_BITS) << SCAN_LSB); //---------------------------------------- // ADC MODE CONTROL register set CHSEL[3:0] TO channel number ADC_MODE_CONTROL |= ((0 & CHSEL_BITS) << CHSEL_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE PM[1:0] BITS ADC_MODE_CONTROL |= ((PowerManagement_0_2 & PM_BITS) << PM_LSB); //---------------------------------------- // ADC MODE CONTROL REGISTER SELECT THE CHAN_ID BIT // (applicable to external clock mode only) // For external clock modes, the data format returned depends on the CHAN_ID bit. // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // when CHAN_ID = 1: misoData16 = CH[3:0] DATA[11:0] // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] ADC_MODE_CONTROL |= ((chan_id_0_1 & CHAN_ID_BITS) << CHAN_ID_LSB); //---------------------------------------- // SPI write ADC MODE CONTROL register // Send SPI configuration to device SPI_MOSI_Semantic = 1; // 0:Nothing 1:regWrite 2:sampleSetPattern SPIoutputCS(0); // drive CS low SPIwrite16bits(ADC_MODE_CONTROL); SPIoutputCS(1); // drive CS high //---------------------------------------- // return number of words to read return NumWords; } //---------------------------------------- // Example configure and perform some measurements in ScanManual mode. // @param[out] pd_mean = address for double mean (avearge) // @param[out] pd_variance = address for double variance (variance) // @param[out] pd_stddev = address for double stddev (standard deviation) // @param[out] pd_Sx = address for double Sx (sum of all X) // @param[out] pd_Sxx = address for double Sxx (sum of squares of each X) void MAX11131::Example_ScanManual(int channelNumber_0_15, int nWords, double* pd_mean, double* pd_variance, double* pd_stddev, double* pd_Sx, double* pd_Sxx) { //---------------------------------------- // configure and perform some measurements in ScanManual mode Init(); channelNumber_0_15 = channelNumber_0_15; // Analog Input Channel Select AIN0.. PowerManagement_0_2 = 0; // Power Management 0=Normal, 1=AutoShutdown, 2=AutoStandby 3=reserved chan_id_0_1 = 1; // when CHAN_ID = 0: misoData16 = 0 DATA[11:0] x x x // const int nWords = 100; double Sx = 0; double Sxx = 0; int index; ScanManual(); for (index = 0; index < nWords; index++) { int16_t misoData16 = ScanRead(); // For internal clock modes, the data format always includes the channel address. // misoData16 = CH[3:0] DATA[11:0] int16_t value_u12 = (misoData16 & 0x0FFF); int channelId = ((misoData16 >> 12) & 0x000F); Sx = Sx + value_u12; Sxx = Sxx + ((double)value_u12 * value_u12); } if (pd_Sx != 0) { *(pd_Sx) = Sx; } if (pd_Sxx != 0) { *(pd_Sxx) = Sxx; } if (pd_mean != 0) { *(pd_mean) = Sx / nWords; } if (nWords >= 2) { if (pd_variance != 0) { // TODO1: is this variance calculation too naive to work reliably? // see https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance *(pd_variance) = (Sxx - ( Sx * Sx / nWords) ) / (nWords - 1); } if (pd_stddev != 0) { extern double sqrt(double); *(pd_stddev) = sqrt( *(pd_variance) ); } } } // End of file