better example code

master
Ondřej Hruška 9 years ago
parent 326b6324cd
commit c7f3337c6f
  1. 41
      main.c
  2. 93
      source/scpi_errors.c
  3. 22
      source/scpi_errors.h
  4. 72
      source/scpi_parser.c
  5. 16
      source/scpi_parser.h

@ -6,16 +6,23 @@
// ------- TESTING ----------
static void send_cmd(const char *cmd)
{
printf("\n> %s\n", cmd);
scpi_handle_string(cmd);
}
int main()
{
scpi_handle_string("*IDN?\n");
scpi_handle_string("*SRE 4\n");
scpi_handle_string("FOO:BAR:BAZ\n");
scpi_handle_string("SYST:ERR:COUNT?\n");
scpi_handle_string("SYST:ERR?\n");
scpi_handle_string("SYST:ERR?\n");
scpi_handle_string("DATA:BLOB #216abcdefghijklmnop\n");
scpi_handle_string("SYST:ERR?\n");
send_cmd("*IDN?\n"); // builtin commands..
send_cmd("*SRE 4\n"); // enable SRQ on error
send_cmd("FOO:BAR:BAZ\n"); // invalid command causes error
send_cmd("SYST:ERR:COUNT?\n"); // error subsystem
send_cmd("SYST:ERR:NEXT?;COUNT?;NEXT?\n"); // semicolon works according to spec
send_cmd("DATA:BLOB #216abcdefghijklmnop\n"); // binary data block
send_cmd("APPLY:SINE 50, 1.0, 2.17\n"); // floats
send_cmd("DISP:TEXT \"Hello world\"\n"); // string
}
@ -35,37 +42,43 @@ const char *scpi_device_identifier(void)
void scpi_service_request_impl(void)
{
printf("[SRQ]\n");
// NOTE: Actual instrument should send SRQ event somehow
printf("[SRQ] - error: ");
char buf[256];
scpi_read_error_noremove(buf); // show error message (for debug)
printf("%s\n", buf);
}
// ---- COMMANDS ----
// ---- INSTRUMENT COMMANDS ----
void cmd_APPL_SIN_cb(const SCPI_argval_t *args)
{
printf("cb APPLy:SINe %d, %f, %f\n", args[0].INT, args[0].FLOAT, args[0].FLOAT);
printf("cb APPLy:SINe %d, %f, %f\n", args[0].INT, args[1].FLOAT, args[2].FLOAT);
}
void cmd_DISP_TEXT_cb(const SCPI_argval_t *args)
{
printf("cb DISPlay:TEXT %s\n", args[0].STRING);
printf("cb DISPlay:TEXT %s\n", args[0].STRING);
}
void cmd_DATA_BLOB_cb(const SCPI_argval_t *args)
{
printf("cb DATA:BLOB <%d>\n", args[1].BLOB_LEN);
printf("cb DATA:BLOB <%d>\n", args[0].BLOB_LEN);
}
void cmd_DATA_BLOB_data(const uint8_t *bytes)
{
printf("blob item: %s\n", bytes);
printf("binary data: \"%s\"\n", bytes);
}
// Command definition (mandatory commands are built-in)
const SCPI_command_t scpi_commands[] = {
{
.levels = {"APPLy", "SINe"},

@ -5,12 +5,104 @@
#include <string.h>
#include "scpi_errors.h"
#include "scpi_regs.h"
#define ERR_QUEUE_LEN 4
#define MAX_ERROR_LEN 255
// --- queue impl ---
static struct {
char queue[ERR_QUEUE_LEN][MAX_ERROR_LEN + 1];
int8_t r_pos;
int8_t w_pos;
int8_t count; // signed for backtracking
} erq;
void scpi_add_error(SCPI_error_t errno, const char *extra)
{
bool added = true;
if (erq.count >= ERR_QUEUE_LEN) {
errno = E_DEV_QUEUE_OVERFLOW;
extra = NULL;
added = false; // replaced only
// backtrack
erq.w_pos--;
erq.count--;
if (erq.w_pos < 0) {
erq.w_pos = ERR_QUEUE_LEN - 1;
}
}
scpi_error_string(erq.queue[erq.w_pos], errno, extra);
erq.w_pos++;
erq.count++;
if (erq.w_pos >= ERR_QUEUE_LEN) {
erq.w_pos = 0;
}
scpi_status_update();
}
void scpi_read_error_noremove(char *buf)
{
if (erq.count == 0) {
scpi_error_string(buf, E_NO_ERROR, NULL);
return;
}
strcpy(buf, erq.queue[erq.r_pos]);
}
void scpi_read_error(char *buf)
{
if (erq.count == 0) {
scpi_error_string(buf, E_NO_ERROR, NULL);
return;
}
strcpy(buf, erq.queue[erq.r_pos++]);
erq.count--;
if (erq.r_pos >= ERR_QUEUE_LEN) {
erq.r_pos = 0;
}
scpi_status_update();
}
void scpi_clear_errors(void)
{
erq.r_pos = 0;
erq.w_pos = 0;
erq.count = 0;
scpi_status_update();
}
uint8_t scpi_error_count(void)
{
return erq.count;
}
// ---- table ----
typedef struct {
const int16_t errno;
const char *msg;
} SCPI_error_desc;
static const SCPI_error_desc error_table[] = {
{ 0, "No error"},
{ -100, "Command error"},
@ -184,3 +276,4 @@ void scpi_error_string(char *buffer, SCPI_error_t errno, const char *extra)
sprintf(buffer, "\""); // "
}

@ -132,6 +132,7 @@ typedef enum {
/** Get SCPI error message (alone) */
const char *scpi_error_message(SCPI_error_t errno);
/**
* Get SCPI error string for reporting:
* <code>,"<message>[; <extra>]"
@ -139,3 +140,24 @@ const char *scpi_error_message(SCPI_error_t errno);
* extra can be NULL to skip the optional part.
*/
void scpi_error_string(char *buffer, SCPI_error_t errno, const char *extra);
/** Add error to the error queue */
void scpi_add_error(SCPI_error_t errno, const char *extra);
/** Get number of errors in the error queue */
uint8_t scpi_error_count(void);
/**
* Read and remove one entry from the error queue.
* Returns 0,"No error" if the queue is empty.
*
* The entry is copied to the provided buffer, which must be 256 chars long.
*/
void scpi_read_error(char *buf);
/** Read error, do not remove from queue */
void scpi_read_error_noremove(char *buf);

@ -11,8 +11,6 @@
#include "scpi_regs.h"
// Config
#define ERR_QUEUE_LEN 4
#define MAX_ERROR_LEN 255
#define MAX_CHARBUF_LEN 255
@ -52,11 +50,6 @@ typedef enum {
/** Parser internal state struct */
static struct {
char err_queue[ERR_QUEUE_LEN][MAX_ERROR_LEN + 1];
int8_t err_queue_r;
int8_t err_queue_w;
int8_t err_queue_used; // signed for backtracking
parser_state_t state; // current parser internal state
// string buffer, chars collected here until recognized
@ -140,70 +133,7 @@ void scpi_send_string(const char *message)
scpi_send_byte_impl('\n');
}
// ------------------- ERROR QUEUE ---------------------
void scpi_add_error(SCPI_error_t errno, const char *extra)
{
bool added = true;
if (pst.err_queue_used >= ERR_QUEUE_LEN) {
errno = E_DEV_QUEUE_OVERFLOW;
extra = NULL;
added = false; // replaced only
// backtrack
pst.err_queue_w--;
pst.err_queue_used--;
if (pst.err_queue_w < 0) {
pst.err_queue_w = ERR_QUEUE_LEN - 1;
}
}
scpi_error_string(pst.err_queue[pst.err_queue_w], errno, extra);
pst.err_queue_w++;
pst.err_queue_used++;
if (pst.err_queue_w >= ERR_QUEUE_LEN) {
pst.err_queue_w = 0;
}
scpi_status_update();
}
void scpi_read_error(char *buf)
{
if (pst.err_queue_used == 0) {
scpi_error_string(buf, E_NO_ERROR, NULL);
return;
}
strcpy(buf, pst.err_queue[pst.err_queue_r++]);
pst.err_queue_used--;
if (pst.err_queue_r >= ERR_QUEUE_LEN) {
pst.err_queue_r = 0;
}
scpi_status_update();
}
void scpi_clear_errors(void)
{
pst.err_queue_r = 0;
pst.err_queue_w = 0;
pst.err_queue_used = 0;
scpi_status_update();
}
uint8_t scpi_error_count(void)
{
return pst.err_queue_used;
}
// ------- Error shortcuts ----------
static void err_no_such_command()
{

@ -40,7 +40,7 @@ typedef union {
*/
typedef struct {
// levels MUST BE FIRST!
const char levels[SCPI_MAX_LEVEL_COUNT][SCPI_MAX_CMD_LEN+2]; // up to 4 parts (+? and \0)
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.
@ -84,20 +84,6 @@ void scpi_handle_byte(const uint8_t b);
void scpi_handle_string(const char* str);
/** Add error to the error queue */
void scpi_add_error(SCPI_error_t errno, const char *extra);
/** Get number of errors in the error queue */
uint8_t scpi_error_count(void);
/**
* Read and remove one entry from the error queue.
* Returns 0,"No error" if the queue is empty.
*
* The entry is copied to the provided buffer, which must be 256 chars long.
*/
void scpi_read_error(char *buf);
/** Discard the rest of the currently processed blob */
void scpi_discard_blob(void);

Loading…
Cancel
Save