The basic implementation completed. Tests are needed. (issue #73)
| | |
| | | #endif |
| | | |
| | | #ifndef USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | #define USE_DEVICE_DEPENDENT_ERROR_INFORMATION 1 |
| | | #define USE_DEVICE_DEPENDENT_ERROR_INFORMATION 0 |
| | | #ifndef USE_MEMORY_ALLOCATION_FREE |
| | | #define USE_MEMORY_ALLOCATION_FREE 1 |
| | | #endif |
| | |
| | | #endif |
| | | |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | |
| | | #if USE_MEMORY_ALLOCATION_FREE |
| | | #include <stdlib.h> |
| | | #include <string.h> |
| | | #include <malloc.h> |
| | | #define SCPIDEFINE_DESCRIPTION_MAX_PARTS 2 |
| | | #define SCPIDEFINE_strdup(h, s) strdup((s)) |
| | | #define SCPIDEFINE_free(h, s, r) free((s)) |
| | |
| | | /* 21.8 :ERRor Subsystem |
| | | * The maximum string length of <Error/event_description> plus <Device-dependent_info> is 255 characters. |
| | | */ |
| | | #define SCPI_STD_ERROR_DESC_CHARS_LIMIT 255 |
| | | #define SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH 255 |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | |
| | | 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); |
| | | scpi_bool_t SCPI_ErrorPop(scpi_t * context, scpi_error_t * error); |
| | | 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); |
| | |
| | | typedef scpi_result_t(*scpi_command_callback_t)(scpi_t *); |
| | | |
| | | struct _scpi_error_info_heap_t { |
| | | int16_t wr; |
| | | //int16_t rd; |
| | | int16_t count; |
| | | int16_t size; |
| | | size_t wr; |
| | | //size_t rd; |
| | | size_t count; |
| | | size_t size; |
| | | char * data; |
| | | }; |
| | | typedef struct _scpi_error_info_heap_t scpi_error_info_heap_t; |
| | |
| | | * @param error |
| | | * @return |
| | | */ |
| | | scpi_bool_t SCPI_ErrorPopEx(scpi_t * context, scpi_error_t * error) { |
| | | if(!error) return FALSE; |
| | | scpi_bool_t SCPI_ErrorPop(scpi_t * context, scpi_error_t * error) { |
| | | if(!error || !context) return FALSE; |
| | | error->error_code = 0; |
| | | error->device_dependent_info = NULL; |
| | | fifo_remove(&context->error_queue, error); |
| | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | |
| | | return TRUE; |
| | | } |
| | | /** |
| | | * Pop error from queue |
| | | * @param context - scpi context |
| | | * @return error number |
| | | */ |
| | | int16_t SCPI_ErrorPop(scpi_t * context) { |
| | | int16_t result = 0; |
| | | |
| | | fifo_remove(&context->error_queue, &result); |
| | | |
| | | SCPI_ErrorEmitEmpty(context); |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | |
| | | SCPI_ErrorEmit(context, err); |
| | | if (queue_overflow) { |
| | | SCPI_ErrorEmit(context, SCPI_ERROR_QUEUE_OVERFLOW); |
| | | #if USE_DEVICE_DEPENDENT_ERROR_INFORMATION |
| | | SCPIDEFINE_free(&context->error_info_heap, info_ptr, true); |
| | | #endif |
| | | } |
| | | |
| | | if (context) { |
| | |
| | | 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, NULL); |
| | | // |
| | | //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; |
| | | //} |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return |
| | | */ |
| | | scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) { |
| | | SCPI_ResultInt32(context,context->error_info_heap.count); |
| | | |
| | | scpi_error_t error; |
| | | SCPI_ErrorPopEx(context, &error); |
| | | SCPI_ErrorPop(context, &error); |
| | | SCPI_ResultError(context, &error); |
| | | |
| | | SCPI_ResultInt32(context,context->error_info_heap.count); |
| | | return SCPI_RES_OK; |
| | | |
| | | } |
| | | |
| | | /** |
| | |
| | | result &= processCommand(context); |
| | | cmd_prev = state->programHeader; |
| | | } else { |
| | | //SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
| | | /* test */ |
| | | data[r-1]=0; |
| | | /* place undefined header with error */ |
| | | data[r?(r-1):r]=0; |
| | | SCPI_ErrorPushEx(context, SCPI_ERROR_UNDEFINED_HEADER, data); |
| | | //SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
| | | result = FALSE; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Write string withn " to the result |
| | | * SCPI-99:21.8 Device-dependent error information. |
| | | * Write error information with the following syntax: |
| | | * <Error/event_number>,"<Error/event_description>[;<Device-dependent_info>]" |
| | | * The maximum string length of <Error/event_description> plus <Device-dependent_info> |
| | | * is SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH (255) characters. |
| | | * |
| | | * @param context |
| | | * @param data |
| | | * @param error |
| | | * @return |
| | | */ |
| | | static size_t outputlimit_0=0; |
| | | size_t SCPI_ResultError(scpi_t * context, scpi_error_t * error) { |
| | | size_t result = 0; |
| | | size_t outputlimit = outputlimit_0++; //SCPI_STD_ERROR_DESC_CHARS_LIMIT; |
| | | size_t outputlimit = SCPI_STD_ERROR_DESC_MAX_STRING_LENGTH; |
| | | size_t step = 0; |
| | | const char * quote; |
| | | |
| | |
| | | if(!s || !heap) { |
| | | return NULL; |
| | | } |
| | | |
| | | if(heap->data[heap->wr]!='\0'){ |
| | | return NULL; |
| | | } |
| | | |
| | | size_t len=strlen(s) + 1; // additional '\0' at end |
| | | if(len > heap->count){ |
| | | size_t len=strlen(s); |
| | | if( ( len == 0 ) || ( len > heap->count ) ){ |
| | | return NULL; |
| | | } |
| | | len++; // additional '\0' at end |
| | | char * ptrs = s; |
| | | char * head = &heap->data[heap->wr]; |
| | | size_t rem = heap->size - (&heap->data[heap->wr]-heap->data); |
| | |
| | | |
| | | if( !OUR_get_parts( heap, s, &len[0], &data_add, &len[1] ) ) return; |
| | | |
| | | |
| | | if(data_add) { |
| | | len[1]++; |
| | | memset(data_add,0,len[1]); |
| | |
| | | } |
| | | memset(s,0,len[0]); |
| | | heap->count += len[0]; |
| | | if( heap->count == heap->size){ |
| | | heap->wr = 0; |
| | | return; |
| | | } |
| | | if(rollback){ |
| | | heap->wr-=len[0]; |
| | | heap->wr-=len[1]; |
| | | if(heap->wr < 0)heap->wr += heap->size; |
| | | size_t rb = len[0] + len[1]; |
| | | if( rb > heap->wr){ |
| | | heap->wr += heap->size; |
| | | } |
| | | heap->wr -= rb; |
| | | } |
| | | } |
| | | |