From 59d4618036c85dafc9026d0f84ab00fcb900acc9 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周三, 23 10月 2013 21:46:41 +0800 Subject: [PATCH] merge functionality from 'master' branch --- .gitignore | 1 libscpi/inc/scpi/error.h | 10 ++- libscpi/inc/scpi/types.h | 1 libscpi/src/ieee488.c | 13 +++- libscpi/src/minimal.c | 2 libscpi/src/parser.c | 52 +++++++++++++++-- libscpi/src/units.c | 29 ++++----- libscpi/inc/scpi/parser.h | 3 + libscpi/inc/scpi/constants.h | 16 ++++- examples/common/scpi-def.c | 34 ++++++++++- 10 files changed, 124 insertions(+), 37 deletions(-) diff --git a/.gitignore b/.gitignore index ab6d275..cdb9024 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ *.out *.app *.test +examples/*/test # Backup files *~ diff --git a/examples/common/scpi-def.c b/examples/common/scpi-def.c index 782445a..cdfee2d 100644 --- a/examples/common/scpi-def.c +++ b/examples/common/scpi-def.c @@ -89,7 +89,7 @@ return SCPI_RES_OK; } -scpi_result_t SCPI_TestBool(scpi_t * context) { +scpi_result_t TEST_Bool(scpi_t * context) { scpi_parameter_t param1; fprintf(stderr, "TEST:BOOL\r\n"); // debug command name @@ -103,6 +103,30 @@ return SCPI_RES_OK; } +const char * trigger_source[] = { + "BUS", + "IMMediate", + "EXTernal", + NULL /* termination of option list */ +}; + + +scpi_result_t TEST_ChoiceQ(scpi_t * context) { + scpi_parameter_t param1; + int32_t result; + + if (!SCPI_Parameter(context, ¶m1, true)) { + return SCPI_RES_ERR; + } + + result = SCPI_ParamGetChoiceVal(context, ¶m1, trigger_source); + + fprintf(stderr, "\tP1=%s (%d)\r\n", result >= 0 ? trigger_source[result] : "", result); + + SCPI_ResultInt(context, result); + + return SCPI_RES_OK; +} static const scpi_command_t scpi_commands[] = { /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */ @@ -149,10 +173,11 @@ {.pattern = "MEASure:FRESistance?", .callback = SCPI_StubQ,}, {.pattern = "MEASure:FREQuency?", .callback = SCPI_StubQ,}, {.pattern = "MEASure:PERiod?", .callback = SCPI_StubQ,}, - + {.pattern = "SYSTem:COMMunication:TCPIP:CONTROL?", .callback = SCPI_SystemCommTcpipControlQ,}, - - {.pattern = "TEST:BOOL", .callback = SCPI_TestBool,}, + + {.pattern = "TEST:BOOL", .callback = TEST_Bool,}, + {.pattern = "TEST:CHOice?", .callback = TEST_ChoiceQ,}, SCPI_CMD_LIST_END }; @@ -182,4 +207,5 @@ .registers = scpi_regs, .units = scpi_units_def, .special_numbers = scpi_special_numbers_def, + .idn = {"MANUFACTURE", "INSTR2013", NULL, "01-02"}, }; diff --git a/libscpi/inc/scpi/constants.h b/libscpi/inc/scpi/constants.h index 9316556..6023e6d 100644 --- a/libscpi/inc/scpi/constants.h +++ b/libscpi/inc/scpi/constants.h @@ -42,9 +42,19 @@ #endif -#define SCPI_MANUFACTURE "CTU FEE" -#define SCPI_DEV_NAME "TEST SCPI INSTRUMENT TSI3225" -#define SCPI_DEV_VERSION "v1.0" +/* 4.1.3.6 *IDN? */ + +#define SCPI_DEFAULT_1_MANUFACTURE "CTU FEE" +#define SCPI_DEFAULT_2_MODEL "TSI3225" +#define SCPI_DEFAULT_3 "0" +#define SCPI_DEFAULT_4_REVISION "01-01" + +/* 21.21 :VERSion? + * YYYY.V + * YYYY = SCPI year + * V = SCPI revision + */ +#define SCPI_STD_VERSION_REVISION "1999.0" #ifdef __cplusplus } diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index bf486b9..27ad31b 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -52,17 +52,19 @@ /* http://en.wikipedia.org/wiki/X_Macro */ #define LIST_OF_ERRORS \ + X(SCPI_ERROR_INVALID_CHARACTER, -101, "Invalid character") \ X(SCPI_ERROR_SYNTAX, -102, "Syntax error") \ X(SCPI_ERROR_INVALID_SEPARATOR, -103, "Invalid separator") \ - X(SCPI_ERROR_UNDEFINED_HEADER, -113, "Undefined header") \ + X(SCPI_ERROR_DATA_TYPE_ERROR, -104, "Data type error") \ X(SCPI_ERROR_PARAMETER_NOT_ALLOWED,-108, "Parameter not allowed") \ X(SCPI_ERROR_MISSING_PARAMETER, -109, "Missing parameter") \ + X(SCPI_ERROR_UNDEFINED_HEADER, -113, "Undefined header") \ X(SCPI_ERROR_INVALID_SUFFIX, -131, "Invalid suffix") \ X(SCPI_ERROR_SUFFIX_NOT_ALLOWED, -138, "Suffix not allowed") \ - X(SCPI_ERROR_UNKNOWN_PARAMETER, -199, "Unknown parameter") \ - X(SCPI_ERROR_INVALID_PARAMETER, -198, "Invalid parameter") \ - X(SCPI_ERROR_UNEXPECTED_CHARACTER, -197, "Unexpected character") \ + X(SCPI_ERROR_INVALID_STRING_DATA, -151, "Invalid string data") \ X(SCPI_ERROR_EXECUTION_ERROR, -200, "Execution error") \ + X(SCPI_ERROR_ILLEGAL_PARAMETER_VALUE,-224,"Illegal parameter value") \ + X(SCPI_ERROR_SYSTEM_ERROR, -310, "System error") \ enum { diff --git a/libscpi/inc/scpi/parser.h b/libscpi/inc/scpi/parser.h index d42f9bd..1a6966e 100644 --- a/libscpi/inc/scpi/parser.h +++ b/libscpi/inc/scpi/parser.h @@ -37,6 +37,7 @@ #ifndef SCPI_PARSER_H #define SCPI_PARSER_H +#include <string.h> #include "scpi/types.h" #include "scpi/debug.h" #include "scpi/lexer.h" @@ -51,6 +52,7 @@ size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len); +#define SCPI_ResultMnemonic(context, data) SCPI_ResultCharacters((context), (data), strlen(data)) size_t SCPI_ResultInt(scpi_t * context, int32_t val); size_t SCPI_ResultIntBase(scpi_t * context, int32_t val, int8_t base); size_t SCPI_ResultDouble(scpi_t * context, double val); @@ -64,6 +66,7 @@ #define SCPI_ParamGetCharactersVal SCPI_ParamGetTextVal #define SCPI_ParamGetArbitraryBlockVal SCPI_ParamGetTextVal bool_t SCPI_ParamGetBoolVal(scpi_t * context, scpi_parameter_t * parameter); + int32_t SCPI_ParamGetChoiceVal(scpi_t * context, scpi_parameter_t * parameter, const char * options[]); bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, bool_t mandatory); diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index c6ede6a..3791c9d 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -283,6 +283,7 @@ const scpi_special_number_def_t * special_numbers; void * user_context; scpi_parser_state_t parser_state; + const char * idn[4]; }; #ifdef __cplusplus diff --git a/libscpi/src/ieee488.c b/libscpi/src/ieee488.c index 5fd7fe9..ab62b56 100644 --- a/libscpi/src/ieee488.c +++ b/libscpi/src/ieee488.c @@ -240,13 +240,20 @@ /** * *IDN? + * + * field1: MANUFACTURE + * field2: MODEL + * field4: SUBSYSTEMS REVISIONS + * + * example: MANUFACTURE,MODEL,0,01-02-01 * @param context * @return */ scpi_result_t SCPI_CoreIdnQ(scpi_t * context) { - SCPI_ResultText(context, SCPI_MANUFACTURE); - SCPI_ResultText(context, SCPI_DEV_NAME); - SCPI_ResultText(context, SCPI_DEV_VERSION); + SCPI_ResultMnemonic(context, context->idn[0]); + SCPI_ResultMnemonic(context, context->idn[1]); + SCPI_ResultMnemonic(context, context->idn[2]); + SCPI_ResultMnemonic(context, context->idn[3]); return SCPI_RES_OK; } diff --git a/libscpi/src/minimal.c b/libscpi/src/minimal.c index eab2624..353fbe0 100644 --- a/libscpi/src/minimal.c +++ b/libscpi/src/minimal.c @@ -67,7 +67,7 @@ * @return */ scpi_result_t SCPI_SystemVersionQ(scpi_t * context) { - SCPI_ResultText(context, SCPI_DEV_VERSION); + SCPI_ResultText(context, SCPI_STD_VERSION_REVISION); return SCPI_RES_OK; } diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index 2a0eabf..c65e6bc 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -42,6 +42,7 @@ #include "scpi/lexer.h" #include "utils.h" #include "scpi/error.h" +#include "scpi/constants.h" /** * Write data to SCPI output @@ -74,7 +75,7 @@ */ static size_t writeDelimiter(scpi_t * context) { if (context->output_count > 0) { - return writeData(context, ", ", 2); + return writeData(context, ",", 2); } else { return 0; } @@ -168,7 +169,7 @@ r = SCPI_DetectProgramMessageUnit(state, data, len); if (state->programHeader.type == TokInvalid) { - SCPI_ErrorPush(context, SCPI_ERROR_UNEXPECTED_CHARACTER); + SCPI_ErrorPush(context, SCPI_ERROR_INVALID_CHARACTER); } else if (state->programHeader.len > 0) { if (findCommandHeader(context, state->programHeader.ptr, state->programHeader.len)) { @@ -203,6 +204,19 @@ * @param interface */ void SCPI_Init(scpi_t * context) { + if (context->idn[0] == NULL) { + context->idn[0] = SCPI_DEFAULT_1_MANUFACTURE; + } + if (context->idn[1] == NULL) { + context->idn[1] = SCPI_DEFAULT_2_MODEL; + } + if (context->idn[2] == NULL) { + context->idn[2] = SCPI_DEFAULT_3; + } + if (context->idn[3] == NULL) { + context->idn[3] = SCPI_DEFAULT_4_REVISION; + } + context->buffer.position = 0; SCPI_ErrorInit(context); } @@ -433,7 +447,7 @@ parameter->type = TokUnknown; parameter->data.ptr = NULL; parameter->data.len = 0; - SCPI_ErrorPush(context, SCPI_ERROR_UNKNOWN_PARAMETER); + SCPI_ErrorPush(context, SCPI_ERROR_INVALID_STRING_DATA); return FALSE; } } @@ -447,7 +461,7 @@ case TokDecimalNumericProgramDataWithSuffix: return parameter->number.value; default: - SCPI_ErrorPush(context, SCPI_ERROR_INVALID_PARAMETER); + SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); return 0; } } @@ -472,15 +486,41 @@ } else if (compareStr("OFF", 3, parameter->data.ptr, parameter->data.len)) { return FALSE; } else { - SCPI_ErrorPush(context, SCPI_ERROR_INVALID_PARAMETER); + SCPI_ErrorPush(context, SCPI_ERROR_ILLEGAL_PARAMETER_VALUE); return FALSE; } default: - SCPI_ErrorPush(context, SCPI_ERROR_INVALID_PARAMETER); + SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); return FALSE; } } +/** + * Get choice parameter + */ +int32_t SCPI_ParamGetChoiceVal(scpi_t * context, scpi_parameter_t * parameter, const char * options[]) { + size_t res; + + if (!options) { + SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); + return -1; + } + + switch(parameter->type) { + case TokProgramMnemonic: + for (res = 0; options[res]; ++res) { + if (matchPattern(options[res], strlen(options[res]), parameter->data.ptr, parameter->data.len)) { + return res; + } + } + SCPI_ErrorPush(context, SCPI_ERROR_ILLEGAL_PARAMETER_VALUE); + return -1; + default: + SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); + return -1; + } +} + int SCPI_ParseProgramData(lex_state_t * state, token_t * token) { token_t tmp; int result = 0; diff --git a/libscpi/src/units.c b/libscpi/src/units.c index 3583ef5..351d735 100644 --- a/libscpi/src/units.c +++ b/libscpi/src/units.c @@ -257,25 +257,22 @@ state.pos = state.buffer; state.len = parameter->data.len; - if (parameter->type == TokDecimalNumericProgramDataWithSuffix) { - SCPI_LexDecimalNumericProgramData(&state, &token); - SCPI_LexWhiteSpace(&state, &token); - SCPI_LexSuffixProgramData(&state, &token); + switch(parameter->type) { + case TokDecimalNumericProgramDataWithSuffix: + SCPI_LexDecimalNumericProgramData(&state, &token); + SCPI_LexWhiteSpace(&state, &token); + SCPI_LexSuffixProgramData(&state, &token); - return transformNumber(context, token.ptr, token.len, ¶meter->number); + return transformNumber(context, token.ptr, token.len, ¶meter->number); + case TokProgramMnemonic: + SCPI_LexWhiteSpace(&state, &token); + SCPI_LexCharacterProgramData(&state, &token); - } else if (parameter->type == TokProgramMnemonic) { - SCPI_LexWhiteSpace(&state, &token); - SCPI_LexCharacterProgramData(&state, &token); - - /* convert string to special number type */ - if (translateSpecialNumber(context->special_numbers, token.ptr, token.len, ¶meter->number)) { - /* found special type */ - return TRUE; - } + /* convert string to special number type */ + return translateSpecialNumber(context->special_numbers, token.ptr, token.len, ¶meter->number); + default: + return FALSE; } - - return FALSE; } /** -- Gitblit v1.9.1