From: Frank Mori Hess Date: Thu, 7 Sep 2006 19:09:04 +0000 (+0000) Subject: Added some primative support for using software calibration in a way X-Git-Tag: v0_8_0~59 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1421d0919ea6790f5bc08110fa764b365b4eb82d;p=comedilib.git Added some primative support for using software calibration in a way that can be integrated with boards that don't use software calibrations. --- diff --git a/include/comedilib.h b/include/comedilib.h index 446b9af..37dda01 100644 --- a/include/comedilib.h +++ b/include/comedilib.h @@ -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 diff --git a/lib/calib.c b/lib/calib.c index 87fc634..c43d672 100644 --- a/lib/calib.c +++ b/lib/calib.c @@ -22,6 +22,8 @@ #define _GNU_SOURCE +#include +#include #include #include #include @@ -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)); +} diff --git a/lib/version_script b/lib/version_script index c00eec1..84755e5 100644 --- a/lib/version_script +++ b/lib/version_script @@ -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;