Added some primative support for using software calibration in a way
that can be integrated with boards that don't use software calibrations.
This commit is contained in:
parent
881600a31e
commit
1421d0919e
3 changed files with 121 additions and 2 deletions
|
@ -205,7 +205,7 @@ typedef struct
|
|||
unsigned int channel;
|
||||
unsigned int value;
|
||||
} comedi_caldac_t;
|
||||
#define COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS (4)
|
||||
#define COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS 4
|
||||
typedef struct
|
||||
{
|
||||
double coefficients[COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS];
|
||||
|
@ -248,7 +248,24 @@ void comedi_cleanup_calibration( comedi_calibration_t *calibration );
|
|||
int comedi_apply_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel,
|
||||
unsigned int range, unsigned int aref, const char *cal_file_path);
|
||||
|
||||
|
||||
/* New stuff to provide conversion between integers and physical values that
|
||||
* can support software calibrations. */
|
||||
enum comedi_conversion_direction
|
||||
{
|
||||
COMEDI_TO_PHYSICAL,
|
||||
COMEDI_FROM_PHYSICAL
|
||||
};
|
||||
int comedi_get_softcal_converter(
|
||||
unsigned subdevice, unsigned channel, unsigned range,
|
||||
enum comedi_conversion_direction direction,
|
||||
const comedi_calibration_t *calibration, comedi_polynomial_t* polynomial);
|
||||
int comedi_get_hardcal_converter(
|
||||
comedi_t *dev, unsigned subdevice, unsigned channel, unsigned range,
|
||||
enum comedi_conversion_direction direction, comedi_polynomial_t* polynomial);
|
||||
double comedi_to_physical(lsampl_t data,
|
||||
const comedi_polynomial_t *conversion_polynomial);
|
||||
lsampl_t comedi_from_physical(double data,
|
||||
const comedi_polynomial_t *conversion_polynomial);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
98
lib/calib.c
98
lib/calib.c
|
@ -22,6 +22,8 @@
|
|||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -242,3 +244,99 @@ int _comedi_apply_calibration( comedi_t *dev, unsigned int subdev, unsigned int
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
EXPORT_ALIAS_DEFAULT(_comedi_get_hardcal_converter, comedi_get_hardcal_converter, 0.7.23);
|
||||
int _comedi_get_hardcal_converter(
|
||||
comedi_t *dev, unsigned subdevice, unsigned channel, unsigned range,
|
||||
enum comedi_conversion_direction direction,
|
||||
comedi_polynomial_t* polynomial)
|
||||
{
|
||||
comedi_range *range_ptr = comedi_get_range(dev, subdevice, channel, range);
|
||||
if(range_ptr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
lsampl_t maxdata = comedi_get_maxdata(dev, subdevice, channel);
|
||||
if(maxdata == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
polynomial->order = 1;
|
||||
switch(direction)
|
||||
{
|
||||
case COMEDI_TO_PHYSICAL:
|
||||
polynomial->expansion_origin = 0.;
|
||||
polynomial->coefficients[0] = range_ptr->min;
|
||||
polynomial->coefficients[1] = (range_ptr->max - range_ptr->min) / maxdata;
|
||||
break;
|
||||
case COMEDI_FROM_PHYSICAL:
|
||||
polynomial->expansion_origin = range_ptr->min;
|
||||
polynomial->coefficients[0] = 0.;
|
||||
polynomial->coefficients[1] = maxdata / (range_ptr->max - range_ptr->min);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_ALIAS_DEFAULT(_comedi_get_softcal_converter, comedi_get_softcal_converter, 0.7.23);
|
||||
int _comedi_get_softcal_converter(
|
||||
unsigned subdevice, unsigned channel, unsigned range,
|
||||
enum comedi_conversion_direction direction,
|
||||
const comedi_calibration_t *calibration, comedi_polynomial_t* polynomial)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < calibration->num_settings; ++i)
|
||||
{
|
||||
if(calibration->settings[i].subdevice != subdevice) continue;
|
||||
if(valid_channel(calibration, i, channel) == 0) continue;
|
||||
if(valid_range(calibration, i, range) == 0) continue;
|
||||
switch(direction)
|
||||
{
|
||||
case COMEDI_TO_PHYSICAL:
|
||||
if(calibration->settings[i].soft_calibration.to_phys == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*polynomial = *calibration->settings[i].soft_calibration.to_phys;
|
||||
break;
|
||||
case COMEDI_FROM_PHYSICAL:
|
||||
if(calibration->settings[i].soft_calibration.from_phys == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*polynomial = *calibration->settings[i].soft_calibration.from_phys;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static double apply_polynomial(const comedi_polynomial_t *polynomial, double input)
|
||||
{
|
||||
double value = 0.;
|
||||
double term = 1.;
|
||||
unsigned i;
|
||||
assert(polynomial->order < COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS);
|
||||
for(i = 0; i <= polynomial->order; ++i)
|
||||
{
|
||||
value += polynomial->coefficients[i] * term;
|
||||
term *= input - polynomial->expansion_origin;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
EXPORT_ALIAS_DEFAULT(_comedi_to_physical, comedi_to_physical, 0.7.23);
|
||||
double _comedi_to_physical(lsampl_t data,
|
||||
const comedi_polynomial_t *conversion_polynomial)
|
||||
{
|
||||
return apply_polynomial(conversion_polynomial, data);
|
||||
}
|
||||
|
||||
EXPORT_ALIAS_DEFAULT(_comedi_from_physical, comedi_from_physical, 0.7.23);
|
||||
lsampl_t _comedi_from_physical(double data,
|
||||
const comedi_polynomial_t *conversion_polynomial)
|
||||
{
|
||||
return nearbyint(apply_polynomial(conversion_polynomial, data));
|
||||
}
|
||||
|
|
|
@ -83,7 +83,11 @@ v0.7.20 {
|
|||
|
||||
v0.7.23 {
|
||||
global:
|
||||
comedi_from_physical;
|
||||
comedi_dio_get_config;
|
||||
comedi_get_hardcal_converter;
|
||||
comedi_get_softcal_converter;
|
||||
comedi_get_subdevice_flags;
|
||||
comedi_mark_buffer_written;
|
||||
comedi_to_physical;
|
||||
} v0.7.20;
|
||||
|
|
Loading…
Add table
Reference in a new issue