Commit 71488635 authored by Federico Vaga's avatar Federico Vaga

lib: convert raw DAC offset into uV offset

The library was not converting back the offset from the DAC raw value to
uV as expected by the API. This bug was masked by a previously fixed bug.

   143b17 lib: bugfix do not override value on write

Beware that the offset gets approximated to a 16bit number withing the
range [-5V, 4.999V]. This means that most of the time the read back is
not exactly what was configured but its hardware approximation (~152uV
steps).
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
Reported-by: 's avatarNicolas Magnin <nicolas.magnin@cern.ch>
parent 1143b17d
......@@ -592,6 +592,8 @@ class PyFmcAdc100m14b4ch(PyAdcAbstract):
ADC_CONF_100M14B4CHA_FSM_STATE_POST = 4
ADC_CONF_100M14B4CHA_FSM_STATE_DECR = 5
ADC_CONF_100M14B4CHA_DAC_VREF_uV = 5000000
def __init__(self, devid):
super(PyFmcAdc100m14b4ch, self).__init__(devid)
self.__dbg_path = "/sys/kernel/debug/fmc-adc-100m.{:d}.auto/".format(self.dev_id)
......
......@@ -472,7 +472,7 @@ static int adc_100m14b4cha_config_acq(struct adc_dev *adc,
/**
* Convert offset value from microVolt to raw
* @param[in] offset value in micro Volt
* @param[in] value_uv value in micro Volt
*
* @return offset raw value
*/
......@@ -483,6 +483,20 @@ static uint32_t __offset_uv_to_raw(uint32_t value_uv)
return (0x8000LL * (value_uv_s + ADC_100M14B4CHA_DAC_VREF_uV))/ADC_100M14B4CHA_DAC_VREF_uV;
}
/**
* Convert offset value from raw to microVolt
* @param[in] value_raw raw value
*
* @return offset in micro Volt
*/
static uint32_t __offset_raw_to_uv(uint32_t value_raw)
{
int32_t value_raw_s = (int32_t)value_raw;
return (value_raw_s * (ADC_100M14B4CHA_DAC_VREF_uV / 0x8000LL)) - ADC_100M14B4CHA_DAC_VREF_uV;
}
#define ADC_100M14B4CHA_MAX_CHN_SRC FA100M14B4C_NCHAN
/**
* It configures the options related to the channel
......@@ -537,15 +551,32 @@ static int adc_100m14b4cha_config_chn(struct adc_dev *adc,
return -1;
}
err = adc_param[direction](adc, path, NULL, (int *)&value_tmp);
if (!err && direction == ADC_CONF_SET &&
index == ADC_CONF_CHN_RANGE) {
/*
* Whenever the user changes voltage range we need to adjust
* the zero-offset value (if any)
*/
return adc_100m14b4cha_offset_zero_set(adc);
if (err)
return err;
if (direction == ADC_CONF_SET) {
switch(index) {
case ADC_CONF_CHN_RANGE:
/*
* Whenever the user changes voltage range we need to adjust
* the zero-offset value (if any)
*/
err = adc_100m14b4cha_offset_zero_set(adc);
break;
default:
break;
}
}
if (direction == ADC_CONF_GET) {
switch(index) {
case ADC_CONF_CHN_OFFSET:
case __ADC_CONF_CHN_OFFSET_ZERO:
*value = __offset_raw_to_uv(value_tmp);
break;
default:
*value = value_tmp;
break;
}
}
return err;
}
......
......@@ -82,7 +82,9 @@ class TestAdcGetterSetterChannel(object):
assert int(termination) == conf.value_get(PyAdcConf.ADC_CONF_CHN_TERMINATION)
assert int(termination) == conf_rb.value_get(PyAdcConf.ADC_CONF_CHN_TERMINATION)
@pytest.mark.parametrize("offset", range(-5000000, 4999999 + 1, 100000))
@pytest.mark.parametrize("offset", [-5000152] +
list(range(-PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV,
PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV - 1, 100000)))
@pytest.mark.parametrize("channel", range(4))
def test_adc_offset(self, adc100m14b4cha, offset, channel):
"""Test that we can read/write offset on all channels"""
......@@ -94,13 +96,23 @@ class TestAdcGetterSetterChannel(object):
conf_rb = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_CHN, channel)
conf_rb.mask_set(PyAdcConf.ADC_CONF_CHN_OFFSET)
adc100m14b4cha.retrieve_config(conf_rb)
assert offset == conf_rb.value_get(PyAdcConf.ADC_CONF_CHN_OFFSET)
assert offset == conf.value_get(PyAdcConf.ADC_CONF_CHN_OFFSET)
@pytest.mark.parametrize("offset", [-5000001, 5000000])
assert ctypes.c_uint32(offset).value == conf.value_get(PyAdcConf.ADC_CONF_CHN_OFFSET)
step = PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV / 0x8000
offset_rb = ctypes.c_int32(conf_rb.value_get(PyAdcConf.ADC_CONF_CHN_OFFSET)).value
assert abs(offset - offset_rb) <= step
@pytest.mark.parametrize("offset", [-5000153, ] +
list(range(-PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV * 2,
-PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV -153,
1000000))
+ list(range(PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV,
PyFmcAdc100m14b4ch.ADC_CONF_100M14B4CHA_DAC_VREF_uV * 2,
1000000)))
@pytest.mark.parametrize("channel", range(4))
def test_adc_offset_invalid(self, adc100m14b4cha, offset, channel):
"""Test that we can read/write offset on all channels"""
"""Test that we can read/write offset on all channels.
Due to approximation the range [-5000152 uV, -5000001 uV]
is treaded as -5000000 uV: hance, a valid value"""
conf = PyAdcConf(PyAdcConf.ADC_CONF_TYPE_CHN, channel)
conf.value_set(PyAdcConf.ADC_CONF_CHN_OFFSET, offset)
assert conf.value_get(PyAdcConf.ADC_CONF_CHN_OFFSET) == ctypes.c_uint32(offset).value
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment