First pass at parsing additional calibration file elements which
authorFrank Mori Hess <fmhess@speakeasy.net>
Tue, 22 Aug 2006 18:14:22 +0000 (18:14 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Tue, 22 Aug 2006 18:14:22 +0000 (18:14 +0000)
support software calibration.

include/comedilib.h
lib/Makefile.am
lib/calib_lex.l
lib/calib_yacc.y
lib/libinternal.h

index b4905b5109848baf0144a84116afb65e4667aa81..446b9af666ee048304e7a1f5e4dabb318245e42f 100644 (file)
@@ -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
index 8162f2159215be789397573199c6d0ea12ad5f68..5964842df6599188b2637918c1e48f63d676f1fd 100644 (file)
@@ -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 $<
 
index ba018e471621177602bef9491100bfc289a36ea5..a3e933545e5036661971361a514ff1048e954341 100644 (file)
@@ -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 <fmhess@users.sourceforge.net
+    Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
 
 %%
 
-%{
-       calib_llocp->first_line = 1;
-%}
-
-<STRING,INITIAL>\n { calib_llocp->first_line++; }
+<STRING,INITIAL>\n
 
 "#" { BEGIN(COMMENT); }
-<COMMENT>\n { calib_llocp->first_line++; BEGIN(INITIAL); }
+<COMMENT>\n {BEGIN(INITIAL); }
 <COMMENT>.
 
 \" { BEGIN(STRING); }
 <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]);}
 
 
 %%
index c017e633ef7fa2eabaa477188666d6f48cab6cb2..1417f68747f45b5d3860fa056cbfe5cbc5288b10 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #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 <ival> T_NUMBER
 %type <sval> T_STRING
+%type <dval> 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)
index 539cbce801461896172629e205d8f25a77ac6e2f..dc209c9edd6eb53404e7ab63fb6883331c3aa7c0 100644 (file)
@@ -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