Maxim Integrated MAX5715 12-bit 4-channel voltage-output DAC
Dependents: MAX5715BOB_Tester MAX5715BOB_12bit_4ch_SPI_DAC MAX5715BOB_Serial_Tester
MAX5715.cpp
- Committer:
- whismanoid
- Date:
- 2019-10-30
- Revision:
- 7:3c45adf3efe8
- Parent:
- 5:7894decf9375
File content as of revision 7:3c45adf3efe8:
// /******************************************************************************* // * Copyright (C) 2019 Maxim Integrated Products, Inc., All Rights Reserved. // * // * Permission is hereby granted, free of charge, to any person obtaining a // * copy of this software and associated documentation files (the "Software"), // * to deal in the Software without restriction, including without limitation // * the rights to use, copy, modify, merge, publish, distribute, sublicense, // * and/or sell copies of the Software, and to permit persons to whom the // * Software is furnished to do so, subject to the following conditions: // * // * The above copyright notice and this permission notice shall be included // * in all copies or substantial portions of the Software. // * // * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES // * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // * OTHER DEALINGS IN THE SOFTWARE. // * // * Except as contained in this notice, the name of Maxim Integrated // * Products, Inc. shall not be used except as stated in the Maxim Integrated // * Products, Inc. Branding Policy. // * // * The mere transfer of this software does not imply any licenses // * of trade secrets, proprietary technology, copyrights, patents, // * trademarks, maskwork rights, or any other form of intellectual // * property whatsoever. Maxim Integrated Products, Inc. retains all // * ownership rights. // ******************************************************************************* // */ // ********************************************************************* // @file MAX5715.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 "MAX5715.h" // Device Name = MAX5715 // Device Description = Ultra-Small, 12-Bit, 4-Channel, Buffered Output Voltage DAC with Internal Reference and SPI Interface // Device DeviceBriefDescription = 12-bit 4-ch SPI VOUT DAC // Device Manufacturer = Maxim Integrated // Device PartNumber = MAX5715AAUD+ // Device RegValue_Width = DataWidth16bit_HL // // DAC NumChannels = 4 // DAC ResolutionBits = 12 // // SPI CS = ActiveLow // SPI FrameStart = CS // SPI CPOL = 1 // SPI CPHA = 0 // SPI MOSI and MISO Data are both stable on Falling edge of SCLK // SPI SCLK Idle High // SPI SCLKMaxMHz = 50 // SPI SCLKMinMHz = 0 // // InputPin Name = LDAC# // InputPin Description = Dedicated Active-Low Asynchronous Load DAC. // InputPin Function = Trigger // // InputPin Name = CLR# // InputPin Description = Active-Low Clear Input. // InputPin Function = Trigger // // InputPin Name = REF // InputPin Description = Reference Voltage Input/Output. // Software selectable to be external reference or internal 2.048V, 2.500V, or 4.096V reference. // Default is external reference mode. // InputPin Function = Reference // // OutputPin Name = OUTA // OutputPin Description = Buffered Channel A DAC Output // OutputPin Function = Analog // // OutputPin Name = OUTB // OutputPin Description = Buffered Channel B DAC Output // OutputPin Function = Analog // // OutputPin Name = OUTC // OutputPin Description = Buffered Channel C DAC Output // OutputPin Function = Analog // // OutputPin Name = OUTD // OutputPin Description = Buffered Channel D DAC Output // OutputPin Function = Analog // // OutputPin Name = RDY# // OutputPin Description = SPI RDY Output. In daisy-chained applications connect RDY to the CSB of the next device in the chain. // OutputPin Function = DaisyChain // // SupplyPin Name = VDD // SupplyPin Description = Supply Voltage Input. Bypass VDD with a 0.1uF capacitor to GND. // SupplyPin VinMax = 5.5 // SupplyPin VinMin = 2.7 (unless configured DAC VRefInternal = 4.096V, then VinMin = 4.5V) // SupplyPin Function = Analog // // SupplyPin Name = VDDIO // SupplyPin Description = Digital Interface Power-Supply Input // SupplyPin VinMax = 5.5 // SupplyPin VinMin = 1.8 // SupplyPin Function = Digital // MAX5715::MAX5715(SPI &spi, DigitalOut &cs_pin, // SPI interface DigitalOut &LDACb_pin, // Digital Trigger Input to MAX5715 device DigitalOut &CLRb_pin, // Digital Trigger Input to MAX5715 device // AnalogOut &REF_pin, // Reference Input to MAX5715 device // AnalogIn &OUTA_pin, // Analog Output from MAX5715 device // AnalogIn &OUTB_pin, // Analog Output from MAX5715 device // AnalogIn &OUTC_pin, // Analog Output from MAX5715 device // AnalogIn &OUTD_pin, // Analog Output from MAX5715 device // DigitalIn &RDYb_pin, // Digital DaisyChain Output from MAX5715 device MAX5715_ic_t ic_variant) : m_spi(spi), m_cs_pin(cs_pin), // SPI interface m_LDACb_pin(LDACb_pin), // Digital Trigger Input to MAX5715 device m_CLRb_pin(CLRb_pin), // Digital Trigger Input to MAX5715 device // m_REF_pin(REF_pin), // Reference Input to MAX5715 device // m_OUTA_pin(OUTA_pin), // Analog Output from MAX5715 device // m_OUTB_pin(OUTB_pin), // Analog Output from MAX5715 device // m_OUTC_pin(OUTC_pin), // Analog Output from MAX5715 device // m_OUTD_pin(OUTD_pin), // Analog Output from MAX5715 device // m_RDYb_pin(RDYb_pin), // Digital DaisyChain Output from MAX5715 device m_ic_variant(ic_variant) { // SPI CS = ActiveLow // SPI FrameStart = CS m_SPI_cs_state = 1; m_cs_pin = m_SPI_cs_state; // SPI CPOL = 1 // SPI CPHA = 0 // SPI MOSI and MISO Data are both stable on Falling edge of SCLK // SPI SCLK Idle High m_SPI_dataMode = 2; //SPI_MODE2; // CPOL=1,CPHA=0: Falling 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 = 50 // SPI SCLKMinMHz = 0 //#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 m_SPI_SCLK_Hz = 12000000; // 12MHz; MAX5715 limit is 50MHz m_spi.frequency(m_SPI_SCLK_Hz); // // LDACb Trigger Input to MAX5715 device m_LDACb_pin = 1; // output logic high -- initial value in constructor // // CLRb Trigger Input to MAX5715 device m_CLRb_pin = 1; // output logic high -- initial value in constructor // // REF Reference Input to MAX5715 device // // OUTA Analog Output from device // // OUTB Analog Output from device // // OUTC Analog Output from device // // OUTD Analog Output from device // // RDYb DaisyChain Output from device } MAX5715::~MAX5715() { // do nothing } /// set SPI SCLK frequency void MAX5715::spi_frequency(int spi_sclk_Hz) { m_SPI_SCLK_Hz = spi_sclk_Hz; m_spi.frequency(m_SPI_SCLK_Hz); } // Assert SPI Chip Select // SPI chip-select for MAX5715 // void MAX5715::SPIoutputCS(int isLogicHigh) { m_SPI_cs_state = isLogicHigh; m_cs_pin = m_SPI_cs_state; } // SPI write 24 bits // SPI interface to MAX5715 shift 24 bits mosiData into MAX5715 DIN // void MAX5715::SPIwrite24bits(int8_t mosiData8_FF0000, int16_t mosiData16_00FFFF) { size_t byteCount = 3; static char mosiData[3]; static char misoData[3]; mosiData[0] = mosiData8_FF0000; mosiData[1] = (char)((mosiData16_00FFFF >> 8) & 0xFF); // MSByte mosiData[2] = (char)((mosiData16_00FFFF >> 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); //~ SPI.transfer(mosiData8_FF0000); //~ SPI.transfer(mosiData16_00FF00); //~ 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 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 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; } // Assert MAX5715 LDAC pin : High = inactive, Low = load DAC. // void MAX5715::LDACboutputValue(int isLogicHigh) { // m_LDACb_pin.output(); // only applicable to DigitalInOut m_LDACb_pin = isLogicHigh; } // Assert MAX5715 CLR pin : High = inactive, Low = clear DAC. // void MAX5715::CLRboutputValue(int isLogicHigh) { // m_CLRb_pin.output(); // only applicable to DigitalInOut m_CLRb_pin = isLogicHigh; } //---------------------------------------- // Menu item '!' // Initialize device // @return 1 on success; 0 on failure uint8_t MAX5715::Init(void) { //---------------------------------------- // Initialize device //---------------------------------------- // Perform Software Reset if (!SW_RESET()) { return 0; // failure } //---------------------------------------- // Turn on the reference output pin REF(REF_AlwaysOn_2V500); // //~ Serial.println(F(" success")); //~ return; return 1; // success } //---------------------------------------- // Return the DAC register value corresponding to physical voltage. // Does not perform any offset or gain correction. // // @pre VRef = Voltage of REF input, in Volts // @param[in] voltage = physical voltage in Volts // @return raw 12-bit MAX5715 code (right justified). uint16_t MAX5715::DACCodeOfVoltage(double voltageV) { //---------------------------------------- // Linear map min and max endpoints const double MaxScaleVoltage = VRef; // voltage of maximum code 0x0fff const double MinScaleVoltage = 0.0; // voltage of minimum code 0x000 const uint16_t FULL_SCALE_CODE_12BIT = 0x0fff; const uint16_t MaxCode = FULL_SCALE_CODE_12BIT; const uint16_t MinCode = 0x000; double codeFraction = (voltageV - MinScaleVoltage) / (MaxScaleVoltage - MinScaleVoltage); double dacRegValueIdeal = ((codeFraction * (double)(MaxCode - MinCode + 1)) + MinCode + 0.5); uint16_t dacRegValue = (uint16_t)dacRegValueIdeal; if (dacRegValueIdeal > MaxCode) { dacRegValue = MaxCode; } else if (dacRegValueIdeal < MinCode) { dacRegValue = MinCode; } return dacRegValue; } //---------------------------------------- // Return the physical voltage corresponding to DAC register. // Does not perform any offset or gain correction. // // @pre VRef = Voltage of REF input, in Volts // @param[in] value_u12: raw 12-bit MAX5715 code (right justified). // @return physical voltage corresponding to MAX5715 code. double MAX5715::VoltageOfCode(uint16_t value_u12) { //---------------------------------------- // Linear map min and max endpoints double MaxScaleVoltage = VRef; // voltage of maximum code 0x0fff double MinScaleVoltage = 0.0; // voltage of minimum code 0x000 const uint16_t FULL_SCALE_CODE_12BIT = 0x0fff; const uint16_t MaxCode = FULL_SCALE_CODE_12BIT; const uint16_t MinCode = 0x000; double codeFraction = ((double)value_u12 - MinCode) / (MaxCode - MinCode + 1); return MinScaleVoltage + ((MaxScaleVoltage - MinScaleVoltage) * codeFraction); } //---------------------------------------- // CMD_1000_0000_dddd_dddd_dddd_0000_CODEall // // Writes data to all CODE registers // @post updates g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] // @post updates g_MAX5815_device.CODE[0..3] void MAX5715::CODEall(uint16_t dacCodeLsbs) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_1000_0000_dddd_dddd_dddd_0000_CODEall; uint16_t regValue = (dacCodeLsbs << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register CODE 0010_nnnn[channel_0_3] // Each bit of channels_bitmask_DCBA maps to an index of g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] if (channels_bitmask_DCBA & (1 << 0)) { CODE[0] = dacCodeLsbs; Shadow_0010_nnnn_CODE[0] = regValue; } if (channels_bitmask_DCBA & (1 << 1)) { CODE[1] = dacCodeLsbs; Shadow_0010_nnnn_CODE[1] = regValue; } if (channels_bitmask_DCBA & (1 << 2)) { CODE[2] = dacCodeLsbs; Shadow_0010_nnnn_CODE[2] = regValue; } if (channels_bitmask_DCBA & (1 << 3)) { CODE[3] = dacCodeLsbs; Shadow_0010_nnnn_CODE[3] = regValue; } } //---------------------------------------- // CMD_0000_nnnn_dddd_dddd_dddd_0000_CODEn // // Writes data to the selected CODE register(s) // // @param[in] channel_0_3 = DAC Selection: 0=OUTA, 1=OUTB, 2=OUTC, 3=OUTD, 4..15=ALL OUTA,OUTB,OUTC,OUTD // @post updates g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] // @post updates g_MAX5815_device.CODE[0..3] void MAX5715::CODEn(uint8_t channel_0_3, uint16_t dacCodeLsbs) { //---------------------------------------- // update channel selection from channel_0_3 channelNumber_0_3 = channel_0_3; switch (channelNumber_0_3) { case 0: channels_bitmask_DCBA = 0x01; // OUTA only break; case 1: channels_bitmask_DCBA = 0x02; // OUTB only break; case 2: channels_bitmask_DCBA = 0x04; // OUTC only break; case 3: channels_bitmask_DCBA = 0x08; // OUTD only break; default: channels_bitmask_DCBA = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0000_nnnn_dddd_dddd_dddd_0000_CODEn | (channel_0_3 & 0x0F); uint16_t regValue = (dacCodeLsbs << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register CODE 0010_nnnn[channel_0_3] // Each bit of channels_bitmask_DCBA maps to an index of g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] if (channels_bitmask_DCBA & (1 << 0)) { CODE[0] = dacCodeLsbs; Shadow_0010_nnnn_CODE[0] = regValue; } if (channels_bitmask_DCBA & (1 << 1)) { CODE[1] = dacCodeLsbs; Shadow_0010_nnnn_CODE[1] = regValue; } if (channels_bitmask_DCBA & (1 << 2)) { CODE[2] = dacCodeLsbs; Shadow_0010_nnnn_CODE[2] = regValue; } if (channels_bitmask_DCBA & (1 << 3)) { CODE[3] = dacCodeLsbs; Shadow_0010_nnnn_CODE[3] = regValue; } } //---------------------------------------- // CMD_1000_0010_dddd_dddd_dddd_0000_CODEallLOADall // // Simultaneously writes data to all CODE registers while updating all DAC registers // @post updates g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] // @post updates g_MAX5815_device.CODE[0..3] void MAX5715::CODEallLOADall(uint16_t dacCodeLsbs) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_1000_0010_dddd_dddd_dddd_0000_CODEallLOADall; uint16_t regValue = (dacCodeLsbs << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register CODE 0010_nnnn[channel_0_3] // Each bit of channels_bitmask_DCBA maps to an index of g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] CODE[0] = dacCodeLsbs; Shadow_0010_nnnn_CODE[0] = regValue; CODE[1] = dacCodeLsbs; Shadow_0010_nnnn_CODE[1] = regValue; CODE[2] = dacCodeLsbs; Shadow_0010_nnnn_CODE[2] = regValue; CODE[3] = dacCodeLsbs; Shadow_0010_nnnn_CODE[3] = regValue; } //---------------------------------------- // CMD_0010_nnnn_dddd_dddd_dddd_0000_CODEnLOADall // // Simultaneously writes data to the selected CODE register(s) while updating all DAC registers. // // @param[in] channel_0_3 = DAC Selection: 0=OUTA, 1=OUTB, 2=OUTC, 3=OUTD, 4..15=ALL OUTA,OUTB,OUTC,OUTD // @post updates g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] // @post updates g_MAX5815_device.CODE[0..3] void MAX5715::CODEnLOADall(uint8_t channel_0_3, uint16_t dacCodeLsbs) { //---------------------------------------- // update channel selection from channel_0_3 channelNumber_0_3 = channel_0_3; switch (channelNumber_0_3) { case 0: channels_bitmask_DCBA = 0x01; // OUTA only break; case 1: channels_bitmask_DCBA = 0x02; // OUTB only break; case 2: channels_bitmask_DCBA = 0x04; // OUTC only break; case 3: channels_bitmask_DCBA = 0x08; // OUTD only break; default: channels_bitmask_DCBA = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0010_nnnn_dddd_dddd_dddd_0000_CODEnLOADall | (channel_0_3 & 0x0F); uint16_t regValue = (dacCodeLsbs << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register CODE 0010_nnnn[channel_0_3] // Each bit of channels_bitmask_DCBA maps to an index of g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] if (channels_bitmask_DCBA & (1 << 0)) { CODE[0] = dacCodeLsbs; Shadow_0010_nnnn_CODE[0] = regValue; } if (channels_bitmask_DCBA & (1 << 1)) { CODE[1] = dacCodeLsbs; Shadow_0010_nnnn_CODE[1] = regValue; } if (channels_bitmask_DCBA & (1 << 2)) { CODE[2] = dacCodeLsbs; Shadow_0010_nnnn_CODE[2] = regValue; } if (channels_bitmask_DCBA & (1 << 3)) { CODE[3] = dacCodeLsbs; Shadow_0010_nnnn_CODE[3] = regValue; } } //---------------------------------------- // CMD_0011_nnnn_dddd_dddd_dddd_0000_CODEnLOADn // // Simultaneously writes data to the selected CODE register(s) while updating selected DAC register(s) // // @param[in] channel_0_3 = DAC Selection: 0=OUTA, 1=OUTB, 2=OUTC, 3=OUTD, 4..15=ALL OUTA,OUTB,OUTC,OUTD // @post updates g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] // @post updates g_MAX5815_device.CODE[0..3] void MAX5715::CODEnLOADn(uint8_t channel_0_3, uint16_t dacCodeLsbs) { //---------------------------------------- // update channel selection from channel_0_3 channelNumber_0_3 = channel_0_3; switch (channelNumber_0_3) { case 0: channels_bitmask_DCBA = 0x01; // OUTA only break; case 1: channels_bitmask_DCBA = 0x02; // OUTB only break; case 2: channels_bitmask_DCBA = 0x04; // OUTC only break; case 3: channels_bitmask_DCBA = 0x08; // OUTD only break; default: channels_bitmask_DCBA = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0011_nnnn_dddd_dddd_dddd_0000_CODEnLOADn | (channel_0_3 & 0x0F); uint16_t regValue = (dacCodeLsbs << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register CODE 0010_nnnn[channel_0_3] // Each bit of channels_bitmask_DCBA maps to an index of g_MAX5815_device.Shadow_0010_nnnn_CODE[0..3] if (channels_bitmask_DCBA & (1 << 0)) { CODE[0] = dacCodeLsbs; Shadow_0010_nnnn_CODE[0] = regValue; } if (channels_bitmask_DCBA & (1 << 1)) { CODE[1] = dacCodeLsbs; Shadow_0010_nnnn_CODE[1] = regValue; } if (channels_bitmask_DCBA & (1 << 2)) { CODE[2] = dacCodeLsbs; Shadow_0010_nnnn_CODE[2] = regValue; } if (channels_bitmask_DCBA & (1 << 3)) { CODE[3] = dacCodeLsbs; Shadow_0010_nnnn_CODE[3] = regValue; } } //---------------------------------------- // CMD_0110_0000_0000_dcba_0000_0000_CONFIGn_LATCHED // // Sets the DAC Latch Mode of the selected DACs. // Only DACS with a 1 in the selection bit are updated by the command. // LD_EN = 0: DAC latch is operational (LOAD and LDAC controlled) // // @param[in] channels_bitmask_DCBA = channel select bitmap // bit 1000 = channel D // bit 0100 = channel C // bit 0010 = channel B // bit 0001 = channel A void MAX5715::CONFIGn_LATCHED(uint8_t channels_bitmask_DCBA) { //---------------------------------------- // update channel selection from channels_bitmask_DCBA channels_bitmask_DCBA = channels_bitmask_DCBA; if (channels_bitmask_DCBA == 0x0F) { channelNumber_0_3 = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } else if ((channels_bitmask_DCBA & 0x01) != 0) { channelNumber_0_3 = 0x00; // OUTA only } else if ((channels_bitmask_DCBA & 0x02) != 0) { channelNumber_0_3 = 0x01; // OUTB only } else if ((channels_bitmask_DCBA & 0x04) != 0) { channelNumber_0_3 = 0x02; // OUTC only } else { channelNumber_0_3 = 0x03; // OUTD only } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0110_0000_0000_dcba_0000_0000_CONFIGn_LATCHED; uint16_t regValue = ((channels_bitmask_DCBA & 0x0F) << 8); // align field 0000_dcba_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0110_0001_0000_dcba_0000_0000_CONFIGn_TRANSPARENT // // Sets the DAC Latch Mode of the selected DACs. // Only DACS with a 1 in the selection bit are updated by the command. // LD_EN = 1: DAC latch is transparent // // @param[in] channels_bitmask_DCBA = channel select bitmap // bit 1000 = channel D // bit 0100 = channel C // bit 0010 = channel B // bit 0001 = channel A void MAX5715::CONFIGn_TRANSPARENT(uint8_t channels_bitmask_DCBA) { //---------------------------------------- // update channel selection from channels_bitmask_DCBA channels_bitmask_DCBA = channels_bitmask_DCBA; if (channels_bitmask_DCBA == 0x0F) { channelNumber_0_3 = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } else if ((channels_bitmask_DCBA & 0x01) != 0) { channelNumber_0_3 = 0x00; // OUTA only } else if ((channels_bitmask_DCBA & 0x02) != 0) { channelNumber_0_3 = 0x01; // OUTB only } else if ((channels_bitmask_DCBA & 0x04) != 0) { channelNumber_0_3 = 0x02; // OUTC only } else { channelNumber_0_3 = 0x03; // OUTD only } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0110_0001_0000_dcba_0000_0000_CONFIGn_TRANSPARENT; uint16_t regValue = ((channels_bitmask_DCBA & 0x0F) << 8); // align field 0000_dcba_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0110_1000_0000_0000_0000_0000_CONFIGall_LATCHED // // Sets the DAC Latch Mode of all DACs. // LD_EN = 0: DAC latch is operational (LOAD and LDAC controlled) void MAX5715::CONFIGall_LATCHED(void) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0110_1000_0000_0000_0000_0000_CONFIGall_LATCHED; uint16_t regValue = 0; // 0000_0000_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0110_1001_0000_0000_0000_0000_CONFIGall_TRANSPARENT // // Sets the DAC Latch Mode of all DACs. // LD_EN = 1: DAC latch is transparent void MAX5715::CONFIGall_TRANSPARENT(void) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0110_1001_0000_0000_0000_0000_CONFIGall_TRANSPARENT; uint16_t regValue = 0; // 0000_0000_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_1000_0001_0000_0000_0000_0000_LOADall // // Updates all DAC latches with current CODE register data void MAX5715::LOADall(void) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_1000_0001_0000_0000_0000_0000_LOADall; uint16_t regValue = 0; // 0000_0000_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0001_nnnn_0000_0000_0000_0000_LOADn // // Transfers data from the selected CODE register(s) to the selected DAC register(s). // // @param[in] channel_0_3 = DAC Selection: 0=OUTA, 1=OUTB, 2=OUTC, 3=OUTD, 4..15=ALL OUTA,OUTB,OUTC,OUTD void MAX5715::LOADn(uint8_t channel_0_3) { //---------------------------------------- // update channel selection from channel_0_3 channelNumber_0_3 = channel_0_3; switch (channelNumber_0_3) { case 0: channels_bitmask_DCBA = 0x01; // OUTA only break; case 1: channels_bitmask_DCBA = 0x02; // OUTB only break; case 2: channels_bitmask_DCBA = 0x04; // OUTC only break; case 3: channels_bitmask_DCBA = 0x08; // OUTD only break; default: channels_bitmask_DCBA = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0001_nnnn_0000_0000_0000_0000_LOADn | (channel_0_3 & 0x0F); uint16_t regValue = (0 << 4); // left-align dddd_dddd_dddd_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0100_0000_0000_dcba_0000_0000_POWERn_Normal // CMD_0100_0001_0000_dcba_0000_0000_POWERn_PD1k // CMD_0100_0010_0000_dcba_0000_0000_POWERn_PD100k // CMD_0100_0011_0000_dcba_0000_0000_POWERn_PDHiZ // // Sets the power mode of the selected DACs // (DACs selected with a 1 in the corresponding DACn bit are updated, // DACs with a 0 in the corresponding DACn bit are not impacted) // // @param[in] channels_bitmask_DCBA = channel select bitmap // bit 1000 = channel D // bit 0100 = channel C // bit 0010 = channel B // bit 0001 = channel A // @param[in] powerValue = power configuration for selected channel void MAX5715::POWER(uint8_t channels_bitmask_DCBA, MAX5715_POWER_enum_t powerValue) { //---------------------------------------- // update channel selection from channels_bitmask_DCBA channels_bitmask_DCBA = channels_bitmask_DCBA; if (channels_bitmask_DCBA == 0x0F) { channelNumber_0_3 = 0x0F; // ALL OUTA,OUTB,OUTC,OUTD } else if ((channels_bitmask_DCBA & 0x01) != 0) { channelNumber_0_3 = 0x00; // OUTA only } else if ((channels_bitmask_DCBA & 0x02) != 0) { channelNumber_0_3 = 0x01; // OUTB only } else if ((channels_bitmask_DCBA & 0x04) != 0) { channelNumber_0_3 = 0x02; // OUTC only } else { channelNumber_0_3 = 0x03; // OUTD only } //---------------------------------------- // select command_regAddress based on condition uint8_t command_regAddress = CMD_0100_0000_0000_dcba_0000_0000_POWERn_Normal; // diagnostic uint16_t regValue = ((channels_bitmask_DCBA & 0x0F) << 8); // 0000_dcba_0000_0000 // select command_regAddress from list of 4 values, based on condition if (powerValue == POWERn_Normal) { command_regAddress = CMD_0100_0000_0000_dcba_0000_0000_POWERn_Normal; } if (powerValue == POWERn_PD1k) { command_regAddress = CMD_0100_0001_0000_dcba_0000_0000_POWERn_PD1k; } if (powerValue == POWERn_PD100k) { command_regAddress = CMD_0100_0010_0000_dcba_0000_0000_POWERn_PD100k; } if (powerValue == POWERn_PDHiZ) { command_regAddress = CMD_0100_0011_0000_dcba_0000_0000_POWERn_PDHiZ; } //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); } //---------------------------------------- // CMD_0111_0000_0000_0000_0000_0000_REF_EXT // CMD_0111_0001_0000_0000_0000_0000_REF_2V500 // CMD_0111_0010_0000_0000_0000_0000_REF_2V048 // CMD_0111_0011_0000_0000_0000_0000_REF_4V096 // CMD_0111_0100_0000_0000_0000_0000_REF_AlwaysOn_EXT // CMD_0111_0101_0000_0000_0000_0000_REF_AlwaysOn_2V500 // CMD_0111_0110_0000_0000_0000_0000_REF_AlwaysOn_2V048 // CMD_0111_0111_0000_0000_0000_0000_REF_AlwaysOn_4V096 // // Sets the reference operating mode. // REF Power (B18): 0 = Internal reference is only powered if at least one DAC is powered // 1 = Internal reference is always powered void MAX5715::REF(MAX5715_REF_enum_t ref) { //---------------------------------------- // select command_regAddress based on condition uint8_t command_regAddress = CMD_0111_0110_0000_0000_0000_0000_REF_AlwaysOn_2V048; // diagnostic uint16_t regValue = 0; // 0000_0000_0000_0000 // select command_regAddress from list of 8 values, based on condition if (ref == REF_EXT) { command_regAddress = CMD_0111_0000_0000_0000_0000_0000_REF_EXT; } if (ref == REF_2V500) { command_regAddress = CMD_0111_0001_0000_0000_0000_0000_REF_2V500; VRef = 2.500; } if (ref == REF_2V048) { command_regAddress = CMD_0111_0010_0000_0000_0000_0000_REF_2V048; VRef = 2.048; } if (ref == REF_4V096) { command_regAddress = CMD_0111_0011_0000_0000_0000_0000_REF_4V096; VRef = 4.096; } if (ref == REF_AlwaysOn_EXT) { command_regAddress = CMD_0111_0100_0000_0000_0000_0000_REF_AlwaysOn_EXT; } if (ref == REF_AlwaysOn_2V500) { command_regAddress = CMD_0111_0101_0000_0000_0000_0000_REF_AlwaysOn_2V500; VRef = 2.500; } if (ref == REF_AlwaysOn_2V048) { command_regAddress = CMD_0111_0110_0000_0000_0000_0000_REF_AlwaysOn_2V048; VRef = 2.048; } if (ref == REF_AlwaysOn_4V096) { command_regAddress = CMD_0111_0111_0000_0000_0000_0000_REF_AlwaysOn_4V096; VRef = 4.096; } //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // shadow of write-only register REF CMD_0111_0rrr Shadow_0111_0rrr_REF = regValue; } //---------------------------------------- // CMD_0101_0000_0000_0000_0000_0000_SW_CLEAR // // Software Clear // All CODE and DAC registers cleared to their default values. // // @return 1 on success; 0 on failure uint8_t MAX5715::SW_CLEAR(void) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0101_0000_0000_0000_0000_0000_SW_CLEAR; uint16_t regValue = 0; // 0000_0000_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // after successful SW_RESET, update shadow registers // assume SPI write was successful if (1) { // shadow of write-only register CODE[channel_0_3] CMD_0010_nnnn Shadow_0010_nnnn_CODE[0] = 0x0000; Shadow_0010_nnnn_CODE[1] = 0x0000; Shadow_0010_nnnn_CODE[2] = 0x0000; Shadow_0010_nnnn_CODE[3] = 0x0000; // // shadow of write-only register POWER[channel_0_3] CMD_0100_00pp //Shadow_0100_00pp_POWER[0] = POWERn_Normal; //Shadow_0100_00pp_POWER[1] = POWERn_Normal; //Shadow_0100_00pp_POWER[2] = POWERn_Normal; //Shadow_0100_00pp_POWER[3] = POWERn_Normal; // // shadow of write-only register CONFIG[channel_0_3] CMD_0110_a00t //Shadow_0110_a00t_CONFIG[0] = 0; // normal (latched, not transparent) //Shadow_0110_a00t_CONFIG[1] = 0; // normal (latched, not transparent) //Shadow_0110_a00t_CONFIG[2] = 0; // normal (latched, not transparent) //Shadow_0110_a00t_CONFIG[3] = 0; // normal (latched, not transparent) // // shadow of write-only register REF CMD_0111_0rrr //Shadow_0111_0rrr_REF = REF_EXT; // // shadow of CODE field of write-only register CODE[channel_0_3] CMD_0010_nnnn CODE[0] = 0x0000; CODE[1] = 0x0000; CODE[2] = 0x0000; CODE[3] = 0x0000; // } //---------------------------------------- // success return 1; } //---------------------------------------- // CMD_0101_0001_0000_0000_0000_0000_SW_RESET // // Software Reset // All CODE, DAC, and control registers returned to their default values, // simulating a power cycle reset. // // @return 1 on success; 0 on failure uint8_t MAX5715::SW_RESET(void) { //---------------------------------------- // Define command code uint8_t command_regAddress = CMD_0101_0001_0000_0000_0000_0000_SW_RESET; uint16_t regValue = 0; // 0000_0000_0000_0000 //---------------------------------------- // SPI write 8-bit regAddress and 16-bit regValue // int16_t mosiData16 = ((command_regAddress << 8) & 0xFF00) | ((regValue >> 8) & 0xFF); // int8_t mosiData8_0000FF = (regValue & 0xFF); SPIoutputCS(0); SPIwrite24bits(command_regAddress, regValue); SPIoutputCS(1); //---------------------------------------- // after successful SW_RESET, update shadow registers // assume SPI write was successful if (1) { // shadow of write-only register CODE[channel_0_3] CMD_0010_nnnn Shadow_0010_nnnn_CODE[0] = 0x0000; Shadow_0010_nnnn_CODE[1] = 0x0000; Shadow_0010_nnnn_CODE[2] = 0x0000; Shadow_0010_nnnn_CODE[3] = 0x0000; // // shadow of write-only register POWER[channel_0_3] CMD_0100_00pp Shadow_0100_00pp_POWER[0] = POWERn_Normal; Shadow_0100_00pp_POWER[1] = POWERn_Normal; Shadow_0100_00pp_POWER[2] = POWERn_Normal; Shadow_0100_00pp_POWER[3] = POWERn_Normal; // // shadow of write-only register CONFIG[channel_0_3] CMD_0110_a00t Shadow_0110_a00t_CONFIG[0] = 0; // normal (latched, not transparent) Shadow_0110_a00t_CONFIG[1] = 0; // normal (latched, not transparent) Shadow_0110_a00t_CONFIG[2] = 0; // normal (latched, not transparent) Shadow_0110_a00t_CONFIG[3] = 0; // normal (latched, not transparent) // // shadow of write-only register REF CMD_0111_0rrr Shadow_0111_0rrr_REF = REF_EXT; // // shadow of CODE field of write-only register CODE[channel_0_3] CMD_0010_nnnn CODE[0] = 0x0000; CODE[1] = 0x0000; CODE[2] = 0x0000; CODE[3] = 0x0000; // } //---------------------------------------- // success return 1; } // End of file