From 35732d948e7907f04a72267d2a9e57057b9d0206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 5 Dec 2015 17:10:44 +0100 Subject: [PATCH] added skeleton for required SCPI SYST and STAT commands --- Makefile | 2 +- main.c | 7 +- scpi.pro | 6 +- scpi_builtins.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++ scpi_builtins.h | 26 ++++ scpi_parser.c | 174 +------------------------- scpi_parser.h | 19 +-- 7 files changed, 365 insertions(+), 190 deletions(-) create mode 100644 scpi_builtins.c create mode 100644 scpi_builtins.h diff --git a/Makefile b/Makefile index fcdac19..b8a5c73 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: main.c scpi_parser.c scpi_parser.h - gcc main.c scpi_parser.c scpi_errors.c scpi_regs.c -o main.elf + gcc main.c scpi_parser.c scpi_errors.c scpi_regs.c scpi_builtins.c -o main.elf run: all ./main.elf diff --git a/main.c b/main.c index cc92ebc..96ca700 100644 --- a/main.c +++ b/main.c @@ -111,6 +111,11 @@ const char *scpi_device_identifier(void) } +const char *scpi_device_version(void) +{ + return "0.0.1"; +} + int main() { @@ -134,7 +139,7 @@ int main() //const char *inp = "FOO\nDATA:BLOB 13.456, #216AbcdEfghIjklMnop\nFREQ 50\r\nAPPLY:MOO\n"; //const char *inp = "STAT:QUE:ENAB?;ENAB \t 1;ENAB?;:*IDN?\n"; - const char *inp = "*idn?\n"; + const char *inp = "*idn?;*sre?;*cls;"; for (int i = 0; i < strlen(inp); i++) { scpi_handle_byte(inp[i]); diff --git a/scpi.pro b/scpi.pro index 9d56d88..1f0929e 100644 --- a/scpi.pro +++ b/scpi.pro @@ -7,7 +7,8 @@ SOURCES += \ scpi_parser.c \ main.c \ scpi_errors.c \ - scpi_regs.c + scpi_regs.c \ + scpi_builtins.c DISTFILES += \ style.astylerc \ @@ -19,4 +20,5 @@ DISTFILES += \ HEADERS += \ scpi_parser.h \ scpi_errors.h \ - scpi_regs.h + scpi_regs.h \ + scpi_builtins.h diff --git a/scpi_builtins.c b/scpi_builtins.c new file mode 100644 index 0000000..1cc9084 --- /dev/null +++ b/scpi_builtins.c @@ -0,0 +1,321 @@ +#include +#include +#include +#include + +#include "scpi_builtins.h" +#include "scpi_parser.h" +#include "scpi_errors.h" +#include "scpi_regs.h" + +// response buffer +static char sbuf[256]; + + +// ---------------- BUILTIN SCPI COMMANDS ------------------ + +static void builtin_CLS(const SCPI_argval_t *args) +{ + // clear the registers + SCPI_REG_SESR.u8 = 0; + SCPI_REG_OPER.u16 = 0; + SCPI_REG_QUES.u16 = 0; + scpi_clear_errors(); + + if (scpi_user_CLS) { + scpi_user_CLS(); + } + + scpi_status_update(); // flags +} + + +static void builtin_RST(const SCPI_argval_t *args) +{ + if (scpi_user_RST) { + scpi_user_RST(); + } +} + + +static void builtin_TSTq(const SCPI_argval_t *args) +{ + if (scpi_user_TSTq) { + scpi_user_TSTq(); + } +} + + +static void builtin_IDNq(const SCPI_argval_t *args) +{ + scpi_send_string(scpi_device_identifier()); +} + + +static void builtin_ESE(const SCPI_argval_t *args) +{ + SCPI_REG_SESR_EN.u8 = (uint8_t) args[0].INT; +} + + +static void builtin_ESEq(const SCPI_argval_t *args) +{ + sprintf(sbuf, "%d", SCPI_REG_SESR_EN.u8); + scpi_send_string(sbuf); +} + + +static void builtin_ESRq(const SCPI_argval_t *args) +{ + sprintf(sbuf, "%d", SCPI_REG_SESR.u8); + scpi_send_string(sbuf); +} + + +static void builtin_OPC(const SCPI_argval_t *args) +{ + // implementation for instruments with no overlapping commands. + // Can be overridden in the user commands. + SCPI_REG_SESR.OPC = 1; +} + + +static void builtin_OPCq(const SCPI_argval_t *args) +{ + // implementation for instruments with no overlapping commands. + // Can be overridden in the user commands. + // (would be): sprintf(sbuf, "%d", SCPI_REG_SESR.OPC); + + scpi_send_string("1"); +} + + +static void builtin_SRE(const SCPI_argval_t *args) +{ + SCPI_REG_SRE.u8 = (uint8_t) args[0].INT; +} + + +static void builtin_SREq(const SCPI_argval_t *args) +{ + sprintf(sbuf, "%d", SCPI_REG_SRE.u8); + scpi_send_string(sbuf); +} + + +static void builtin_STBq(const SCPI_argval_t *args) +{ + sprintf(sbuf, "%d", SCPI_REG_STB.u8); + scpi_send_string(sbuf); +} + + +static void builtin_WAI(const SCPI_argval_t *args) +{ + // no-op +} + + +static void builtin_SYST_ERRq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_SYST_VERSq(const SCPI_argval_t *args) +{ + scpi_send_string(scpi_device_version()); +} + + +static void builtin_STAT_OPER_EVENq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_OPER_CONDq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_OPER_ENAB(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_OPER_ENABq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_QUES_EVENq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_QUES_CONDq(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_QUES_ENAB(const SCPI_argval_t *args) +{ + // TODO +} + + +static void builtin_STAT_QUES_ENABq(const SCPI_argval_t *args) +{ + // TODO +} + +static void builtin_STAT_PRES(const SCPI_argval_t *args) +{ + // TODO +} + + +const SCPI_command_t scpi_commands_builtin[] = { + // ---- COMMON COMMANDS ---- + { + .levels = {"*CLS"}, + .callback = builtin_CLS + }, + { + .levels = {"*ESE"}, + .params = {SCPI_DT_INT}, + .callback = builtin_ESE + }, + { + .levels = {"*ESE?"}, + .callback = builtin_ESEq + }, + { + .levels = {"*ESR?"}, + .callback = builtin_ESRq + }, + { + .levels = {"*IDN?"}, + .callback = builtin_IDNq + }, + { + .levels = {"*OPC"}, + .callback = builtin_OPC + }, + { + .levels = {"*OPCq"}, + .callback = builtin_OPCq + }, + { + .levels = {"*RST"}, + .callback = builtin_RST + }, + { + .levels = {"*SRE"}, + .params = {SCPI_DT_INT}, + .callback = builtin_SRE + }, + { + .levels = {"*SRE?"}, + .callback = builtin_SREq + }, + { + .levels = {"*STB?"}, + .callback = builtin_STBq + }, + { + .levels = {"*WAI"}, + .callback = builtin_WAI + }, + { + .levels = {"*TST?"}, + .callback = builtin_TSTq + }, + + // ---- REQUIRED SUBSYSTEM COMMANDS ---- + + // SYSTem + { + .levels = {"SYSTem", "ERRor?"}, + .callback = builtin_SYST_ERRq + }, + { + .levels = {"SYSTem", "ERRor", "NEXT?"}, + .callback = builtin_SYST_ERRq + }, + { + .levels = {"SYSTem", "VERSion?"}, + .callback = builtin_SYST_VERSq + }, + // STATus:OPERation + { + .levels = {"STATus", "OPERation?"}, + .callback = builtin_STAT_OPER_EVENq + }, + { + .levels = {"STATus", "OPERation", "EVENt?"}, + .callback = builtin_STAT_OPER_EVENq + }, + { + .levels = {"STATus", "OPERation", "CONDition?"}, + .callback = builtin_STAT_OPER_CONDq + }, + { + .levels = {"STATus", "OPERation", "ENABle"}, + .params = {SCPI_DT_BOOL}, + .callback = builtin_STAT_OPER_ENAB + }, + { + .levels = {"STATus", "OPERation", "ENABle?"}, + .callback = builtin_STAT_OPER_ENABq + }, + // STATus:QUEStionable + { + .levels = {"STATus", "QUEStionable?"}, + .callback = builtin_STAT_QUES_EVENq + }, + { + .levels = {"STATus", "QUEStionable", "EVENt?"}, + .callback = builtin_STAT_QUES_EVENq + }, + { + .levels = {"STATus", "QUEStionable", "CONDition?"}, + .callback = builtin_STAT_QUES_CONDq + }, + { + .levels = {"STATus", "QUEStionable", "ENABle"}, + .params = {SCPI_DT_BOOL}, + .callback = builtin_STAT_QUES_ENAB + }, + { + .levels = {"STATus", "QUEStionable", "ENABle?"}, + .callback = builtin_STAT_QUES_ENABq + }, + // STATus:PRESet + { + .levels = {"STATus", "PRESet"}, + .callback = builtin_STAT_PRES + }, + + {0} // end marker +}; + + + + + + + + + + + + + + diff --git a/scpi_builtins.h b/scpi_builtins.h new file mode 100644 index 0000000..666b611 --- /dev/null +++ b/scpi_builtins.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include + +#include "scpi_parser.h" +#include "scpi_errors.h" +#include "scpi_regs.h" + + +/** *CLS command callback - clear non-SCPI device state */ +extern __attribute__((weak)) void scpi_user_CLS(void); + +/** *RST command callback - reset non-SCPI device state */ +extern __attribute__((weak)) void scpi_user_RST(void); + +/** *TST? command callback - perform self test and send response back. */ +extern __attribute__((weak)) void scpi_user_TSTq(void); + +/** Get device *IDN? string. */ +extern const char *scpi_device_identifier(void); + +/** Get device version string. */ +extern const char *scpi_device_version(void); + +// Provides: +// const SCPI_command_t scpi_commands_builtin[]; diff --git a/scpi_parser.c b/scpi_parser.c index 56d2674..24c0dc9 100644 --- a/scpi_parser.c +++ b/scpi_parser.c @@ -7,6 +7,8 @@ #include "scpi_parser.h" #include "scpi_errors.h" +#include "scpi_builtins.h" +#include "scpi_regs.h" // Config #define ERR_QUEUE_LEN 4 @@ -84,9 +86,6 @@ static struct { // buffer for error messages static char ebuf[256]; -// response buffer -static char sbuf[256]; - // ---------------- PRIVATE PROTOTYPES ------------------ // Command parsing @@ -120,175 +119,6 @@ static void pars_reset_cmd(void); static void pars_reset_cmd_keeplevel(void); - -// ---------------- BUILTIN SCPI COMMANDS ------------------ - -static void builtin_CLS(const SCPI_argval_t *args) -{ - // clear the registers - SCPI_REG_SESR.u8 = 0; - SCPI_REG_OPER.u16 = 0; - SCPI_REG_QUES.u16 = 0; - scpi_clear_errors(); - - if (scpi_user_CLS) { - scpi_user_CLS(); - } - - scpi_status_update(); // flags -} - - -static void builtin_RST(const SCPI_argval_t *args) -{ - if (scpi_user_RST) { - scpi_user_RST(); - } -} - - -static void builtin_TSTq(const SCPI_argval_t *args) -{ - if (scpi_user_TSTq) { - scpi_user_TSTq(); - } -} - - -static void builtin_IDNq(const SCPI_argval_t *args) -{ - scpi_send_string(scpi_device_identifier()); -} - - -static void builtin_ESE(const SCPI_argval_t *args) -{ - SCPI_REG_SESR_EN.u8 = (uint8_t) args[0].INT; -} - - -static void builtin_ESEq(const SCPI_argval_t *args) -{ - sprintf(sbuf, "%d", SCPI_REG_SESR_EN.u8); - scpi_send_string(ebuf); -} - - -static void builtin_ESRq(const SCPI_argval_t *args) -{ - sprintf(sbuf, "%d", SCPI_REG_SESR.u8); - scpi_send_string(ebuf); -} - - -static void builtin_OPC(const SCPI_argval_t *args) -{ - // implementation for instruments with no overlapping commands. - // Can be overridden in the user commands. - SCPI_REG_SESR.OPC = 1; -} - - -static void builtin_OPCq(const SCPI_argval_t *args) -{ - // implementation for instruments with no overlapping commands. - // Can be overridden in the user commands. - // (would be): sprintf(sbuf, "%d", SCPI_REG_SESR.OPC); - - scpi_send_string("1"); -} - - -static void builtin_SRE(const SCPI_argval_t *args) -{ - SCPI_REG_SRE.u8 = (uint8_t) args[0].INT; -} - - -static void builtin_SREq(const SCPI_argval_t *args) -{ - sprintf(sbuf, "%d", SCPI_REG_SRE.u8); - scpi_send_string(ebuf); -} - - -static void builtin_STBq(const SCPI_argval_t *args) -{ - sprintf(sbuf, "%d", SCPI_REG_STB.u8); - scpi_send_string(ebuf); -} - - -static void builtin_WAI(const SCPI_argval_t *args) -{ - // no-op -} - - -static const SCPI_command_t scpi_commands_builtin[] = { - // ---- COMMON COMMANDS ---- - { - .levels = {"*CLS"}, - .callback = builtin_CLS - }, - { - .levels = {"*ESE"}, - .params = {SCPI_DT_INT}, - .callback = builtin_ESE - }, - { - .levels = {"*ESE?"}, - .callback = builtin_ESEq - }, - { - .levels = {"*ESR?"}, - .callback = builtin_ESRq - }, - { - .levels = {"*IDN?"}, - .callback = builtin_IDNq - }, - { - .levels = {"*OPC"}, - .callback = builtin_OPC - }, - { - .levels = {"*OPCq"}, - .callback = builtin_OPCq - }, - { - .levels = {"*RST"}, - .callback = builtin_RST - }, - { - .levels = {"*SRE"}, - .params = {SCPI_DT_INT}, - .callback = builtin_SRE - }, - { - .levels = {"*SRE?"}, - .callback = builtin_SREq - }, - { - .levels = {"*STB?"}, - .callback = builtin_STBq - }, - { - .levels = {"*WAI"}, - .callback = builtin_WAI - }, - { - .levels = {"*TST?"}, - .callback = builtin_TSTq - }, - // ---- REQUIRED SYST COMMANDS ---- - - - {0} // end marker -}; - - - // ------------------- MESSAGE SEND ------------------ /** Send a message to master. Trailing newline is added. */ diff --git a/scpi_parser.h b/scpi_parser.h index f2012f2..3930f72 100644 --- a/scpi_parser.h +++ b/scpi_parser.h @@ -3,6 +3,7 @@ #include #include "scpi_errors.h" +#include "scpi_builtins.h" #include "scpi_regs.h" #define SCPI_MAX_CMD_LEN 12 @@ -39,7 +40,7 @@ typedef union { */ typedef struct { // levels MUST BE FIRST! - const char levels[SCPI_MAX_LEVEL_COUNT][SCPI_MAX_CMD_LEN]; // up to 4 parts + const char levels[SCPI_MAX_LEVEL_COUNT][SCPI_MAX_CMD_LEN+2]; // up to 4 parts (+? and \0) // called when the command is completed. BLOB arg must be last in the argument list, // and only the first part is collected. @@ -61,22 +62,12 @@ typedef struct { // Zero terminated command struct array - must be defined. extern const SCPI_command_t scpi_commands[]; +// provided by scpi_builtins.h +extern const SCPI_command_t scpi_commands_builtin[]; + /** Send a byte to master (may be buffered) */ extern void scpi_send_byte_impl(uint8_t b); -/** *CLS command callback - clear non-SCPI device state */ -extern __attribute__((weak)) void scpi_user_CLS(void); - -/** *RST command callback - reset non-SCPI device state */ -extern __attribute__((weak)) void scpi_user_RST(void); - -/** *TST? command callback - perform self test and send response back. */ -extern __attribute__((weak)) void scpi_user_TSTq(void); - -/** Get device identifier. Implemented as a callback to allow dynamic serial number */ -extern const char *scpi_device_identifier(void); - - // --------------- functions --------------------