Commit c107af64 authored by Federico Vaga's avatar Federico Vaga

Merge branch 'release/v2.2'

parents f0f1224b 655c0b9f
......@@ -59,9 +59,9 @@ author = 'Federico Vaga <federico.vaga@cern.ch>'
# built documents.
#
# The short X.Y version.
version = '2.1'
version = '2.2'
# The full version, including alpha/beta/rc tags.
release = '2.1.0'
release = '2.2.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -201,4 +201,9 @@ breathe_projects = {
"adc-lib":"doxygen-lib-output/xml/",
}
breathe_projects_source = {
"adc-lib" : ( "../lib/", ["adc-lib.h",
"route.c"])
}
breathe_default_project = "adc-lib"
The Library API
================
Enumerations And Constants
-----------------------------
.. doxygenenum:: adc_supported_boards
.. doxygenenum:: adc_configuration_type
.. doxygenenum:: adc_configuration_trigger_ext
.. doxygenenum:: adc_configuration_trigger_thr
.. doxygenenum:: adc_configuration_acquisition
.. doxygenenum:: adc_configuration_channel
.. doxygenenum:: adc_configuration_board
Board Specific
''''''''''''''
FMC ADC 100M 14 bit 4 Channel
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. doxygenenum:: adc_configuration_100m14b4cha
Data Structures
---------------
.. doxygenstruct:: adc_conf
:members:
.. doxygenstruct:: adc_buffer
:members:
.. doxygenstruct:: adc_timestamp
:members:
Functions
----------
.. doxygenfunction:: adc_init
.. doxygenfunction:: adc_exit
.. doxygenfunction:: adc_strerror
.. doxygenfunction:: adc_open
.. doxygenfunction:: adc_open_by_lun
.. doxygenfunction:: adc_close
.. doxygenfunction:: adc_apply_config
.. doxygenfunction:: adc_retrieve_config
.. doxygenfunction:: adc_set_conf_mask
.. doxygenfunction:: adc_set_conf_mask_all
.. doxygenfunction:: adc_set_conf
.. doxygenfunction:: adc_get_conf
.. doxygenfunction:: adc_reset_conf
.. doxygenfunction:: adc_get_capabilities
.. doxygenfunction:: adc_set_param
.. doxygenfunction:: adc_get_param
.. doxygenfunction:: adc_acq_start
.. doxygenfunction:: adc_acq_poll
.. doxygenfunction:: adc_acq_stop
.. doxygenfunction:: adc_request_buffer
.. doxygenfunction:: adc_release_buffer
.. doxygenfunction:: adc_fill_buffer
.. doxygenfunction:: adc_tstamp_buffer
.. doxygenfunction:: adc_trigger_fire
.. autodoxygenfile:: adc-lib.h
This diff is collapsed.
......@@ -23,6 +23,7 @@ LOBJ += init.o
LOBJ += config-zio.o
LOBJ += buffer-zio.o
LOBJ += lib.o
LOBJ += lib-math.o
LOBJ += adc-ziofake.o
LOBJ += adc-genericfake.o
LOBJ += adc-zio.o
......
......@@ -330,6 +330,20 @@ static int adc_genfake_fill_buffer(struct adc_dev *dev,
return 0;
}
static int adc_genfake_buffer_get_sample(struct adc_buffer *buf,
unsigned int chan,
unsigned int acq_sample,
int32_t *value)
{
if (chan >= 1) {
errno = EINVAL;
return -1;
}
*value = ((int8_t *)buf->data)[acq_sample];
return 0;
}
static struct adc_operations fa_generic_fake_op = {
.open = adc_genfake_open,
......@@ -349,6 +363,7 @@ static struct adc_operations fa_generic_fake_op = {
.fill_buffer = adc_genfake_fill_buffer,
.tstamp_buffer = adc_genfake_tstamp_buffer,
.release_buffer = adc_genfake_release_buffer,
.buffer_get_sample = adc_genfake_buffer_get_sample,
};
#define ADC_GENERICFAKE_BRD_MASK (1LL << ADC_CONF_BRD_N_CHAN)
......
......@@ -23,6 +23,20 @@ extern "C" {
#include "adc-lib.h"
#define ADC_CONF_100M14B4CHA_CHN_RANGE_N 3
/**
* List of known voltage ranges to be used with the configuration option
* ADC_CONF_CHN_RANGE
*/
enum adc_configuration_100m14b4cha_channel_range {
ADC_CONF_100M14B4CHA_CHN_RANGE_OPEN_DRAIN= 0,
ADC_CONF_100M14B4CHA_CHN_RANGE_100mV= 0x23,
ADC_CONF_100M14B4CHA_CHN_RANGE_1V= 0x11,
ADC_CONF_100M14B4CHA_CHN_RANGE_10V= 0x45,
ADC_CONF_100M14B4CHA_CHN_RANGE_100mV_CAL= 0x42,
ADC_CONF_100M14B4CHA_CHN_RANGE_1V_CAL= 0x40,
ADC_CONF_100M14B4CHA_CHN_RANGE_10V_CAL= 0x44,
};
/**
* List of possible buffer types (options for ADC_CONF_100M14B4CHA_BUF_TYPE)
......
......@@ -45,6 +45,9 @@ struct adc_operations {
typeof(adc_release_buffer) *release_buffer; /**< @related adc_release_buffer */
typeof(adc_trigger_fire) *trigger_fire; /**< @related adc_trigger_fire */
typeof(adc_buffer_get_sample) *buffer_get_sample; /**< @related adc_buffer_get_sample */
typeof(adc_buffer_fixup) *buffer_fixup; /**< @related adc_buffer_fixup*/
typeof(adc_offset_auto_clear) *offset_auto_clear; /**< @related adc_offset_auto_clear */
};
......@@ -88,6 +91,7 @@ struct __adc_dev_zio {
char *sysbase; /**< base path to device sysfs */
unsigned long samplesize; /**< size of 1 sample */
unsigned long pagesize; /**< size of 1 page */
void *priv; /**< specific ZIO board data */
/* Mandatory field */
struct adc_gid gid; /**< general ADC descriptor */
};
......@@ -181,6 +185,10 @@ int adc_zio_get_param(struct adc_dev *dev, char *name,
int adc_zio_sysfs_set(struct __adc_dev_zio *fa, char *name,
uint32_t *value);
int adc_offset_auto_clear_sw_avg(struct adc_dev *dev,
unsigned long flags,
int32_t *offset);
/*adc-genericfake*/
......
......@@ -26,6 +26,12 @@ extern "C" {
#define ADC_ENOMASK 1030
#define ADC_EDISABLED 1031
#define ADC_EROUTE 1032
#define ADC_ENOP_SWTRG 1033
#define ADC_ENOP_OFFCLR 1034
#define ADC_ENOP_OFFCLRHW 1035
#define ADC_ENOP_OFFCLRSW 1036
#define ADC_OFF_AC_RESTORE_S 1037
#define ADC_OFF_AC_RESTORE_R 1038
/**
* Opaque type. any instance of this should be used as token
......@@ -64,6 +70,7 @@ struct adc_buffer {
void *mapaddr; /**< mmap address */
unsigned long maplen; /**< mmap length */
unsigned long flags; /**< internal to the library */
void *priv; /**< library private date */
};
......@@ -242,6 +249,13 @@ enum adc_configuration_type {
#define __ADC_CONF_LEN 64 /* number of allocated items in each structure */
/**
* It enumerates all possible flags for adc_conf.flags
*/
enum adc_conf_flags {
ADC_CONF_F_ERROR=(1ULL << 0), /**< configuration failed */
};
/**
* ADC configuration descriptor.
*/
......@@ -250,7 +264,7 @@ struct adc_conf {
uint32_t dev_type; /**< device type */
uint32_t route_to; /**< internal route to a particular sub-device
(e.g. a channel) */
uint32_t flags; /**< FIXME how to identify invalid? */
uint32_t flags; /**< flags from adc_conf_flags */
uint64_t mask; /**< capabilities mask, 1 when the correspondent
value in ``value[]`` is valid */
uint32_t value[__ADC_CONF_LEN]; /**< array of configuration value.
......@@ -265,6 +279,30 @@ struct adc_conf {
(used by adc_open) */
#define ADC_F_VERBOSE 0x00020000 /**< Flag used to verbose on stdout/stderr
(usable by any function)*/
#define ADC_F_FIXUP 0x00400000 /**< Flag used to fixup a buffer when
filling it (usable by adc_fill_buffer) */
/**
* Enumeration of all possible flags to driver the auto-clear offset
*/
enum adc_offset_auto_clear_flags {
ADC_OFFSET_AC_F_MANUAL=0x00000001, /**< the signal will be acquired with
the last configuration set */
ADC_OFFSET_AC_F_RESTORE=0x00000002, /**< restore previous
configuration when done. It
does not have any effect when
MANUAL is active*/
ADC_OFFSET_AC_F_SOFTWARE=0x00000004, /**< use software mechanism,
it implies manual
configuration */
ADC_OFFSET_AC_F_ZERO=0x00000008, /**< it sets the zero-offset to zero;
which means that it removes any
previously set zero-offset. */
__ADC_OFFSET_AC_F_MASK=(ADC_OFFSET_AC_F_MANUAL |
ADC_OFFSET_AC_F_RESTORE |
ADC_OFFSET_AC_F_SOFTWARE |
ADC_OFFSET_AC_F_ZERO), /**< used internally */
};
/**
* @defgroup dev Basic
......@@ -287,6 +325,8 @@ extern struct adc_dev *adc_open_by_lun(char *name, int lun,
extern int adc_close(struct adc_dev *dev);
extern int adc_trigger_fire(struct adc_dev *dev);
extern int adc_has_trigger_fire(struct adc_dev *dev);
extern int adc_offset_auto_clear(struct adc_dev *dev,
unsigned long flags);
/**@}*/
......@@ -357,8 +397,13 @@ extern int adc_reset_conf(struct adc_dev *dev, unsigned int flags,
struct adc_conf *conf);
extern int adc_apply_config(struct adc_dev *dev, unsigned int flags,
struct adc_conf *conf);
extern int adc_apply_config_n(struct adc_dev *dev, unsigned int flags,
struct adc_conf *conf, unsigned int n);
extern int adc_retrieve_config(struct adc_dev *dev,
struct adc_conf *conf);
extern int adc_retrieve_config_n(struct adc_dev *dev,
struct adc_conf *conf,
unsigned int n);
extern uint64_t adc_get_capabilities(struct adc_dev *dev,
enum adc_configuration_type type);
extern int adc_get_param(struct adc_dev *dev, char *name,
......@@ -396,6 +441,21 @@ extern struct adc_timestamp *adc_tstamp_buffer(struct adc_buffer *buf,
extern int adc_release_buffer(struct adc_dev *dev,
struct adc_buffer *buf,
void (*free_fn)(void *));
extern int adc_buffer_get_sample(struct adc_buffer *buf,
unsigned int chan,
unsigned int acq_sample,
int32_t *value);
extern int adc_buffer_fixup(struct adc_buffer *buf);
/**@}*/
/**
* @defgroup buf_math Buffer Math
* Mathematical operations on buffers
* @{
*/
extern int adc_buffer_math_avg(struct adc_buffer *buf,
unsigned int chan,
int32_t *avg);
/**@}*/
/* libfmcadc version string */
......
......@@ -34,6 +34,20 @@ static struct adc_dev *adc_ziofake_open(const struct adc_board_type *b,
return dev;
}
static int adc_ziofake_buffer_get_sample(struct adc_buffer *buf,
unsigned int chan,
unsigned int acq_sample,
int32_t *value)
{
if (chan >= 1) {
errno = EINVAL;
return -1;
}
*value = ((int8_t *)buf->data)[acq_sample];
return 0;
}
#define ADC_ZIO_ACQ_MASK (1LL << ADC_CONF_ACQ_N_SHOTS) | \
(1LL << ADC_CONF_ACQ_POST_SAMP) | \
......@@ -62,6 +76,7 @@ static struct adc_operations fa_zio_fake_op = {
.fill_buffer = adc_zio_fill_buffer,
.tstamp_buffer = adc_zio_tstamp_buffer,
.release_buffer = adc_zio_release_buffer,
.buffer_get_sample = adc_ziofake_buffer_get_sample,
};
struct adc_board_type adc_ziofake = {
......
This diff is collapsed.
/*
* Routing public functions to device-specific code
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <errno.h>
#include <string.h>
#include "adc-lib.h"
#include "adc-lib-int.h"
/**
* It computes the avarege voltage within the given buffer
* @param[in] buf data set to use
* @param[in] chan channel number [0, NCHAN]
* @param[out] avg the computer avarage. The scale depends on the
* configuration,
* @return 0 on success, -1 on error and errno is set appropriately
* EINVAL: if the buffer is invalid, or channel is invalid
*/
int adc_buffer_math_avg(struct adc_buffer *buf,
unsigned int chan,
int32_t *avg)
{
struct adc_conf cfg_brd;
uint32_t nchan = 0;
int i, err;
int64_t total = 0;
memset(&cfg_brd, 0, sizeof(struct adc_conf));
cfg_brd.type = ADC_CONF_TYPE_BRD;
adc_set_conf_mask_all(&cfg_brd, buf->dev);
err = adc_retrieve_config(buf->dev, &cfg_brd);
if (err)
return err;
adc_get_conf(&cfg_brd, ADC_CONF_BRD_N_CHAN, &nchan);
if (chan >= nchan) {
errno = EINVAL;
return -1;
}
for (i = 0; i < buf->nsamples; ++i) {
int32_t val;
err = adc_buffer_get_sample(buf, chan, i, &val);
if (err)
return err;
total += val;
}
*avg = total / buf->nsamples;
return 0;
}
......@@ -9,6 +9,7 @@
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <errno.h>
#include <string.h>
#include "adc-lib.h"
#include "adc-lib-int.h"
......@@ -31,6 +32,12 @@ static struct adc_errors {
{ ADC_ENOMASK, "Missing configuration mask"},
{ ADC_EDISABLED, "Trigger is disabled: I/O aborted"},
{ ADC_EROUTE, "Cannot route correctly the configuration"},
{ADC_ENOP_SWTRG, "Operation not supported: software trigger"},
{ADC_ENOP_OFFCLR, "Operation not supported: offset auto-clear"},
{ADC_ENOP_OFFCLRHW, "Operation not supported: offset auto-clear hardware"},
{ADC_ENOP_OFFCLRSW, "Operation not supported: offset auto-clear software"},
{ADC_OFF_AC_RESTORE_S, "Offset auto-clear: cannot store configuration"},
{ADC_OFF_AC_RESTORE_R, "Offset auto-clear: cannot restore configuration"},
{ 0, }
};
......@@ -86,3 +93,96 @@ uint64_t adc_get_capabilities(struct adc_dev *dev,
return b->board->capabilities[type];
}
/**
* It computes what are the necessary offsets to apply on channels
* in order to clear a constant offset.
* @param[in] dev ADC device token
* @param[in] flags options @see adc_offset_auto_clear_flags
* @param[out] offset vector of compensation offsets (one for each channel)
* @return 0 on success, -1 on error and errno is set appropriately
* EINVAL: invalid flags value
* ADC_ENOP_SWTRG: when software trigger is missing
*
* The configuration is board dependent, so here we just run and apply
* the compensation offset. The configuration is left to the user.
*
* Since this function uses software trigger, the user should disable
* all trigger sources except the software one.
*
* NOTE: offset is a vector, so when you call this function be careful
* about the size of that parameter, it must big enough to host a value
* for each board channel.
*/
int adc_offset_auto_clear_sw_avg(struct adc_dev *dev,
unsigned long flags,
int32_t *offset)
{
struct adc_conf cfg;
struct adc_buffer *buf;
struct timeval tv = {0, 0};
uint32_t nchan, pre, post;
int err, err_stop, i;
unsigned int nsamples;
if (!(flags & ADC_OFFSET_AC_F_SOFTWARE)) {
errno = EINVAL;
return -1;
}
if (!adc_has_trigger_fire(dev)) {
errno = ADC_ENOP_SWTRG;
return -1;
}
memset(&cfg, 0, sizeof(struct adc_conf));
cfg.type = ADC_CONF_TYPE_ACQ;
adc_set_conf_mask(&cfg, ADC_CONF_ACQ_PRE_SAMP);
adc_set_conf_mask(&cfg, ADC_CONF_ACQ_POST_SAMP);
err = adc_retrieve_config(dev, &cfg);
if (err)
return err;
adc_get_conf(&cfg, ADC_CONF_ACQ_PRE_SAMP, &pre);
adc_get_conf(&cfg, ADC_CONF_ACQ_POST_SAMP, &post);
nsamples = pre + post;
memset(&cfg, 0, sizeof(struct adc_conf));
cfg.type = ADC_CONF_TYPE_BRD;
adc_set_conf_mask(&cfg, ADC_CONF_BRD_N_CHAN);
err = adc_retrieve_config(dev, &cfg);
if (err)
return err;
adc_get_conf(&cfg, ADC_CONF_BRD_N_CHAN, &nchan);
buf = adc_request_buffer(dev, nsamples, NULL, 0);
if (!buf)
return -1;
err = adc_acq_start(dev, ADC_F_FLUSH, &tv);
if (err)
goto out;
err = adc_trigger_fire(dev);
if (err)
goto out;
tv.tv_sec = 10;
err = adc_fill_buffer(dev, buf, 0, &tv);
if (err)
goto out;
for (i = 0; i < nchan; ++i) {
err = adc_buffer_math_avg(buf, i, &offset[i]);
if (err)
goto out;
}
out:
adc_release_buffer(dev, buf, NULL);
err_stop = adc_acq_stop(dev, 0);
if (err_stop)
return err_stop;
return err;
}
......@@ -75,6 +75,8 @@ static const struct adc_board_type *find_board(char *name)
* It should be passed around but not be looked into.
*
* @todo Open should choose the buffer type
*
* It initialize the board, this can be different board to board.
*/
struct adc_dev *adc_open(char *name, unsigned int dev_id,
unsigned long totalsamples,
......@@ -254,13 +256,19 @@ int adc_acq_stop(struct adc_dev *dev, unsigned int flags)
* @param[in] flags
* @param[in] conf configuration to apply
* @return 0 on success, -1 on error and errno is set appropriately
*
* If the configuration cannot be applied entirely, then this function
* will set ADC_CONF_F_ERROR in conf->flags
*/
int adc_apply_config(struct adc_dev *dev, unsigned int flags,
struct adc_conf *conf)
struct adc_conf *conf)
{
struct adc_gid *g = (struct adc_gid *)dev;
const struct adc_board_type *b = g->board;
uint64_t cap_mask;
int err;
conf->flags &= ~ADC_CONF_F_ERROR;
if (!b->adc_op->apply_config) {
errno = ADC_ENOP;
......@@ -282,9 +290,40 @@ int adc_apply_config(struct adc_dev *dev, unsigned int flags,
errno = ADC_ENOCAP;
return -1;
}
return b->adc_op->apply_config(dev, flags, conf);
err = b->adc_op->apply_config(dev, flags, conf);
if (err)
conf->flags |= ADC_CONF_F_ERROR;
return err;
}
/**
* It applies the given configuration to the device
* @param[in] dev ADC device token
* @param[in] flags
* @param[in] conf list of configurations to apply
* @param[in] n number of valid configurations in conf
* @return 0 on success, -1 on error and errno is set appropriately
*
* If a configuration cannot be applied entirely, then this function
* will set ADC_CONF_F_ERROR in conf[i].flags
*/
int adc_apply_config_n(struct adc_dev *dev, unsigned int flags,
struct adc_conf *conf, unsigned int n)
{
unsigned int i;
int err_last = 0;
for (i = 0; i < n; ++i) {
int err = adc_apply_config(dev, flags, &conf[i]);
if (err) {
err_last = err;
continue;
}
}
return err_last;
}
/**
* It retrieve the current device configuration
......@@ -292,12 +331,18 @@ int adc_apply_config(struct adc_dev *dev, unsigned int flags,
* @param[in,out] conf configuration descriptor to fill with configuration
* values.
* @return 0 on success, -1 on error and errno is set appropriately
*
* If the configuration cannot be retrieved entirely, then this function
* will set ADC_CONF_F_ERROR in conf->flags
*/
int adc_retrieve_config(struct adc_dev *dev, struct adc_conf *conf)
{
struct adc_gid *g = (struct adc_gid *)dev;
const struct adc_board_type *b = g->board;
uint64_t cap_mask;
int err;
conf->flags &= ~ADC_CONF_F_ERROR;
if (!b->adc_op->retrieve_config) {
errno = ADC_ENOP;
......@@ -319,9 +364,39 @@ int adc_retrieve_config(struct adc_dev *dev, struct adc_conf *conf)
errno = ADC_ENOCAP;
return -1;
}
return b->adc_op->retrieve_config(dev, conf);
err = b->adc_op->retrieve_config(dev, conf);
if (err)
conf->flags |= ADC_CONF_F_ERROR;
return err;
}
/**
* It retrieve the current device configuration
* @param[in] dev ADC device token
* @param[in,out] conf configuration descriptor to fill with configuration
* values.
* @param[in] n number of valid configurations in conf
* @return 0 on success, -1 on error and errno is set appropriately
*
* If a configuration cannot be retrieved entirely, then this function
* will set ADC_CONF_F_ERROR in conf[i].flags
*/
int adc_retrieve_config_n(struct adc_dev *dev, struct adc_conf *conf,
unsigned int n)
{
unsigned int i;
int err_last = 0;
for (i = 0; i < n; ++i) {
int err = adc_retrieve_config(dev, &conf[i]);
if (err) {
err_last = err;
continue;
}
}
return err_last;
}
/**
* It get a single parameter from the device
......@@ -402,6 +477,7 @@ struct adc_buffer *adc_request_buffer(struct adc_dev *dev,
* @param[in] dev ADC device token
* @param[in] buf the buffer to fill
* @param[in] flags used to control how to fill the buffer
* (ADC_F_FIXUP)
* @param[in] timeout maximum time to fill the buffer. The behavior
* is similar to *select(1)*. If NULL, there is no timeout and
* the function will wait until the data is ready.
......@@ -419,13 +495,21 @@ int adc_fill_buffer(struct adc_dev *dev,
{
struct adc_gid *g = (struct adc_gid *)dev;
const struct adc_board_type *b = g->board;
int err;
if (!b->adc_op->fill_buffer) {
errno = ADC_ENOP;
return -1;
}
return b->adc_op->fill_buffer(dev, buf, flags, timeout);
err = b->adc_op->fill_buffer(dev, buf, flags, timeout);
if (err)
return err;
if (flags & ADC_F_FIXUP)
return adc_buffer_fixup(buf);
return 0;
}
......@@ -499,6 +583,7 @@ int adc_has_trigger_fire(struct adc_dev *dev)
* It forces the board to trigger the acquisition
* @param[in] dev ADC device token
* @return 0 on success, -1 on error and errno is set appropriately
* ADC_ENOP_SWTRG: when software trigger is not supported
*/
int adc_trigger_fire(struct adc_dev *dev)
{
......@@ -506,8 +591,101 @@ int adc_trigger_fire(struct adc_dev *dev)
const struct adc_board_type *b = g->board;
if (!b->adc_op->trigger_fire) {
errno = ADC_ENOP;
errno = ADC_ENOP_SWTRG;
return -1;
}
return b->adc_op->trigger_fire(dev);
}
/**
* It gets a sample from the buffer
* @param[in] buf buffer to use
* @param[in] chan which channel
* @param[in] acq_sample acquisition sample
* @param[out] value
* @return 0 on success, -1 on error and errno is set appropriately
* ADC_ENOP if the operation is not supported by the board that
* acquired the buffer
*/
int adc_buffer_get_sample(struct adc_buffer *buf,
unsigned int chan,
unsigned int acq_sample,
int32_t *value)
{
struct adc_gid *g = (struct adc_gid *)buf->dev;
const struct adc_board_type *b = g->board;
if (!b->adc_op->buffer_get_sample) {
errno = ADC_ENOP;
return -1;
}
if (acq_sample >= buf->nsamples) {
errno = EINVAL;
return -1;
}
return b->adc_op->buffer_get_sample(buf, chan, acq_sample, value);
}
/**
* It fixes the given buffer if there is any need
* @param[in, out] buf acquistion buffer (filled)
* @return 0 on success, -1 on error and errno is set appropriately
*
* This is used by board specifc code to compensate some known error
*/
int adc_buffer_fixup(struct adc_buffer *buf)
{
struct adc_gid *g = (struct adc_gid *)buf->dev;
const struct adc_board_type *b = g->board;
if (b->adc_op->buffer_fixup)
return b->adc_op->buffer_fixup(buf);
return 0;
}
/**
* It checks if the board support offset auto-clear
* @param[in] dev ADC device token
* @return 1 when it does support offset auto clear; 0 when it does not
*/
int adc_has_offset_auto_clear(struct adc_dev *dev)
{
struct adc_gid *g = (struct adc_gid *)dev;
const struct adc_board_type *b = g->board;
return !!b->adc_op->offset_auto_clear;
}
/**
* It clears eventual offsets on all channel
* @param[in] dev ADC device token
* @param[in] flags options @see adc_offset_auto_clear_flags
* @return 0 on success, -1 on error and errno is set appropriately
* EINVAL: invalid flags value
* ADC_ENOP_OFFCLR: when offset auto-clear is not supported
*
* NOTE: The function may overwrite your current configuration (unless
* you use a flag) and it may remove any trace of previous acquisitions.
*
* Offset configuration is always overwritten (no matter what flag you use)
*/
int adc_offset_auto_clear(struct adc_dev *dev,
unsigned long flags)
{
struct adc_gid *g = (struct adc_gid *)dev;
const struct adc_board_type *b = g->board;
if (!adc_has_offset_auto_clear(dev)) {
errno = ADC_ENOP_OFFCLR;
return -1;
}
if (flags & ~__ADC_OFFSET_AC_F_MASK) {
errno = EINVAL;
return -1;
}
return b->adc_op->offset_auto_clear(dev, flags);
}
This diff is collapsed.
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