Maxim Integrated 7-bit Sink/Source Current DAC. DS4424, DS4422 input/output current Digital-to-Analog Converter Driver/library code.

Dependents:   DS4424_Hello_Current_DAC_on_MAX32630FTHR

DS4424.cpp

Committer:
phonemacro
Date:
2019-01-23
Revision:
5:fc75fced724f
Parent:
4:3824afaf0d61

File content as of revision 5:fc75fced724f:

/*******************************************************************************
 * Copyright (C) 2018-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.
 *******************************************************************************
 */
 
#include "DS4424.h"
/* #include "USBSerial.h" */
#define DS4424_U8_MAX     ((uint8_t)~0U)
#define DS4424_S8_MAX     ((int8_t)(DS4424_U8_MAX>>1))
#define DS4424_S8_MIN     ((int8_t)(-DS4424_S8_MAX - 1))

/*
 * DS4424 DAC control register 8 bits
 * [7]      0: to sink; 1: to source
 * [6:0]    steps to sink/source
 * bit[7] looks like a sign bit, but the value of the register is
 * not a two's complement code considering the bit[6:0] is a absolute
 * distance from the zero point.
 */
union ds4424_raw_data {
    struct {
        uint8_t dx:7;
        uint8_t source_bit:1;
    };
    uint8_t bits;
};
 
/******************************************************************************/
DS4424::DS4424(I2C &i2c_bus, DS4424_i2c_adrs_t slaveAddress, DS4424_ic_t ic_variant):
m_i2c(i2c_bus), 
m_writeAddress(slaveAddress <<1),
m_readAddress ((slaveAddress << 1) | 1)
{
    switch(ic_variant) {
       case DS4424_IC:
            m_max_ch_reg_addr = REG_OUT3;
            break;
        case DS4422_IC:
            m_max_ch_reg_addr = REG_OUT1;
            break;
        default:
            m_max_ch_reg_addr = REG_OUT3;
            break;
    }
}
 
 
/******************************************************************************/
DS4424::~DS4424(void) 
{
  /** empty block */
}
 
 
/******************************************************************************/
int DS4424::read_raw(int32_t &result, ChannelRegAddr_e chan_addr) 
{
    uint8_t value;
    int ret = DS4424_ERROR;
    union ds4424_raw_data raw;
    
    if (chan_addr >= REG_OUT0 && chan_addr <=  m_max_ch_reg_addr)
        ret = read_register(value, chan_addr);
    if (ret != 0)
        return DS4424_ERROR;
    

    raw.bits = value;
    result = raw.dx;
    if (raw.source_bit == DS4424_SINK_I)  /** Sinking will be negative values */
        result = -result;
    return DS4424_NO_ERROR;

}



/******************************************************************************/
int DS4424::read_hw_raw(uint8_t &result, ChannelRegAddr_e chan_addr) 
{
    uint8_t value;
    int ret = DS4424_ERROR;

    if (chan_addr >= REG_OUT0 && chan_addr <=  m_max_ch_reg_addr)
        ret = read_register(value, chan_addr);
    if (ret != 0)
        return DS4424_ERROR;

    result = value;
    return DS4424_NO_ERROR;
}


/******************************************************************************/
int DS4424::write_raw(int32_t value, ChannelRegAddr_e chan_addr) 
{
    #define U8_MAX     ((uint8_t)~0U)
    #define S8_MAX     ((int8_t)(U8_MAX>>1))
    #define S8_MIN     ((int8_t)(-S8_MAX - 1))
    int ret = DS4424_ERROR;
    union ds4424_raw_data raw;
    
    if ((chan_addr >= REG_OUT0 && chan_addr <=  m_max_ch_reg_addr) &&
        (value >= S8_MIN && value <= S8_MAX)) {
        if (value > 0) {
            raw.source_bit = DS4424_SOURCE_I;
            raw.dx = value;
        } else {
            raw.source_bit = DS4424_SINK_I;
            raw.dx = -value;
        }
        ret = write_register(chan_addr, raw.bits);
 
        if (ret != 0)
            return DS4424_ERROR;
        return DS4424_NO_ERROR;
    } else {
        return DS4424_ERROR;
    }
}



