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, &param1, true)) {
+        return SCPI_RES_ERR;
+    }
+
+    result = SCPI_ParamGetChoiceVal(context, &param1, 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, &parameter->number);
+            return transformNumber(context, token.ptr, token.len, &parameter->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, &parameter->number)) {
-            /* found special type */
-            return TRUE;
-        }
+            /* convert string to special number type */
+            return translateSpecialNumber(context->special_numbers, token.ptr, token.len, &parameter->number);
+        default:
+            return FALSE;
     }
-
-    return FALSE;
 }
 
 /**

--
Gitblit v1.9.1