From d686d1278fd8f16511b4298f1a045ba9037ec119 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Tue, 22 Aug 2006 18:14:22 +0000 Subject: [PATCH] First pass at parsing additional calibration file elements which support software calibration. --- include/comedilib.h | 13 ++++++ lib/Makefile.am | 8 ++-- lib/calib_lex.l | 32 +++++++++------ lib/calib_yacc.y | 96 +++++++++++++++++++++++++++++++++++++++++++-- lib/libinternal.h | 7 ++-- 5 files changed, 132 insertions(+), 24 deletions(-) diff --git a/include/comedilib.h b/include/comedilib.h index b4905b5..446b9af 100644 --- a/include/comedilib.h +++ b/include/comedilib.h @@ -205,6 +205,18 @@ typedef struct unsigned int channel; unsigned int value; } comedi_caldac_t; +#define COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS (4) +typedef struct +{ + double coefficients[COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS]; + double expansion_origin; + unsigned order; +} comedi_polynomial_t; +typedef struct +{ + comedi_polynomial_t *to_phys; + comedi_polynomial_t *from_phys; +} comedi_softcal_t; #define CS_MAX_AREFS_LENGTH 4 typedef struct { @@ -217,6 +229,7 @@ typedef struct unsigned int num_arefs; comedi_caldac_t *caldacs; unsigned int num_caldacs; + comedi_softcal_t soft_calibration; } comedi_calibration_setting_t; typedef struct diff --git a/lib/Makefile.am b/lib/Makefile.am index 8162f21..5964842 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -7,7 +7,7 @@ CLEANFILES = grammar.output EXTRA_DIST = calib_lex.l calib_yacc.y version_script -BUILT_SOURCES = calib_lex.c calib_yacc.c calib_yacc.h +BUILT_SOURCES = calib_lex.c calib_lex.h calib_yacc.c calib_yacc.h libcomedi_la_SOURCES = \ buffer.c calib.c cmd.c comedi.c data.c dio.c error.c \ @@ -22,9 +22,9 @@ libcomedi_la_LDFLAGS = -soname libcomedi \ -Wl,--version-script=$(srcdir)/version_script -$(srcdir)/calib_yacc.c + $(srcdir)/calib_yacc.h: $(srcdir)/calib_yacc.y +$(srcdir)/calib_yacc.c $(srcdir)/calib_yacc.h: $(srcdir)/calib_yacc.y $(YACC) -d -p calib_yy -o $(srcdir)/calib_yacc.c $< -$(srcdir)/calib_lex.c: $(srcdir)/calib_lex.l - $(LEX) -Pcalib_yy -o$@ $< +$(srcdir)/calib_lex.c $(srcdir)/calib_lex.h: $(srcdir)/calib_lex.l + $(LEX) --header-file=$(srcdir)/calib_lex.h -Pcalib_yy -o$(srcdir)/calib_lex.c $< diff --git a/lib/calib_lex.l b/lib/calib_lex.l index ba018e4..a3e9335 100644 --- a/lib/calib_lex.l +++ b/lib/calib_lex.l @@ -1,5 +1,7 @@ %option noyywrap %option nounput +%option yylineno +%option reentrant %{ @@ -7,7 +9,7 @@ lib/calib_lex.l code for parsing calibration file, generated by flex - Copyright (C) 2003 Frank Mori Hess This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -36,21 +38,17 @@ %% -%{ - calib_llocp->first_line = 1; -%} - -\n { calib_llocp->first_line++; } +\n "#" { BEGIN(COMMENT); } -\n { calib_llocp->first_line++; BEGIN(INITIAL); } +\n {BEGIN(INITIAL); } . \" { BEGIN(STRING); } [^\"]*\" { - if( strlen( calib_yytext ) > 0 ) - calib_yytext[ strlen( calib_yytext ) - 1 ] = 0; - calib_lvalp->sval = calib_yytext; + if(strlen(calib_yyget_text(yyscanner)) > 0) + calib_yyget_text(yyscanner)[strlen(calib_yyget_text(yyscanner)) - 1] = 0; + calib_lvalp->sval = calib_yyget_text(yyscanner); BEGIN(INITIAL); return ( T_STRING ); } @@ -65,14 +63,24 @@ arefs { return ( T_AREFS ); } caldacs { return ( T_CALDACS ); } channel { return ( T_CHANNEL ); } value { return ( T_VALUE ); } +coefficients {return (T_COEFFICIENTS);} +expansion_origin {return (T_EXPANSION_ORIGIN);} +softcal_to_phys {return T_SOFTCAL_TO_PHYS;} +softcal_from_phys {return T_SOFTCAL_FROM_PHYS;} => { return ( T_ASSIGN ); }; -(0[xX])?(00)?[0-9a-fA-F]+ { calib_lvalp->ival = strtol( calib_yytext, NULL, 0 ); +(0[xX])?(00)?[0-9a-fA-F]+ {calib_lvalp->ival = strtol(calib_yyget_text(yyscanner), NULL, 0); return( T_NUMBER ); } +[0-9]+\.*[0-9]* { calib_lvalp->dval = strtod(calib_yyget_text(yyscanner), 0); + return( T_FLOAT ); } + +[0-9]*\.*[0-9]+ { calib_lvalp->dval = strtod(calib_yyget_text(yyscanner), 0); + return( T_FLOAT ); } + [ \t] -. { return( calib_yytext[0] ); } +. {return(calib_yyget_text(yyscanner)[0]);} %% diff --git a/lib/calib_yacc.y b/lib/calib_yacc.y index c017e63..1417f68 100644 --- a/lib/calib_yacc.y +++ b/lib/calib_yacc.y @@ -26,15 +26,27 @@ #include #include #include "calib_yacc.h" +#include "calib_lex.h" #define YYERROR_VERBOSE #define YYPARSE_PARAM parse_arg +#define YYLEX_PARAM priv(YYPARSE_PARAM)->yyscanner + +enum polynomial_direction +{ + POLYNOMIAL_TO_PHYS, + POLYNOMIAL_FROM_PHYS +}; typedef struct { + yyscan_t yyscanner; comedi_calibration_t *parsed_file; comedi_caldac_t caldac; int cal_index; + enum polynomial_direction polynomial_direction; + unsigned num_coefficients; + comedi_polynomial_t polynomial; } calib_yyparse_private_t; YY_DECL; @@ -65,6 +77,16 @@ static void free_calibration_setting( comedi_calibration_setting_t *setting ) setting->caldacs = NULL; setting->num_caldacs = 0; } + if(setting->soft_calibration.to_phys) + { + free(setting->soft_calibration.to_phys); + setting->soft_calibration.to_phys = NULL; + } + if(setting->soft_calibration.from_phys) + { + free(setting->soft_calibration.from_phys); + setting->soft_calibration.from_phys = NULL; + } } static void free_settings( comedi_calibration_t *file_contents ) @@ -168,6 +190,27 @@ static int add_caldac( calib_yyparse_private_t *priv, return 0; } +static int add_polynomial(calib_yyparse_private_t *priv) +{ + comedi_calibration_setting_t *setting; + + setting = current_setting( priv ); + if( setting == NULL ) return -1; + if(priv->num_coefficients < 1) return -1; + if(priv->polynomial_direction == POLYNOMIAL_TO_PHYS) + { + if(setting->soft_calibration.to_phys) return -1; + setting->soft_calibration.to_phys = malloc(sizeof(comedi_polynomial_t)); + *setting->soft_calibration.to_phys = priv->polynomial; + }else + { + if(setting->soft_calibration.from_phys) return -1; + setting->soft_calibration.from_phys = malloc(sizeof(comedi_polynomial_t)); + *setting->soft_calibration.from_phys = priv->polynomial; + } + return 0; +} + static comedi_calibration_t* alloc_calib_parse( void ) { comedi_calibration_t *file_contents; @@ -193,7 +236,6 @@ extern void _comedi_cleanup_calibration( comedi_calibration_t *file_contents ) } free_settings( file_contents ); free( file_contents ); - file_contents = NULL; } EXPORT_ALIAS_DEFAULT(_comedi_parse_calibration_file,comedi_parse_calibration_file,0.7.20); @@ -203,7 +245,7 @@ extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_fil FILE *file; if( cal_file_path == NULL ) return NULL; - + priv.parsed_file = alloc_calib_parse(); if( priv.parsed_file == NULL ) return NULL; priv.cal_index = 0; @@ -214,12 +256,14 @@ extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_fil COMEDILIB_DEBUG( 3, "failed to open file\n" ); return NULL; } - calib_yyrestart( file ); + calib_yylex_init(&priv.yyscanner); + calib_yyrestart(file, priv.yyscanner); if( calib_yyparse( &priv ) ) { comedi_cleanup_calibration( priv.parsed_file ); priv.parsed_file = NULL; } + calib_yylex_destroy(priv.yyscanner); fclose( file ); return priv.parsed_file; } @@ -231,15 +275,18 @@ extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_fil %union { int ival; + double dval; char *sval; } %token T_DRIVER_NAME T_BOARD_NAME T_CALIBRATIONS T_SUBDEVICE T_CHANNELS %token T_RANGES T_AREFS T_CALDACS T_CHANNEL T_VALUE T_NUMBER T_STRING -%token T_ASSIGN +%token T_COEFFICIENTS T_EXPANSION_ORIGIN T_SOFTCAL_TO_PHYS T_SOFTCAL_FROM_PHYS +%token T_ASSIGN T_FLOAT %type T_NUMBER %type T_STRING +%type T_FLOAT %% @@ -290,6 +337,14 @@ extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_fil | T_RANGES T_ASSIGN '[' ranges_array ']' | T_AREFS T_ASSIGN '[' arefs_array ']' | T_CALDACS T_ASSIGN '[' caldacs_array ']' + | T_SOFTCAL_TO_PHYS T_ASSIGN '{' polynomial '}' + { + priv(parse_arg)->polynomial_direction = POLYNOMIAL_TO_PHYS; + } + | T_SOFTCAL_FROM_PHYS T_ASSIGN '{' polynomial '}' + { + priv(parse_arg)->polynomial_direction = POLYNOMIAL_FROM_PHYS; + } ; channels_array: /* empty */ @@ -331,6 +386,39 @@ extern comedi_calibration_t* _comedi_parse_calibration_file( const char *cal_fil | T_VALUE T_ASSIGN T_NUMBER { priv(parse_arg)->caldac.value = $3; } ; + polynomial: /* empty */ { add_polynomial(parse_arg);} + | polynomial_element { add_polynomial(parse_arg);} + | polynomial_element ',' polynomial + ; + + polynomial_element: T_COEFFICIENTS T_ASSIGN '[' coefficient_array ']' {priv(parse_arg)->num_coefficients = 0;} + | T_EXPANSION_ORIGIN T_ASSIGN expansion_origin + ; + + coefficient_array: /* empty */ + | coefficient + | coefficient ',' coefficient_array + ; + + coefficient: T_FLOAT + { + if(priv(parse_arg)->num_coefficients >= COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS) + { + fprintf(stderr, "too many coefficients for polynomial on line %i ,\n", @1.first_line ); + fprintf(stderr, "max is %i .\n", COMEDI_MAX_NUM_POLYNOMIAL_COEFFICIENTS); + YYABORT; + } + priv(parse_arg)->polynomial.order = priv(parse_arg)->num_coefficients; + priv(parse_arg)->polynomial.coefficients[priv(parse_arg)->num_coefficients++] = $1; + } + ; + + expansion_origin: T_FLOAT + { + priv(parse_arg)->polynomial.expansion_origin = $1; + } + ; + %% void calib_yyerror(char *s) diff --git a/lib/libinternal.h b/lib/libinternal.h index 539cbce..dc209c9 100644 --- a/lib/libinternal.h +++ b/lib/libinternal.h @@ -152,10 +152,9 @@ enum{ /* used by range.c, was in comedilib.h but apparently deprecated so I put it here - fmhess */ int comedi_get_rangetype(comedi_t *it,unsigned int subdevice,unsigned int chan); -#define YY_DECL int calib_yylex( YYSTYPE *calib_lvalp, YYLTYPE *calib_llocp ) -void calib_yyerror( char *s ); -int calib_yyparse( void *parse_arg ); -void calib_yyrestart( FILE *input ); +#define YY_DECL int calib_yylex(YYSTYPE *calib_lvalp, YYLTYPE *calib_llocp, yyscan_t yyscanner) +void calib_yyerror(char *s); +int calib_yyparse(void *parse_arg); #endif -- 2.26.2