/******************************************************************************/
int DS4424::write_hw_raw(uint8_t value, ChannelRegAddr_e chan_addr) 
{
    int ret = DS4424_ERROR;
    if (chan_addr >= REG_OUT0 && chan_addr <=  m_max_ch_reg_addr) {
        ret = write_register(chan_addr, value);
 
        if (ret != 0)
            return DS4424_ERROR;
        return DS4424_NO_ERROR;
    } else {
        return DS4424_ERROR;
    }
}


/******************************************************************************/
int DS4424::convert_picoAmps_to_hw_raw(uint8_t *val_out,
    int32_t picoAmps, uint32_t rfs_resistor)
{
    uint32_t val, tmp_scale, round_up;
    union ds4424_raw_data raw;

        /*   val can be 0 to 200,000,000 (200 picoAmps)  */
        val = picoAmps;
        raw.source_bit = DS4424_SOURCE_I;
        if (picoAmps < 0) {
            raw.source_bit = DS4424_SINK_I;
            val = -picoAmps;
        }
        if (val > DS4424_MAX_PICOAMPS ||
                rfs_resistor < DS4424_MIN_RFS ||
                rfs_resistor > DS4424_MAX_RFS)
            return DS4424_ERROR;
        rfs_resistor /= 100;
        val = val / 1000;

        tmp_scale = DS4424_IFS_SCALE / 10;
        round_up = tmp_scale / 2;
        val = ((val * rfs_resistor) + round_up) /
            tmp_scale;

        val = val / 100;
        if (val > DS4424_S8_MAX) {
            printf("%s : Requested current %d\r\n",
                __func__, val);
            printf("exceeds maximum. DAC set to maximum %d\n\r\n",
                DS4424_S8_MAX);
            val = DS4424_S8_MAX;
        }
        raw.dx = val;
        *val_out = raw.bits;
        return DS4424_NO_ERROR;

}


/******************************************************************************/
int DS4424::convert_raw_to_picoAmps(int32_t *val_out,
    int8_t raw_in, uint32_t rfs_resistor)
{
    uint32_t round_up;
    union ds4424_raw_data raw;
    if (rfs_resistor < DS4424_MIN_RFS || rfs_resistor > DS4424_MAX_RFS) {
        return DS4424_ERROR;
    }
    rfs_resistor /= 100;

    raw.bits = raw_in;
    *val_out = DS4424_IFS_SCALE * raw.dx * 10;
    round_up = rfs_resistor / 2;
    *val_out = (*val_out + round_up) / rfs_resistor;

    if (raw.source_bit == DS4424_SINK_I)
        *val_out = -*val_out;  /* this routine use negatives if sinking */
    *val_out = *val_out * 1000; /* picoAmps */
    return DS4424_NO_ERROR;
}


/******************************************************************************/
int DS4424::read_register(uint8_t &value, ChannelRegAddr_e reg) 
{
    int32_t ret;
 
    char data = reg;
 
    ret = m_i2c.write(m_writeAddress, &data, sizeof(data));
    if (ret != 0) {
        printf("%s - failed - ret: %d reg: %d data: %d sizeof(data): %d\r\n", __func__, ret, (int)reg, data, sizeof(data));
        return DS4424_ERROR;
    }
 
    ret = m_i2c.read(m_readAddress, &data, sizeof(data));
    if (ret != 0) {
        printf("%s - failed - ret: %d\r\n", __func__, ret);
        return DS4424_ERROR;
    }
 
    value = data;
    return DS4424_NO_ERROR;

}


/******************************************************************************/
int DS4424::write_register(ChannelRegAddr_e reg, uint8_t value)
{
    
    int32_t ret;
 
    char cmdData[] = {static_cast<char>(reg), static_cast<char>(value)};
 
    ret = m_i2c.write(m_writeAddress, cmdData, sizeof(cmdData));

    if (ret != 0)
        return DS4424_ERROR;
 
    return DS4424_NO_ERROR;
}