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:
Frank Mori Hess 2006-09-07 19:09:04 +00:00
parent 881600a31e
commit 1421d0919e
3 changed files with 121 additions and 2 deletions

View file

@ -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

View file

@ -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));
}

View file

@ -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;