Skip to content

Commit

Permalink
Refactoring of arbitrary data, special numbers
Browse files Browse the repository at this point in the history
 - refactoring of handling arbitrary program data
 - refactoring of handling special numbers and bool as choice
  • Loading branch information
j123b567 committed Jan 18, 2015
1 parent 794a6e9 commit e9becf5
Show file tree
Hide file tree
Showing 9 changed files with 484 additions and 241 deletions.
43 changes: 31 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Source codes are published with open source Simplified BSD license.
Usage
---------------
Download source package or clone repository
- v2.0_beta1 - https://github.com/j123b567/scpi-parser/archive/v2.0_beta1.zip
- v1.2 - https://github.com/j123b567/scpi-parser/archive/v1.2.zip
- v1.1 - https://github.com/j123b567/scpi-parser/archive/v1.1.zip
- v1.0 - https://github.com/j123b567/scpi-parser/archive/v1.0.zip
- git clone https://github.com/j123b567/scpi-parser.git

Expand All @@ -27,17 +30,22 @@ You can use any of the examples in the `examples` directory

Version history
----------------
Version v1.0 released 24.6.2013
- support basic command pattern matching (no optional keywoards)
- support basic data types (no expressions, no nondecimal numbers, no arbitrary program data, ...)
- last version before refactoring of the parser and before extending parameter handling

Future Version v2.0 released ????????
Version v2.0_beta1 2015-01-18
- parsing more compliant with SCPI-1999
- support all parameter types defined in the spec - separate them and identifie them
- support for Arbitrary program data
- support for tagging command patterns (useful for common handler)
- support for extending any parameter type using SCPI_Parameter
- general support for number or text value (e.g. 1, 6, DEF, INF) not limited to one array of special numbers
- support for optional command headers (Richard.hmm)


Version v1.0 released 2013-06-24
- support basic command pattern matching (no optional keywoards)
- support basic data types (no expressions, no nondecimal numbers, no arbitrary program data, ...)
- last version before refactoring of the parser and before extending parameter handling


