added skeleton for required SCPI SYST and STAT commands

master
Ondřej Hruška 9 years ago
parent 1cec87973c
commit 35732d948e
  1. 2
      Makefile
  2. 7
      main.c
  3. 6
      scpi.pro
  4. 321
      scpi_builtins.c
  5. 26
      scpi_builtins.h
  6. 174
      scpi_parser.c
  7. 19
      scpi_parser.h

@ -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

@ -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]);

@ -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

@ -0,0 +1,321 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#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
};

@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#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[];

@ -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. */

@ -3,6 +3,7 @@
#include <stdbool.h>
#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 --------------------

Loading…
Cancel
Save