Refactor scpi_init and resolve #66
| | |
| | | return SCPI_RES_OK; |
| | | } |
| | | |
| | | static const scpi_command_t scpi_commands[] = { |
| | | const scpi_command_t scpi_commands[] = { |
| | | /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */ |
| | | { .pattern = "*CLS", .callback = SCPI_CoreCls,}, |
| | | { .pattern = "*ESE", .callback = SCPI_CoreEse,}, |
| | |
| | | SCPI_CMD_LIST_END |
| | | }; |
| | | |
| | | static scpi_interface_t scpi_interface = { |
| | | scpi_interface_t scpi_interface = { |
| | | .error = SCPI_Error, |
| | | .write = SCPI_Write, |
| | | .control = SCPI_Control, |
| | |
| | | .reset = SCPI_Reset, |
| | | }; |
| | | |
| | | #define SCPI_INPUT_BUFFER_LENGTH 256 |
| | | static char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH]; |
| | | char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH]; |
| | | int16_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | |
| | | static scpi_reg_val_t scpi_regs[SCPI_REG_COUNT]; |
| | | |
| | | |
| | | scpi_t scpi_context = { |
| | | .cmdlist = scpi_commands, |
| | | .buffer = |
| | | { |
| | | .length = SCPI_INPUT_BUFFER_LENGTH, |
| | | .data = scpi_input_buffer, |
| | | }, |
| | | .interface = &scpi_interface, |
| | | .registers = scpi_regs, |
| | | .units = scpi_units_def, |
| | | .idn = |
| | | {"MANUFACTURE", "INSTR2013", NULL, "01-02"}, |
| | | }; |
| | | |
| | | scpi_t scpi_context; |
| | |
| | | |
| | | #include "scpi/scpi.h" |
| | | |
| | | #define SCPI_INPUT_BUFFER_LENGTH 256 |
| | | #define SCPI_ERROR_QUEUE_SIZE 17 |
| | | #define SCPI_IDN1 "MANUFACTURE" |
| | | #define SCPI_IDN2 "INSTR2013" |
| | | #define SCPI_IDN3 NULL |
| | | #define SCPI_IDN4 "01-02" |
| | | |
| | | extern const scpi_command_t scpi_commands[]; |
| | | extern scpi_interface_t scpi_interface; |
| | | extern char scpi_input_buffer[]; |
| | | extern int16_t scpi_error_queue_data[]; |
| | | extern scpi_t scpi_context; |
| | | |
| | | size_t SCPI_Write(scpi_t * context, const char * data, size_t len); |
| | |
| | | int main(int argc, char** argv) { |
| | | int result; |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | if (InitCVIRTE(0, argv, 0) == 0) |
| | | return -1; /* out of memory */ |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file scpi_server.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief TCP/IP SCPI Server |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | |
| | | queue_event_t msg; |
| | | msg.cmd = SCPI_MSG_SET_ESE_REQ; |
| | | |
| | | /* Avoid sending evtQueue message if ESR_REQ is already set |
| | | /* Avoid sending evtQueue message if ESR_REQ is already set |
| | | if((SCPI_RegGet(&scpi_context, SCPI_REG_ESR) & ESR_REQ) == 0) { |
| | | xQueueSend(user_data.evtQueue, &msg, 1000); |
| | | } |
| | |
| | | } |
| | | |
| | | /* |
| | | * |
| | | * |
| | | */ |
| | | static void scpi_server_thread(void *arg) { |
| | | queue_event_t evt; |
| | |
| | | user_data.evtQueue = xQueueCreate(10, sizeof (queue_event_t)); |
| | | |
| | | // user_context will be pointer to socket |
| | | scpi_context.user_context = &user_data; |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | scpi_context.user_context = &user_data; |
| | | |
| | | user_data.io_listen = createServer(DEVICE_PORT); |
| | | user_data.control_io_listen = createServer(CONTROL_PORT); |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file main.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief SCPI parser test |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | |
| | | } |
| | | |
| | | /* |
| | | * |
| | | * |
| | | */ |
| | | int main(int argc, char** argv) { |
| | | (void) argc; |
| | | (void) argv; |
| | | int result; |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | //printf("%.*s %s\r\n", 3, "asdadasdasdasdas", "b"); |
| | | printf("SCPI Interactive demo\r\n"); |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file main.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief SCPI parser test |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | |
| | | } |
| | | |
| | | /* |
| | | * |
| | | * |
| | | */ |
| | | int main(int argc, char** argv) { |
| | | (void) argc; |
| | | (void) argv; |
| | | int result; |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | #define TEST_SCPI_INPUT(cmd) result = SCPI_Input(&scpi_context, cmd, strlen(cmd)) |
| | | |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file main.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief TCP/IP SCPI Server |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | |
| | | } |
| | | |
| | | /* |
| | | * |
| | | * |
| | | */ |
| | | int main(int argc, char** argv) { |
| | | (void) argc; |
| | |
| | | }; |
| | | |
| | | // user_context will be pointer to socket |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | scpi_context.user_context = &user_data; |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | |
| | | user_data.io_listen = createServer(5025); |
| | | user_data.control_io_listen = createServer(CONTROL_PORT); |
| | |
| | | * Copyright (c) 2012-2013 Jan Breuer, |
| | | * |
| | | * All Rights Reserved |
| | | * |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are |
| | | * met: |
| | |
| | | * 2. Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * |
| | | * |
| | | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
| | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| | |
| | | /** |
| | | * @file main.c |
| | | * @date Thu Nov 15 10:58:45 UTC 2012 |
| | | * |
| | | * |
| | | * @brief TCP/IP SCPI Server |
| | | * |
| | | * |
| | | * |
| | | * |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | |
| | | } |
| | | |
| | | /* |
| | | * |
| | | * |
| | | */ |
| | | int main(int argc, char** argv) { |
| | | (void) argc; |
| | |
| | | // user_context will be pointer to socket |
| | | scpi_context.user_context = NULL; |
| | | |
| | | SCPI_Init(&scpi_context); |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | SCPI_IDN1, SCPI_IDN2, SCPI_IDN3, SCPI_IDN4, |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | listenfd = createServer(5025); |
| | | |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | void SCPI_ErrorInit(scpi_t * context); |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size); |
| | | void SCPI_ErrorClear(scpi_t * context); |
| | | int16_t SCPI_ErrorPop(scpi_t * context); |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err); |
| | |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #endif |
| | | void SCPI_Init(scpi_t * context); |
| | | void SCPI_Init(scpi_t * context, |
| | | const scpi_command_t * commands, |
| | | scpi_interface_t * interface, |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | int16_t * error_queue_data, int16_t error_queue_size); |
| | | |
| | | scpi_bool_t SCPI_Input(scpi_t * context, const char * data, int len); |
| | | scpi_bool_t SCPI_Parse(scpi_t * context, char * data, int len); |
| | |
| | | |
| | | typedef scpi_result_t(*scpi_command_callback_t)(scpi_t *); |
| | | |
| | | /* scpi error queue */ |
| | | typedef void * scpi_error_queue_t; |
| | | struct _scpi_fifo_t { |
| | | int16_t wr; |
| | | int16_t rd; |
| | | int16_t size; |
| | | int16_t * data; |
| | | }; |
| | | typedef struct _scpi_fifo_t scpi_fifo_t; |
| | | |
| | | /* scpi units */ |
| | | enum _scpi_unit_t { |
| | |
| | | int_fast16_t output_count; |
| | | int_fast16_t input_count; |
| | | scpi_bool_t cmd_error; |
| | | scpi_error_queue_t error_queue; |
| | | scpi_reg_val_t * registers; |
| | | scpi_fifo_t error_queue; |
| | | scpi_reg_val_t registers[SCPI_REG_COUNT]; |
| | | const scpi_unit_def_t * units; |
| | | void * user_context; |
| | | scpi_parser_state_t parser_state; |
| | |
| | | #include "scpi/error.h" |
| | | #include "fifo_private.h" |
| | | |
| | | /* basic FIFO */ |
| | | static scpi_fifo_t local_error_queue; |
| | | |
| | | /** |
| | | * Initialize error queue |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorInit(scpi_t * context) { |
| | | context->error_queue = (scpi_error_queue_t) & local_error_queue; |
| | | fifo_init((scpi_fifo_t *) context->error_queue); |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size) { |
| | | fifo_init(&context->error_queue, data, size); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorClear(scpi_t * context) { |
| | | fifo_clear((scpi_fifo_t *) context->error_queue); |
| | | fifo_clear(&context->error_queue); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | } |
| | |
| | | int16_t SCPI_ErrorPop(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | fifo_remove((scpi_fifo_t *) context->error_queue, &result); |
| | | fifo_remove(&context->error_queue, &result); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | |
| | |
| | | int32_t SCPI_ErrorCount(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | fifo_count((scpi_fifo_t *) context->error_queue, &result); |
| | | fifo_count(&context->error_queue, &result); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { |
| | | if (!fifo_add((scpi_fifo_t *) context->error_queue, err)) { |
| | | fifo_remove_last((scpi_fifo_t *) context->error_queue, NULL); |
| | | fifo_add((scpi_fifo_t *) context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | if (!fifo_add(&context->error_queue, err)) { |
| | | fifo_remove_last(&context->error_queue, NULL); |
| | | fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | } |
| | | } |
| | | |
| | |
| | | * Initialize fifo |
| | | * @param fifo |
| | | */ |
| | | void fifo_init(scpi_fifo_t * fifo) { |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) { |
| | | fifo->wr = 0; |
| | | fifo->rd = 0; |
| | | fifo->size = FIFO_SIZE; |
| | | fifo->data = data; |
| | | fifo->size = size; |
| | | } |
| | | |
| | | /** |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | |
| | | #define FIFO_SIZE 16 |
| | | |
| | | struct _scpi_fifo_t { |
| | | int16_t wr; |
| | | int16_t rd; |
| | | int16_t size; |
| | | int16_t data[FIFO_SIZE]; |
| | | }; |
| | | typedef struct _scpi_fifo_t scpi_fifo_t; |
| | | |
| | | void fifo_init(scpi_fifo_t * fifo) LOCAL; |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) LOCAL; |
| | | void fifo_clear(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_empty(scpi_fifo_t * fifo) LOCAL; |
| | | scpi_bool_t fifo_is_full(scpi_fifo_t * fifo) LOCAL; |
| | |
| | | * @param buffer |
| | | * @param interface |
| | | */ |
| | | void SCPI_Init(scpi_t * context) { |
| | | void SCPI_Init(scpi_t * context, |
| | | const scpi_command_t * commands, |
| | | scpi_interface_t * interface, |
| | | const scpi_unit_def_t * units, |
| | | const char * idn1, const char * idn2, const char * idn3, const char * idn4, |
| | | char * input_buffer, size_t input_buffer_length, |
| | | int16_t * error_queue_data, int16_t error_queue_size) { |
| | | memset(context, 0, sizeof(*context)); |
| | | context->cmdlist = commands; |
| | | context->interface = interface; |
| | | context->units = units; |
| | | context->idn[0] = idn1; |
| | | context->idn[1] = idn2; |
| | | context->idn[2] = idn3; |
| | | context->idn[3] = idn4; |
| | | context->buffer.data = input_buffer; |
| | | context->buffer.length = input_buffer_length; |
| | | context->buffer.position = 0; |
| | | SCPI_ErrorInit(context); |
| | | SCPI_ErrorInit(context, error_queue_data, error_queue_size); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | static void testFifo() { |
| | | scpi_fifo_t fifo; |
| | | fifo_init(&fifo); |
| | | int16_t fifo_data[5]; |
| | | fifo_init(&fifo, fifo_data, 5); |
| | | int16_t value; |
| | | |
| | | fifo.size = 5; |
| | | |
| | | #define TEST_FIFO_COUNT(n) \ |
| | | do { \ |
| | |
| | | #define SCPI_INPUT_BUFFER_LENGTH 256 |
| | | static char scpi_input_buffer[SCPI_INPUT_BUFFER_LENGTH]; |
| | | |
| | | static scpi_reg_val_t scpi_regs[SCPI_REG_COUNT]; |
| | | |
| | | |
| | | scpi_t scpi_context = { |
| | | .cmdlist = scpi_commands, |
| | | .buffer = |
| | | { |
| | | .length = SCPI_INPUT_BUFFER_LENGTH, |
| | | .data = scpi_input_buffer, |
| | | }, |
| | | .interface = &scpi_interface, |
| | | .registers = scpi_regs, |
| | | .units = scpi_units_def, |
| | | .idn = |
| | | {"MA", "IN", NULL, "VER"}, |
| | | }; |
| | | #define SCPI_ERROR_QUEUE_SIZE 5 |
| | | static int16_t scpi_error_queue_data[SCPI_ERROR_QUEUE_SIZE]; |
| | | |
| | | static int init_suite(void) { |
| | | SCPI_Init(&scpi_context); |
| | | SCPI_Init(&scpi_context, |
| | | scpi_commands, |
| | | &scpi_interface, |
| | | scpi_units_def, |
| | | "MA", "IN", NULL, "VER", |
| | | scpi_input_buffer, SCPI_INPUT_BUFFER_LENGTH, |
| | | scpi_error_queue_data, SCPI_ERROR_QUEUE_SIZE); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | } |
| | | |
| | | static void testErrorQueue(void) { |
| | | ((scpi_fifo_t *) (scpi_context.error_queue))->size = 5; |
| | | |
| | | SCPI_ErrorClear(&scpi_context); |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | SCPI_ErrorPush(&scpi_context, -1); |
| | |
| | | CU_ASSERT_EQUAL(SCPI_ErrorCount(&scpi_context), 0); |
| | | |
| | | SCPI_ErrorClear(&scpi_context); |
| | | ((scpi_fifo_t *) (scpi_context.error_queue))->size = FIFO_SIZE; |
| | | } |
| | | |
| | | int main() { |