finished implementing comedi_set_calibration() (untested)
This commit is contained in:
parent
45c3292e6d
commit
e36d2e5b3a
3 changed files with 160 additions and 30 deletions
|
@ -50,7 +50,7 @@ typedef struct comedi_sv_struct{
|
|||
/* range policy */
|
||||
int range;
|
||||
int aref;
|
||||
|
||||
|
||||
/* number of measurements to average (for ai) */
|
||||
int n;
|
||||
|
||||
|
@ -153,7 +153,7 @@ int comedi_sv_update(comedi_sv_t *it);
|
|||
int comedi_sv_measure(comedi_sv_t *it,double *data);
|
||||
|
||||
/* streaming I/O (commands) */
|
||||
|
||||
|
||||
int comedi_get_cmd_src_mask(comedi_t *dev,unsigned int subdevice,
|
||||
comedi_cmd *cmd);
|
||||
int comedi_get_cmd_generic_timed(comedi_t *dev,unsigned int subdevice,
|
||||
|
@ -193,6 +193,8 @@ int comedi_get_rangetype(comedi_t *it,unsigned int subdevice,
|
|||
compatibility. In practice, this is a holding place for the next
|
||||
library ABI version change.
|
||||
*/
|
||||
int comedi_set_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel,
|
||||
unsigned int range, unsigned int aref, const char *cal_file_path);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
181
lib/calib.c
181
lib/calib.c
|
@ -23,27 +23,29 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <comedilib.h>
|
||||
#include <libinternal.h>
|
||||
|
||||
static int ph_extract_element( const char *file_path, const char *element,
|
||||
char *result, unsigned int result_size )
|
||||
static int extract_ph_element( const char *file_path, const char *hash_ref,
|
||||
const char *element, char *result, unsigned int result_size )
|
||||
{
|
||||
char perl_prog[ 1024 ];
|
||||
FILE *perl_stdout;
|
||||
int retval;
|
||||
|
||||
snprintf( perl_prog, sizeof( perl_prog ),
|
||||
"perl -e '"
|
||||
"use strict;"
|
||||
"use warnings;"
|
||||
"my $hash;"
|
||||
"my $cal;"
|
||||
"$hash = `cat %s`;"
|
||||
"eval \"\\$cal = $hash;\";"
|
||||
"print $cal->%s;"
|
||||
"'",
|
||||
file_path, element );
|
||||
"perl -e '
|
||||
use strict;
|
||||
use warnings;
|
||||
my $hash;
|
||||
my $%s;
|
||||
$hash = `cat %s`;
|
||||
eval \"\\$%s = $hash;\";
|
||||
print %s;
|
||||
'",
|
||||
hash_ref, file_path, hash_ref, element );
|
||||
|
||||
perl_stdout = popen( perl_prog, "r");
|
||||
if( perl_stdout == NULL )
|
||||
|
@ -68,37 +70,160 @@ static int ph_extract_element( const char *file_path, const char *element,
|
|||
return 0;
|
||||
}
|
||||
|
||||
//EXPORT_SYMBOL(comedi_set_calibration,0.7.20);
|
||||
int comedi_set_calibration( comedi_t *dev, const char *cal_file_path,
|
||||
unsigned int subdev, unsigned int channel, unsigned int range, unsigned int aref )
|
||||
static int check_cal_file( comedi_t *dev, const char *file_path )
|
||||
{
|
||||
char result[ 100 ];
|
||||
int retval;
|
||||
|
||||
retval = extract_ph_element( file_path, "cal", "cal->{driver_name}",
|
||||
result, sizeof( result ) );
|
||||
if( retval < 0 ) return retval;
|
||||
|
||||
if( strcmp( comedi_get_driver_name( dev ), result ) )
|
||||
{
|
||||
fprintf( stderr, "driver name does not match calibration file\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = extract_ph_element( file_path, "cal", "cal->{board_name}",
|
||||
result, sizeof( result ) );
|
||||
if( retval < 0 ) return retval;
|
||||
|
||||
if( strcmp( comedi_get_board_name( dev ), result ) )
|
||||
{
|
||||
fprintf( stderr, "board name does not match calibration file\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int num_calibrations( const char *file_path )
|
||||
{
|
||||
int retval;
|
||||
char result[ 100 ];
|
||||
|
||||
retval = extract_ph_element( file_path, "cal", "scalar( @{$cal->{calibrations}} )",
|
||||
result, sizeof( result ) );
|
||||
if( retval < 0 ) return retval;
|
||||
|
||||
return strtol( result, NULL, 0 );
|
||||
}
|
||||
|
||||
static int extract_array_element( const char *file_path, unsigned int cal_index,
|
||||
const char *array_name, unsigned int array_index )
|
||||
{
|
||||
char element[ 100 ];
|
||||
char result[ 100 ];
|
||||
int retval;
|
||||
|
||||
snprintf( element, sizeof( element ),
|
||||
"cal->{ calibrations }[ %i ]->{ %s }[ %i ]", cal_index, array_name, array_index );
|
||||
retval = extract_ph_element( file_path, "cal", element, result, sizeof( result ) );
|
||||
if( retval < 0 ) return retval;
|
||||
|
||||
return strtol( result, NULL, 0 );
|
||||
}
|
||||
|
||||
static int extract_array_length( const char *file_path, unsigned int cal_index,
|
||||
const char *array_name )
|
||||
{
|
||||
char result[ 100 ];
|
||||
char element[ 100 ];
|
||||
int retval;
|
||||
|
||||
snprintf( element, sizeof( element ),
|
||||
"scalar( @{ cal->{ calibrations }[ %i ]->{ %s } } )", cal_index, array_name );
|
||||
retval = extract_ph_element( file_path, "cal", element, result, sizeof( result ) );
|
||||
if( retval < 0 ) return 0;
|
||||
|
||||
return strtol( result, NULL, 0 );
|
||||
}
|
||||
|
||||
static int valid_item( const char *file_path, unsigned int cal_index,
|
||||
const char *item_type, unsigned int item )
|
||||
{
|
||||
int num_items, i;
|
||||
|
||||
num_items = extract_array_length( file_path, cal_index, item_type );
|
||||
if( num_items < 0 ) return 0;
|
||||
if( num_items == 0 ) return 1;
|
||||
for( i = 0; i < num_items; i++ )
|
||||
{
|
||||
if( extract_array_element( file_path, cal_index, item_type, i ) == item )
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int valid_range( const char *file_path, unsigned int cal_index,
|
||||
unsigned int range )
|
||||
{
|
||||
return valid_item( file_path, cal_index, "ranges", range );
|
||||
}
|
||||
|
||||
static inline int valid_channel( const char *file_path, unsigned int cal_index,
|
||||
unsigned int channel )
|
||||
{
|
||||
return valid_item( file_path, cal_index, "channels", channel );
|
||||
}
|
||||
|
||||
static inline int valid_aref( const char *file_path, unsigned int cal_index,
|
||||
unsigned int aref )
|
||||
{
|
||||
return valid_item( file_path, cal_index, "arefs", aref );
|
||||
}
|
||||
|
||||
static int find_calibration( const char *file_path, unsigned int channel,
|
||||
unsigned int range, unsigned int aref )
|
||||
{
|
||||
int num_cals, i;
|
||||
|
||||
num_cals = num_calibrations( file_path );
|
||||
if( num_cals < 0 ) return num_cals;
|
||||
|
||||
for( i = 0; i < num_cals; i++ )
|
||||
{
|
||||
if( valid_range( file_path, i, range ) == 0 ) continue;
|
||||
if( valid_channel( file_path, i, channel ) == 0 ) continue;
|
||||
if( valid_aref( file_path, i, aref ) == 0 ) continue;
|
||||
break;
|
||||
}
|
||||
if( i == num_cals ) return -1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(comedi_set_calibration,0.7.20);
|
||||
int comedi_set_calibration( comedi_t *dev, unsigned int subdev, unsigned int channel,
|
||||
unsigned int range, unsigned int aref, const char *cal_file_path )
|
||||
{
|
||||
struct stat file_stats;
|
||||
FILE *cal_file;
|
||||
char file_path[ 1024 ];
|
||||
int retval;
|
||||
int cal_index;
|
||||
|
||||
if( cal_file_path )
|
||||
cal_file = fopen( cal_file_path, "r" );
|
||||
else
|
||||
{
|
||||
char *file_path;
|
||||
|
||||
strncpy( file_path, cal_file_path, sizeof( file_path ) );
|
||||
}else
|
||||
{
|
||||
if( fstat( comedi_fileno( dev ), &file_stats ) < 0 )
|
||||
{
|
||||
fprintf( stderr, "failed to get file stats of comedi device file\n" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
asprintf( &file_path, "/etc/comedi/calibrations/%s_0x%lx",
|
||||
snprintf( file_path, sizeof( file_path ), "/etc/comedi/calibrations/%s_0x%lx",
|
||||
comedi_get_board_name( dev ),
|
||||
( unsigned long ) file_stats.st_ino );
|
||||
cal_file = fopen( file_path, "r" );
|
||||
free( file_path );
|
||||
}
|
||||
|
||||
if( cal_file == NULL )
|
||||
{
|
||||
fprintf( stderr, "failed to open calibration file\n" );
|
||||
return -1;
|
||||
}
|
||||
retval = check_cal_file( dev, file_path );
|
||||
if( retval < 0 ) return retval;
|
||||
|
||||
cal_index = find_calibration( file_path, channel, range, aref );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,3 +18,6 @@ v0.7.19 {
|
|||
|
||||
} v0.7.18;
|
||||
|
||||
v0.7.20 {
|
||||
|
||||
} v0.7.19;
|
||||
|
|
Loading…
Add table
Reference in a new issue