| | |
| | | #define USE_USER_ERROR_LIST 0 |
| | | #endif |
| | | |
| | | #ifndef USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #define USE_DEVICE_DEPENDENT_ERROR_INFORMATION 1 |
| | | #endif |
| | | |
| | | #ifndef USE_MEMORY_ALLOCATION_FREE |
| | | #define USE_MEMORY_ALLOCATION_FREE 1 |
| | | #endif |
| | | |
| | | #ifndef USE_COMMAND_TAGS |
| | | #define USE_COMMAND_TAGS 1 |
| | | #endif |
| | |
| | | #define SCPIDEFINE_doubleToStr(v, s, l) snprintf((s), (l), "%.15lg", (v)) |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | #include <string.h> |
| | | #include <malloc.h> |
| | | #define SCPIDEFINE_strdup(s) strdup((s)) |
| | | #define SCPIDEFINE_free(s) free((s)) |
| | | #else |
| | | #define SCPIDEFINE_strdup(s) NULL |
| | | #define SCPIDEFINE_free(s) NULL |
| | | #endif |
| | | #else |
| | | #define SCPIDEFINE_strdup(s) NULL |
| | | #define SCPIDEFINE_free(s) NULL |
| | | #endif |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size); |
| | | void SCPI_ErrorInit(scpi_t * context, scpi_error_t * data, int16_t size); |
| | | void SCPI_ErrorClear(scpi_t * context); |
| | | scpi_bool_t SCPI_ErrorPopEx(scpi_t * context, scpi_error_t * error); |
| | | int16_t SCPI_ErrorPop(scpi_t * context); |
| | | void SCPI_ErrorPushEx(scpi_t * context, int16_t err, char * info); |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err); |
| | | int32_t SCPI_ErrorCount(scpi_t * context); |
| | | const char * SCPI_ErrorTranslate(int16_t err); |
| | |
| | | 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_error_t * error_queue_data, int16_t error_queue_size, |
| | | char * error_info_heap, size_t error_info_heap_length); |
| | | |
| | | 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 *); |
| | | |
| | | struct _scpi_error_info_heap_t { |
| | | size_t length; |
| | | size_t position; |
| | | char * data; |
| | | }; |
| | | typedef struct _scpi_error_info_heap_t scpi_error_info_heap_t; |
| | | |
| | | struct _scpi_error_t { |
| | | int16_t error_code; |
| | | const char * device_dependent_info; |
| | | }; |
| | | typedef struct _scpi_error_t scpi_error_t; |
| | | |
| | | struct _scpi_fifo_t { |
| | | int16_t wr; |
| | | int16_t rd; |
| | | int16_t count; |
| | | int16_t size; |
| | | int16_t * data; |
| | | scpi_error_t * data; |
| | | }; |
| | | typedef struct _scpi_fifo_t scpi_fifo_t; |
| | | |
| | |
| | | int_fast16_t input_count; |
| | | scpi_bool_t cmd_error; |
| | | scpi_fifo_t error_queue; |
| | | scpi_error_info_heap_t error_info_heap; |
| | | scpi_reg_val_t registers[SCPI_REG_COUNT]; |
| | | const scpi_unit_def_t * units; |
| | | void * user_context; |
| | |
| | | * Initialize error queue |
| | | * @param context - scpi context |
| | | */ |
| | | void SCPI_ErrorInit(scpi_t * context, int16_t * data, int16_t size) { |
| | | void SCPI_ErrorInit(scpi_t * context, scpi_error_t * data, int16_t size) { |
| | | fifo_init(&context->error_queue, data, size); |
| | | } |
| | | |
| | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | } |
| | | |
| | | |
| | | scpi_bool_t SCPI_ErrorPopEx(scpi_t * context, scpi_error_t * error) { |
| | | if(error == NULL) return FALSE; |
| | | |
| | | fifo_remove(&context->error_queue, error); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | |
| | | return TRUE; |
| | | } |
| | | /** |
| | | * Pop error from queue |
| | | * @param context - scpi context |
| | |
| | | return result; |
| | | } |
| | | |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { |
| | | if (!fifo_add(&context->error_queue, err)) { |
| | | static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info) { |
| | | if (!fifo_add(&context->error_queue, err, info)) { |
| | | fifo_remove_last(&context->error_queue, NULL); |
| | | fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW, NULL); |
| | | return FALSE; |
| | | } |
| | | return TRUE; |
| | |
| | | * @param context - scpi context |
| | | * @param err - error number |
| | | */ |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err) { |
| | | void SCPI_ErrorPushEx(scpi_t * context, int16_t err, char * info) { |
| | | int i; |
| | | char * info_ptr=SCPIDEFINE_strdup(info); |
| | | scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err, info_ptr); |
| | | |
| | | for (i = 0; i < ERROR_DEFS_N; i++) { |
| | | if ((err <= errs[i].from) && (err >= errs[i].to)) { |
| | | SCPI_RegSetBits(context, SCPI_REG_ESR, errs[i].bit); |
| | | } |
| | | } |
| | | |
| | | SCPI_ErrorEmit(context, err); |
| | | if (queue_overflow) { |
| | | SCPI_ErrorEmit(context, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | } |
| | | |
| | | if (context) { |
| | | context->cmd_error = TRUE; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Push error to queue |
| | | * @param context - scpi context |
| | | * @param err - error number |
| | | */ |
| | | void SCPI_ErrorPush(scpi_t * context, int16_t err) { |
| | | SCPI_ErrorPushEx(context, err, NULL); |
| | | return; |
| | | int i; |
| | | |
| | | scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err); |
| | | scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err, NULL); |
| | | |
| | | for (i = 0; i < ERROR_DEFS_N; i++) { |
| | | if ((err <= errs[i].from) && (err >= errs[i].to)) { |
| | |
| | | * Initialize fifo |
| | | * @param fifo |
| | | */ |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) { |
| | | void fifo_init(scpi_fifo_t * fifo, scpi_error_t * data, int16_t size) { |
| | | fifo->wr = 0; |
| | | fifo->rd = 0; |
| | | fifo->count = 0; |
| | |
| | | /** |
| | | * Add element to fifo. If fifo is full, return FALSE. |
| | | * @param fifo |
| | | * @param value |
| | | * @param err |
| | | * @param info |
| | | * @return |
| | | */ |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) { |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t err, char * info) { |
| | | /* FIFO full? */ |
| | | if (fifo_is_full(fifo)) { |
| | | return FALSE; |
| | | } |
| | | |
| | | fifo->data[fifo->wr] = value; |
| | | fifo->data[fifo->wr].error_code = err; |
| | | fifo->data[fifo->wr].device_dependent_info = info; |
| | | fifo->wr = (fifo->wr + 1) % (fifo->size); |
| | | fifo->count += 1; |
| | | return TRUE; |
| | |
| | | * @param value |
| | | * @return FALSE - fifo is empty |
| | | */ |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) { |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, scpi_error_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | |
| | | * @param value |
| | | * @return FALSE - fifo is empty |
| | | */ |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) { |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, scpi_error_t * value) { |
| | | /* FIFO empty? */ |
| | | if (fifo_is_empty(fifo)) { |
| | | return FALSE; |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | void fifo_init(scpi_fifo_t * fifo, int16_t * data, int16_t size) LOCAL; |
| | | void fifo_init(scpi_fifo_t * fifo, scpi_error_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; |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t value) LOCAL; |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | scpi_bool_t fifo_add(scpi_fifo_t * fifo, int16_t err, char * info) LOCAL; |
| | | scpi_bool_t fifo_remove(scpi_fifo_t * fifo, scpi_error_t * value) LOCAL; |
| | | scpi_bool_t fifo_remove_last(scpi_fifo_t * fifo, scpi_error_t * value) LOCAL; |
| | | scpi_bool_t fifo_count(scpi_fifo_t * fifo, int16_t * value) LOCAL; |
| | | |
| | | #ifdef __cplusplus |
| | |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) { |
| | | int16_t err = SCPI_ErrorPop(context); |
| | | scpi_error_t error; |
| | | if(!SCPI_ErrorPopEx(context, &error))return SCPI_RES_ERR; |
| | | |
| | | SCPI_ResultInt32(context, err); |
| | | SCPI_ResultText(context, SCPI_ErrorTranslate(err)); |
| | | //int16_t err = SCPI_ErrorPop(context); |
| | | |
| | | SCPI_ResultInt32(context, error.error_code); |
| | | SCPI_ResultText(context, SCPI_ErrorTranslate(error.error_code)); |
| | | |
| | | size_t info_len=0; |
| | | if(error.device_dependent_info){ |
| | | info_len=SCPIDEFINE_strnlen(error.device_dependent_info,255); |
| | | SCPI_ResultCharacters(context, ";", 1); |
| | | SCPI_ResultText(context, error.device_dependent_info); |
| | | SCPIDEFINE_free(error.device_dependent_info); |
| | | } |
| | | |
| | | |
| | | |
| | | return SCPI_RES_OK; |
| | | } |
| | |
| | | result &= processCommand(context); |
| | | cmd_prev = state->programHeader; |
| | | } else { |
| | | SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
| | | //SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
| | | /* test */ |
| | | data[r-1]=0; |
| | | SCPI_ErrorPushEx(context, SCPI_ERROR_UNDEFINED_HEADER, data); |
| | | result = FALSE; |
| | | } |
| | | } |
| | |
| | | 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_error_t * error_queue_data, int16_t error_queue_size, |
| | | char * error_info_heap, size_t error_info_heap_length) { |
| | | memset(context, 0, sizeof(*context)); |
| | | context->cmdlist = commands; |
| | | context->interface = interface; |
| | |
| | | context->buffer.data = input_buffer; |
| | | context->buffer.length = input_buffer_length; |
| | | context->buffer.position = 0; |
| | | context->error_info_heap.data = error_info_heap; |
| | | context->error_info_heap.position = 0; |
| | | context->error_info_heap.length = error_info_heap_length; |
| | | SCPI_ErrorInit(context, error_queue_data, error_queue_size); |
| | | } |
| | | |