Command pattern definition
-----------
Command pattern is defined by well known representation from SCPI instruments. Pattern is case insensitive but uses lower and upper case letters to show short and long form of the command.
Expand Down Expand Up @@ -65,7 +73,7 @@ The "Q" at the end of the function name indicates, that this function is Query f
The command callback can use predefined function to parse input parameters and to write output.
Reading input parameter is done by functions `SCPI_ParamInt`, `SCPI_ParamDouble`, `SCPI_ParamString` adn `SCPI_ParamNumber`.
Reading input parameter is done by functions `SCPI_ParamInt`, `SCPI_ParamDouble`, `SCPI_ParamString`, `SCPI_ParamNumber`, `SCPI_ParamArbitraryBlock`, `SCPI_ParamCopyText`, `SCPI_ParamBool` and `SCPI_ParamChoice`
Writing output is done by functions `SCPI_ResultInt`, `SCPI_ResultDouble`, `SCPI_ResultString`, `SCPI_ResultText`. You can write multiple output variables. They are automaticcaly separated by coma ",".
Expand Down Expand Up @@ -136,7 +144,6 @@ scpi_t scpi_context = {
.interface = &scpi_interface,
.registers = scpi_regs,
.units = scpi_units_def,
.special_numbers = scpi_special_numbers_def,
};
```

Expand Down Expand Up @@ -196,17 +203,29 @@ Every time, you call function to read parameter, it shifts pointers to the next

If you discard some parameters, there is no way to recover them.

Specifying `mandatory` parameter will introduce SCPI Error -109 "Missing parameter"

These are the functions, you can use to read parameters
- `SCPI_Parameter` - read parameter to scpi_parameter_t. This structure contains pointer to buffer and type of the parameter (program mnemonic, hex number, ....)
- `SCPI_ParamInt` - read signed 32bit integer value (dec or hex with 0x prefix)
- `SCPI_ParamDouble` - read double value
- `SCPI_ParamNumber` - read double value with or without units or represented by special number (DEF, MIN, MAX, ...). This function is more universal then SCPI_ParamDouble.
- `SCPI_ParamText` - read text value - may be encapsuled in ""
- `SCPI_ParamString` - read unspecified parameter not encapsulated in ""
- `SCPI_ParamCopyText` - read text value - must be encapsuled in ""
- `SCPI_ParamBool` - read boolean value (0, 1, on, off)
- `SCPI_ParamChoice` - read value from predefined constants


These are the functions, you can use to write results
- `SCPI_ResultInt` - write integer value
- `SCPI_ResultDouble` - write double value
- `SCPI_ResultText` - write text value encapsulated in ""
- `SCPI_ResultString` - directly write string value
- `SCPI_ResultMnemonic` - directly write string value
- `SCPI_ResultArbitraryBlock` - result arbitrary data
- `SCPI_ResultIntBase` - write integer in special base
- `SCPI_ResultBool` - write boolean value

You can use function `SCPI_NumberToStr` to convert number with units to textual representation and then use `SCPI_ResultMnemonic` to write this to the user.

You can use `SCPI_Parameter` in conjuction with `SCPI_ParamIsNumber`, `SCPI_ParamToInt`, `SCPI_ParamToDouble`, `SCPI_ParamToChoice` in your own parameter type handlers.

You can use function `SCPI_NumberToStr` to convert number with units to textual representation and then use `SCPI_ResultString` to write this to the user.
`SCPI_ParamNumber` is now more universal. It can handle number with units, it can handle special numbers like `DEF`, `INF`, ... These special numbers are now defined in parameter and not in context. It is possible to define more general usage with different special numbers for different commands,
56 changes: 41 additions & 15 deletions examples/common/scpi-def.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,21 @@ scpi_result_t DMM_MeasureVoltageDcQ(scpi_t * context) {
fprintf(stderr, "meas:volt:dc\r\n"); // debug command name

// read first parameter if present
if (!SCPI_ParamNumber(context, &param1, false)) {
if (!SCPI_ParamNumber(context, scpi_special_numbers_def, &param1, false)) {
// do something, if parameter not present
}

// read second paraeter if present
if (!SCPI_ParamNumber(context, &param2, false)) {
if (!SCPI_ParamNumber(context, scpi_special_numbers_def, &param2, false)) {
// do something, if parameter not present
}


SCPI_NumberToStr(context, &param1, bf, 15);
SCPI_NumberToStr(context, scpi_special_numbers_def, &param1, bf, 15);
fprintf(stderr, "\tP1=%s\r\n", bf);


SCPI_NumberToStr(context, &param2, bf, 15);
SCPI_NumberToStr(context, scpi_special_numbers_def, &param2, bf, 15);
fprintf(stderr, "\tP2=%s\r\n", bf);

SCPI_ResultDouble(context, 0);
Expand All @@ -75,21 +75,21 @@ scpi_result_t DMM_MeasureVoltageAcQ(scpi_t * context) {
fprintf(stderr, "meas:volt:ac\r\n"); // debug command name

// read first parameter if present
if (!SCPI_ParamNumber(context, &param1, false)) {
if (!SCPI_ParamNumber(context, scpi_special_numbers_def, &param1, false)) {
// do something, if parameter not present
}

// read second paraeter if present
if (!SCPI_ParamNumber(context, &param2, false)) {
if (!SCPI_ParamNumber(context, scpi_special_numbers_def, &param2, false)) {
// do something, if parameter not present
}


SCPI_NumberToStr(context, &param1, bf, 15);
SCPI_NumberToStr(context, scpi_special_numbers_def, &param1, bf, 15);
fprintf(stderr, "\tP1=%s\r\n", bf);


SCPI_NumberToStr(context, &param2, bf, 15);
SCPI_NumberToStr(context, scpi_special_numbers_def, &param2, bf, 15);
fprintf(stderr, "\tP2=%s\r\n", bf);

SCPI_ResultDouble(context, 0);
Expand Down Expand Up @@ -131,23 +131,25 @@ scpi_result_t TEST_Bool(scpi_t * context) {
return SCPI_RES_OK;
}

const char * trigger_source[] = {
"BUS",
"IMMediate",
"EXTernal",
NULL /* termination of option list */
scpi_choice_def_t trigger_source[] = {
{"BUS", 5},
{"IMMediate", 6},
{"EXTernal", 7},
SCPI_CHOICE_LIST_END /* termination of option list */
};


scpi_result_t TEST_ChoiceQ(scpi_t * context) {

int32_t param;
const char * name;

if (!SCPI_ParamChoice(context, trigger_source, &param, true)) {
return SCPI_RES_ERR;
}

fprintf(stderr, "\tP1=%s (%d)\r\n", trigger_source[param], param);
SCPI_ChoiceToName(trigger_source, param, &name);
fprintf(stderr, "\tP1=%s (%d)\r\n", name, param);

SCPI_ResultInt(context, param);

Expand All @@ -161,6 +163,29 @@ scpi_result_t TEST_Numbers(scpi_t * context) {
return SCPI_RES_OK;
}

scpi_result_t TEST_Text(scpi_t * context) {
char buffer[100];
size_t copy_len;

buffer[0] = 0;
SCPI_ParamCopyText(context, buffer, 100, &copy_len, false);

fprintf(stderr, "TEXT: ***%s***\r\n", buffer);

return SCPI_RES_OK;
}

scpi_result_t TEST_ArbQ(scpi_t * context) {
const char * data;
size_t len;

SCPI_ParamArbitraryBlock(context, &data, &len, false);

SCPI_ResultArbitraryBlock(context, data, len);

return SCPI_RES_OK;
}

static const scpi_command_t scpi_commands[] = {
/* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */
{ .pattern = "*CLS", .callback = SCPI_CoreCls,},
Expand Down Expand Up @@ -212,6 +237,8 @@ static const scpi_command_t scpi_commands[] = {
{.pattern = "TEST:BOOL", .callback = TEST_Bool,},
{.pattern = "TEST:CHOice?", .callback = TEST_ChoiceQ,},
{.pattern = "TEST#:NUMbers#", .callback = TEST_Numbers,},
{.pattern = "TEST:TEXT", .callback = TEST_Text,},
{.pattern = "TEST:ARBitrary?", .callback = TEST_ArbQ,},

SCPI_CMD_LIST_END
};
Expand Down Expand Up @@ -240,6 +267,5 @@ scpi_t scpi_context = {
.interface = &scpi_interface,
.registers = scpi_regs,
.units = scpi_units_def,
.special_numbers = scpi_special_numbers_def,
.idn = {"MANUFACTURE", "INSTR2013", NULL, "01-02"},
};
15 changes: 10 additions & 5 deletions libscpi/inc/scpi/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,26 @@ extern "C" {
size_t SCPI_ResultText(scpi_t * context, const char * data);
size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len);
size_t SCPI_ResultBool(scpi_t * context, scpi_bool_t val);


scpi_bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamIsNumber(scpi_parameter_t * parameter, scpi_bool_t suffixAllowed);
scpi_bool_t SCPI_ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value);
scpi_bool_t SCPI_ParamToDouble(scpi_t * context, scpi_parameter_t * parameter, double * value);
scpi_bool_t SCPI_ParamToChoice(scpi_t * context, scpi_parameter_t * parameter, const scpi_choice_def_t * options, int32_t * value);
scpi_bool_t SCPI_ChoiceToName(const scpi_choice_def_t * options, int32_t tag, const char ** text);


scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory);
// scpi_bool_t SCPI_ParamString(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamCharacters(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory);
#define SCPI_ParamArbitraryBlock SCPI_ParamCharacters
// scpi_bool_t SCPI_ParamText(scpi_t * context, const char ** value, size_t * len, int * type, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamArbitraryBlock(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamCopyText(scpi_t * context, char * buffer, size_t buffer_len, size_t * copy_len, scpi_bool_t mandatory);

scpi_bool_t SCPI_ParamBool(scpi_t * context, scpi_bool_t * value, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamChoice(scpi_t * context, const char * options[], int32_t * value, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamChoice(scpi_t * context, const scpi_choice_def_t * options, int32_t * value, scpi_bool_t mandatory);

scpi_bool_t SCPI_IsCmd(scpi_t * context, const char * cmd);
int32_t SCPI_CmdTag(scpi_t * context);

#ifdef __cplusplus
}
Expand Down
19 changes: 7 additions & 12 deletions libscpi/inc/scpi/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ extern "C" {

typedef struct _scpi_command_t scpi_command_t;

#define SCPI_CMD_LIST_END {NULL, NULL, }
#define SCPI_CMD_LIST_END {NULL, NULL, 0}

/* scpi interface */
typedef struct _scpi_t scpi_t;
Expand Down Expand Up @@ -229,12 +229,12 @@ extern "C" {
};
typedef enum _scpi_special_number_t scpi_special_number_t;

struct _scpi_special_number_def_t {
struct _scpi_choice_def_t {
const char * name;
scpi_special_number_t type;
int32_t tag;
};
#define SCPI_SPECIAL_NUMBERS_LIST_END {NULL, SCPI_NUM_NUMBER}
typedef struct _scpi_special_number_def_t scpi_special_number_def_t;
#define SCPI_CHOICE_LIST_END {NULL, -1}
typedef struct _scpi_choice_def_t scpi_choice_def_t;

struct _scpi_param_list_t {
const scpi_command_t * cmd;
Expand All @@ -257,16 +257,12 @@ extern "C" {
};
typedef struct _scpi_data_parameter_t scpi_data_parameter_t;

struct _scpi_parameter_t {
scpi_token_type_t type;
scpi_data_parameter_t data;
scpi_number_t number;
};
typedef struct _scpi_parameter_t scpi_parameter_t;
typedef scpi_token_t scpi_parameter_t;

struct _scpi_command_t {
const char * pattern;
scpi_command_callback_t callback;
int32_t tag;
};

struct _scpi_interface_t {
Expand All @@ -289,7 +285,6 @@ extern "C" {
scpi_error_queue_t error_queue;
scpi_reg_val_t * registers;
const scpi_unit_def_t * units;
const scpi_special_number_def_t * special_numbers;
void * user_context;
scpi_parser_state_t parser_state;
const char * idn[4];
Expand Down
6 changes: 3 additions & 3 deletions libscpi/inc/scpi/units.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ extern "C" {
#endif

extern const scpi_unit_def_t scpi_units_def[];
extern const scpi_special_number_def_t scpi_special_numbers_def[];
extern const scpi_choice_def_t scpi_special_numbers_def[];

scpi_bool_t SCPI_ParamNumber(scpi_t * context, scpi_number_t * value, scpi_bool_t mandatory);
scpi_bool_t SCPI_ParamNumber(scpi_t * context, const scpi_choice_def_t * special, scpi_number_t * value, scpi_bool_t mandatory);

scpi_bool_t SCPI_ParamTranslateNumberVal(scpi_t * context, scpi_parameter_t * parameter);
size_t SCPI_NumberToStr(scpi_t * context, scpi_number_t * value, char * str, size_t len);
size_t SCPI_NumberToStr(scpi_t * context, const scpi_choice_def_t * special, scpi_number_t * value, char * str, size_t len);

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit e9becf5

Please sign in to comment.