https://github.com/j123b567/scpi-parser
Dependents: scpi_sx127x scpi_sx127x_firstTest MLX90418_I2C_master
units.c
00001 /*- 00002 * Copyright (c) 2012-2013 Jan Breuer, 00003 * 00004 * All Rights Reserved 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are 00008 * met: 00009 * 1. Redistributions of source code must retain the above copyright notice, 00010 * this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00018 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 00019 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00020 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00021 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 00022 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00023 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 00024 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 /** 00029 * @file scpi_units.c 00030 * @date Thu Nov 15 10:58:45 UTC 2012 00031 * 00032 * @brief SCPI units 00033 * 00034 * 00035 */ 00036 00037 #include <string.h> 00038 #include "scpi/parser.h" 00039 #include "scpi/units.h" 00040 #include "utils_private.h" 00041 #include "scpi/utils.h" 00042 #include "scpi/error.h" 00043 #include "lexer_private.h" 00044 00045 00046 /* 00047 * multipliers IEEE 488.2-1992 tab 7-2 00048 * 1E18 EX 00049 * 1E15 PE 00050 * 1E12 T 00051 * 1E9 G 00052 * 1E6 MA (use M for OHM and HZ) 00053 * 1E3 K 00054 * 1E-3 M (disaalowed for OHM and HZ) 00055 * 1E-6 U 00056 * 1E-9 N 00057 * 1E-12 P 00058 * 1E-15 F 00059 * 1E-18 A 00060 */ 00061 00062 /* 00063 * units definition IEEE 488.2-1992 tab 7-1 00064 */ 00065 const scpi_unit_def_t scpi_units_def[] = { 00066 /* voltage */ 00067 {/* name */ "UV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-6}, 00068 {/* name */ "MV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-3}, 00069 {/* name */ "V", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1}, 00070 {/* name */ "KV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e3}, 00071 00072 /* current */ 00073 {/* name */ "UA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-6}, 00074 {/* name */ "MA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-3}, 00075 {/* name */ "A", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1}, 00076 {/* name */ "KA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e3}, 00077 00078 /* resistance */ 00079 {/* name */ "OHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1}, 00080 {/* name */ "KOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e3}, 00081 {/* name */ "MOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e6}, 00082 00083 /* frequency */ 00084 {/* name */ "HZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1}, 00085 {/* name */ "KHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e3}, 00086 {/* name */ "MHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e6}, 00087 {/* name */ "GHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e9}, 00088 00089 /* temperature */ 00090 {/* name */ "CEL", /* unit */ SCPI_UNIT_CELSIUS, /* mult */ 1}, 00091 00092 /* time */ 00093 {/* name */ "PS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-12}, 00094 {/* name */ "NS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-9}, 00095 {/* name */ "US", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-6}, 00096 {/* name */ "MS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-3}, 00097 {/* name */ "S", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1}, 00098 {/* name */ "MIN", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 60}, 00099 {/* name */ "HR", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 3600}, 00100 00101 SCPI_UNITS_LIST_END, 00102 }; 00103 00104 /* 00105 * Special number values definition 00106 */ 00107 const scpi_choice_def_t scpi_special_numbers_def[] = { 00108 {/* name */ "MINimum", /* type */ SCPI_NUM_MIN}, 00109 {/* name */ "MAXimum", /* type */ SCPI_NUM_MAX}, 00110 {/* name */ "DEFault", /* type */ SCPI_NUM_DEF}, 00111 {/* name */ "UP", /* type */ SCPI_NUM_UP}, 00112 {/* name */ "DOWN", /* type */ SCPI_NUM_DOWN}, 00113 {/* name */ "NAN", /* type */ SCPI_NUM_NAN}, 00114 {/* name */ "INFinity", /* type */ SCPI_NUM_INF}, 00115 {/* name */ "NINF", /* type */ SCPI_NUM_NINF}, 00116 {/* name */ "AUTO", /* type */ SCPI_NUM_AUTO}, 00117 SCPI_CHOICE_LIST_END, 00118 }; 00119 00120 /** 00121 * Convert string describing unit to its representation 00122 * @param units units patterns 00123 * @param unit text representation of unknown unit 00124 * @param len length of text representation 00125 * @return pointer of related unit definition or NULL 00126 */ 00127 static const scpi_unit_def_t * translateUnit(const scpi_unit_def_t * units, const char * unit, size_t len) { 00128 int i; 00129 00130 if (units == NULL) { 00131 return NULL; 00132 } 00133 00134 for (i = 0; units[i].name != NULL; i++) { 00135 if (compareStr(unit, len, units[i].name, strlen(units[i].name))) { 00136 return &units[i]; 00137 } 00138 } 00139 00140 return NULL; 00141 } 00142 00143 /** 00144 * Convert unit definition to string 00145 * @param units units definitions (patterns) 00146 * @param unit type of unit 00147 * @return string representation of unit 00148 */ 00149 static const char * translateUnitInverse(const scpi_unit_def_t * units, const scpi_unit_t unit) { 00150 int i; 00151 00152 if (units == NULL) { 00153 return NULL; 00154 } 00155 00156 for (i = 0; units[i].name != NULL; i++) { 00157 if ((units[i].unit == unit) && (units[i].mult == 1)) { 00158 return units[i].name; 00159 } 00160 } 00161 00162 return NULL; 00163 } 00164 00165 /** 00166 * Transform number to base units 00167 * @param context 00168 * @param unit text representation of unit 00169 * @param len length of text representation 00170 * @param value preparsed numeric value 00171 * @return TRUE if value parameter was converted to base units 00172 */ 00173 static scpi_bool_t transformNumber(scpi_t * context, const char * unit, size_t len, scpi_number_t * value) { 00174 size_t s; 00175 const scpi_unit_def_t * unitDef; 00176 s = skipWhitespace(unit, len); 00177 00178 if (s == len) { 00179 value->unit = SCPI_UNIT_NONE; 00180 return TRUE; 00181 } 00182 00183 unitDef = translateUnit(context->units, unit + s, len - s); 00184 00185 if (unitDef == NULL) { 00186 SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SUFFIX); 00187 return FALSE; 00188 } 00189 00190 value->value *= unitDef->mult; 00191 value->unit = unitDef->unit; 00192 00193 return TRUE; 00194 } 00195 00196 /** 00197 * Parse parameter as number, number with unit or special value (min, max, default, ...) 00198 * @param context 00199 * @param value return value 00200 * @param mandatory if the parameter is mandatory 00201 * @return 00202 */ 00203 scpi_bool_t SCPI_ParamNumber(scpi_t * context, const scpi_choice_def_t * special, scpi_number_t * value, scpi_bool_t mandatory) 00204 { 00205 scpi_token_t token; 00206 lex_state_t state; 00207 scpi_parameter_t param; 00208 scpi_bool_t result; 00209 int32_t tag; 00210 00211 if (!value) { 00212 SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); 00213 return FALSE; 00214 } 00215 00216 result = SCPI_Parameter(context, ¶m, mandatory); 00217 00218 if (!result) { 00219 return result; 00220 } 00221 00222 state.buffer = param.ptr; 00223 state.pos = state.buffer; 00224 state.len = param.len; 00225 00226 switch(param.type) { 00227 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: 00228 case SCPI_TOKEN_HEXNUM: 00229 case SCPI_TOKEN_OCTNUM: 00230 case SCPI_TOKEN_BINNUM: 00231 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: 00232 case SCPI_TOKEN_PROGRAM_MNEMONIC: 00233 value->unit = SCPI_UNIT_NONE; 00234 value->special = FALSE; 00235 result = TRUE; 00236 break; 00237 } 00238 00239 switch(param.type) { 00240 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: 00241 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: 00242 case SCPI_TOKEN_PROGRAM_MNEMONIC: 00243 value->base = 10; 00244 break; 00245 case SCPI_TOKEN_BINNUM: 00246 value->base = 2; 00247 break; 00248 case SCPI_TOKEN_HEXNUM: 00249 value->base = 16; 00250 break; 00251 case SCPI_TOKEN_OCTNUM: 00252 value->base = 8; 00253 break; 00254 } 00255 00256 switch(param.type) { 00257 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: 00258 SCPI_ParamToDouble(context, ¶m, &(value->value)); 00259 break; 00260 case SCPI_TOKEN_HEXNUM: 00261 SCPI_ParamToDouble(context, ¶m, &(value->value)); 00262 break; 00263 case SCPI_TOKEN_OCTNUM: 00264 SCPI_ParamToDouble(context, ¶m, &(value->value)); 00265 break; 00266 case SCPI_TOKEN_BINNUM: 00267 SCPI_ParamToDouble(context, ¶m, &(value->value)); 00268 break; 00269 case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: 00270 scpiLex_DecimalNumericProgramData(&state, &token); 00271 scpiLex_WhiteSpace(&state, &token); 00272 scpiLex_SuffixProgramData(&state, &token); 00273 00274 SCPI_ParamToDouble(context, ¶m, &(value->value)); 00275 00276 result = transformNumber(context, token.ptr, token.len, value); 00277 break; 00278 case SCPI_TOKEN_PROGRAM_MNEMONIC: 00279 scpiLex_WhiteSpace(&state, &token); 00280 scpiLex_CharacterProgramData(&state, &token); 00281 00282 /* convert string to special number type */ 00283 SCPI_ParamToChoice(context, &token, special, &tag); 00284 00285 value->special = TRUE; 00286 value->tag = tag; 00287 00288 break; 00289 default: 00290 result = FALSE; 00291 } 00292 00293 return result; 00294 } 00295 00296 /** 00297 * Convert scpi_number_t to string 00298 * @param context 00299 * @param value number value 00300 * @param str target string 00301 * @param len max length of string 00302 * @return number of chars written to string 00303 */ 00304 size_t SCPI_NumberToStr(scpi_t * context, const scpi_choice_def_t * special, scpi_number_t * value, char * str, size_t len) { 00305 const char * type; 00306 const char * unit; 00307 size_t result; 00308 00309 if (!value || !str) { 00310 return 0; 00311 } 00312 00313 if (value->special) { 00314 if (SCPI_ChoiceToName(special, value->tag, &type)) { 00315 strncpy(str, type, len); 00316 return min(strlen(type), len); 00317 } else { 00318 str[0] = 0; 00319 return 0; 00320 } 00321 } 00322 00323 result = SCPI_DoubleToStr(value->value, str, len); 00324 00325 unit = translateUnitInverse(context->units, value->unit); 00326 00327 if (unit) { 00328 strncat(str, " ", len); 00329 strncat(str, unit, len); 00330 result += strlen(unit) + 1; 00331 } 00332 00333 return result; 00334 }
Generated on Tue Jul 12 2022 19:30:15 by 1.7.2