#define _GNU_SOURCE
+#include <assert.h>
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
#include "libinternal.h"
static int set_calibration( comedi_t *dev, const comedi_calibration_t *parsed_file,
{
int retval;
+ if(!valid_dev(dev)) return -1;
retval = check_cal_file( dev, calibration );
if( retval < 0 ) return retval;
static void fixup_board_name( char *name )
{
while( ( name = strchr( name, '/' ) ) )
- if( name ) *name = '-';
+ {
+ if( name )
+ {
+ *name = '-';
+ name++;
+ }
+ }
}
EXPORT_ALIAS_DEFAULT(_comedi_get_default_calibration_path,comedi_get_default_calibration_path,0.7.20);
{
struct stat file_stats;
char *file_path;
- char *board_name, *temp;
- char *driver_name;
+ const char *temp;
+ char *board_name;
+ const char *driver_name;
+ int err;
+ if(!valid_dev(dev)) return NULL;
if( fstat( comedi_fileno( dev ), &file_stats ) < 0 )
{
COMEDILIB_DEBUG( 3, "failed to get file stats of comedi device file\n" );
board_name = strdup( temp );
fixup_board_name( board_name );
- asprintf( &file_path, "/etc/comedi/calibrations/%s_%s_comedi%li",
+ err = asprintf( &file_path, LOCALSTATEDIR "/lib/comedi/calibrations/%s_%s_comedi%li",
driver_name, board_name, ( unsigned long ) minor( file_stats.st_rdev ) );
free( board_name );
+ if( err < 0 )
+ {
+ return NULL;
+ }
return file_path;
}
return retval;
}
+
+EXPORT_ALIAS_DEFAULT(_comedi_get_hardcal_converter, comedi_get_hardcal_converter, 0.8.0);
+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);
+ lsampl_t maxdata;
+
+ if(range_ptr == NULL)
+ {
+ return -1;
+ }
+ 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.8.0);
+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.8.0);
+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.8.0);
+lsampl_t _comedi_from_physical(double data,
+ const comedi_polynomial_t *conversion_polynomial)
+{
+ return nearbyint(apply_polynomial(conversion_polynomial, data));
+}