Added some primative support for using software calibration in a way
authorFrank Mori Hess <fmhess@speakeasy.net>
Thu, 7 Sep 2006 19:09:04 +0000 (19:09 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Thu, 7 Sep 2006 19:09:04 +0000 (19:09 +0000)
that can be integrated with boards that don't use software calibrations.

include/comedilib.h
lib/calib.c
lib/version_script

index 446b9af666ee048304e7a1f5e4dabb318245e42f..37dda01f738ac8f4878393ac87213cd22b2d87b1 100644 (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
 
index 87fc6340484653692c58ecd8f2791a234de0b348..c43d672c19770c47f8825e8b5cc8a883cff54664 100644 (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));
+}
index c00eec1bd6c1830977cd6a748802a3c3a995874c..84755e56180006bc448e439d6e894e70f1eb75dd 100644 (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;