scpi-parser, adopted from github
Revision 0:d8aca47812e0, committed 2014-11-14
- Comitter:
- iesensor
- Date:
- Fri Nov 14 01:07:59 2014 +0000
- Commit message:
- tested on K64F
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/scpi-def.cpp Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,177 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi-def.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI parser test + * + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "scpi/scpi.h" +#include "scpi-def.h" + +scpi_result_t DMM_MeasureVoltageDcQ(scpi_t * context) { + scpi_number_t param1, param2; + char bf[15]; + fprintf(stderr, "meas:volt:dc\r\n"); // debug command name + + // read first parameter if present + if (!SCPI_ParamNumber(context, ¶m1, false)) { + // do something, if parameter not present + } + + // read second paraeter if present + if (!SCPI_ParamNumber(context, ¶m2, false)) { + // do something, if parameter not present + } + + + SCPI_NumberToStr(context, ¶m1, bf, 15); + fprintf(stderr, "\tP1=%s\r\n", bf); + + + SCPI_NumberToStr(context, ¶m2, bf, 15); + fprintf(stderr, "\tP2=%s\r\n", bf); + + SCPI_ResultDouble(context, 0); + + return SCPI_RES_OK; +} + + +scpi_result_t DMM_ConfigureVoltageDc(scpi_t * context) { + double param1, param2; + fprintf(stderr, "conf:volt:dc\r\n"); // debug command name + + // read first parameter if present + if (!SCPI_ParamDouble(context, ¶m1, true)) { + return SCPI_RES_ERR; + } + + // read second paraeter if present + if (!SCPI_ParamDouble(context, ¶m2, false)) { + // do something, if parameter not present + } + + fprintf(stderr, "\tP1=%lf\r\n", param1); + fprintf(stderr, "\tP2=%lf\r\n", param2); + + return SCPI_RES_OK; +} + +static const scpi_command_t scpi_commands[] = { + /* {"pattern", callback} * + + /* IEEE Mandated Commands (SCPI std V1999.0 4.1.1) */ + {"*CLS", SCPI_CoreCls,}, + {"*ESE", SCPI_CoreEse,}, + {"*ESE?", SCPI_CoreEseQ,}, + {"*ESR?", SCPI_CoreEsrQ,}, + {"*IDN?", SCPI_CoreIdnQ,}, + {"*OPC", SCPI_CoreOpc,}, + {"*OPC?", SCPI_CoreOpcQ,}, + {"*RST", SCPI_CoreRst,}, + {"*SRE", SCPI_CoreSre,}, + {"*SRE?", SCPI_CoreSreQ,}, + {"*STB?", SCPI_CoreStbQ,}, + {"*TST?", SCPI_CoreTstQ,}, + {"*WAI", SCPI_CoreWai,}, + + /* Required SCPI commands (SCPI std V1999.0 4.2.1) */ + {"SYSTem:ERRor?", SCPI_SystemErrorNextQ,}, + {"SYSTem:ERRor:NEXT?", SCPI_SystemErrorNextQ,}, + {"SYSTem:ERRor:COUNt?", SCPI_SystemErrorCountQ,}, + {"SYSTem:VERSion?", SCPI_SystemVersionQ,}, + + //{"STATus:OPERation?", scpi_stub_callback,}, + //{"STATus:OPERation:EVENt?", scpi_stub_callback,}, + //{"STATus:OPERation:CONDition?", scpi_stub_callback,}, + //{"STATus:OPERation:ENABle", scpi_stub_callback,}, + //{"STATus:OPERation:ENABle?", scpi_stub_callback,}, + + {"STATus:QUEStionable?", SCPI_StatusQuestionableEventQ,}, + {"STATus:QUEStionable:EVENt?", SCPI_StatusQuestionableEventQ,}, + //{"STATus:QUEStionable:CONDition?", scpi_stub_callback,}, + {"STATus:QUEStionable:ENABle", SCPI_StatusQuestionableEnable,}, + {"STATus:QUEStionable:ENABle?", SCPI_StatusQuestionableEnableQ,}, + + {"STATus:PRESet", SCPI_StatusPreset,}, + + /* DMM */ + {"MEASure:VOLTage:DC?", DMM_MeasureVoltageDcQ,}, + {"CONFigure:VOLTage:DC", DMM_ConfigureVoltageDc,}, + {"MEASure:VOLTage:DC:RATio?", SCPI_StubQ,}, + {"MEASure:VOLTage:AC?", SCPI_StubQ,}, + {"MEASure:CURRent:DC?", SCPI_StubQ,}, + {"MEASure:CURRent:AC?", SCPI_StubQ,}, + {"MEASure:RESistance?", SCPI_StubQ,}, + {"MEASure:FRESistance?", SCPI_StubQ,}, + {"MEASure:FREQuency?", SCPI_StubQ,}, + {"MEASure:PERiod?", SCPI_StubQ,}, + + {"SYSTem:COMMunication:TCPIP:CONTROL?", SCPI_SystemCommTcpipControlQ,}, + + SCPI_CMD_LIST_END +}; + +static scpi_interface_t scpi_interface = { + /* error */ SCPI_Error, + /* write */ SCPI_Write, + /* control */ SCPI_Control, + /* flush */ SCPI_Flush, + /* reset */ SCPI_Reset, + /* test */ SCPI_Test, +}; + +#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, /* position */ 0, /* data */ scpi_input_buffer, }, + /* paramlist */ { /* cmd */ NULL, /* parameters */ NULL, /* length */ 0, }, + /* interface */ &scpi_interface, + /* output_count */ 0, + /* input_count */ 0, + /* cmd_error */ FALSE, + /* error_queue */ NULL, + /* registers */ scpi_regs, + /* units */ scpi_units_def, + /* special_numbers */ scpi_special_numbers_def, + /* user_context */ NULL, + /* idn */ {"MANUFACTURE", "INSTR2013", NULL, "01-02"}, +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/scpi-def.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,27 @@ +#ifndef __SCPI_DEF_H_ +#define __SCPI_DEF_H_ + +#include "scpi/scpi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern scpi_t scpi_context; + +size_t SCPI_Write(scpi_t * context, const char * data, size_t len); +int SCPI_Error(scpi_t * context, int_fast16_t err); +scpi_result_t SCPI_Control(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val); +scpi_result_t SCPI_Reset(scpi_t * context); +scpi_result_t SCPI_Test(scpi_t * context); +scpi_result_t SCPI_Flush(scpi_t * context); + + +scpi_result_t SCPI_SystemCommTcpipControlQ(scpi_t * context); + +#ifdef __cplusplus +} +#endif + +#endif // __SCPI_DEF_H_ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/debug.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,53 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_debug.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Debugging SCPI + * + * + */ + +#include <stdio.h> +#include "scpi/debug.h" + +/** + * Debug function: show current command and its parameters + * @param context + * @return + */ +scpi_bool_t SCPI_DebugCommand(scpi_t * context) { + size_t res; + printf("**DEBUG: %s (\"", context->paramlist.cmd->pattern); + res = fwrite(context->paramlist.parameters, 1, context->paramlist.length, stdout); + (void)res; + printf("\" - %lu\r\n", (unsigned long)context->paramlist.length); + + return TRUE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/error.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,184 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_error.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Error handling and storing routines + * + * + */ + +#include <stdint.h> + +#include "scpi/parser.h" +#include "scpi/ieee488.h" +#include "scpi/error.h" +#include "scpi/fifo.h" + +/* basic FIFO */ +static fifo_t local_error_queue; + + + +void SCPI_ErrorInit(scpi_t * context) { + /* + * // FreeRTOS + * context->error_queue = (scpi_error_queue_t)xQueueCreate(100, sizeof(int16_t)); + */ + + /* basic FIFO */ + context->error_queue = (scpi_error_queue_t)&local_error_queue; + fifo_init((fifo_t *)context->error_queue); +} + +/** + * Clear error queue + * @param context - scpi context + */ +void SCPI_ErrorClear(scpi_t * context) { + /* + * // FreeRTOS + * xQueueReset((xQueueHandle)context->error_queue); + */ + + /* basic FIFO */ + fifo_clear((fifo_t *)context->error_queue); +} + +/** + * Pop error from queue + * @param context - scpi context + * @return error number + */ +int16_t SCPI_ErrorPop(scpi_t * context) { + int16_t result = 0; + + /* + * // FreeRTOS + * if (pdFALSE == xQueueReceive((xQueueHandle)context->error_queue, &result, 0)) { + * result = 0; + * } + */ + + /* basic FIFO */ + fifo_remove((fifo_t *)context->error_queue, &result); + + return result; +} + +/** + * Return number of errors/events in the queue + * @param context + * @return + */ +int32_t SCPI_ErrorCount(scpi_t * context) { + int16_t result = 0; + + /* + * // FreeRTOS + * result = uxQueueMessagesWaiting((xQueueHandle)context->error_queue); + */ + + /* basic FIFO */ + fifo_count((fifo_t *)context->error_queue, &result); + + return result; +} + +static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) { + /* + * // FreeRTOS + * xQueueSend((xQueueHandle)context->error_queue, &err, 0); + */ + + /* basic FIFO */ + fifo_add((fifo_t *)context->error_queue, err); +} + +struct error_reg { + int16_t from; + int16_t to; + scpi_reg_val_t bit; +}; + +#define ERROR_DEFS_N 8 + +static const struct error_reg errs[ERROR_DEFS_N] = { + {-100, -199, ESR_CER}, /* Command error (e.g. syntax error) ch 21.8.9 */ + {-200, -299, ESR_EER}, /* Execution Error (e.g. range error) ch 21.8.10 */ + {-300, -399, ESR_DER}, /* Device specific error -300, -399 ch 21.8.11 */ + {-400, -499, ESR_QER}, /* Query error -400, -499 ch 21.8.12 */ + {-500, -599, ESR_PON}, /* Power on event -500, -599 ch 21.8.13 */ + {-600, -699, ESR_URQ}, /* User Request Event -600, -699 ch 21.8.14 */ + {-700, -799, ESR_REQ}, /* Request Control Event -700, -799 ch 21.8.15 */ + {-800, -899, ESR_OPC}, /* Operation Complete Event -800, -899 ch 21.8.16 */ +}; + +/** + * Push error to queue + * @param context - scpi context + * @param err - error number + */ +void SCPI_ErrorPush(scpi_t * context, int16_t err) { + + int i; + + SCPI_ErrorAddInternal(context, err); + + 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); + } + } + + if (context) { + if (context->interface && context->interface->error) { + context->interface->error(context, err); + } + + context->cmd_error = TRUE; + } +} + +/** + * Translate error number to string + * @param err - error number + * @return Error string representation + */ +const char * SCPI_ErrorTranslate(int16_t err) { + switch (err) { + case 0: return "No error"; + #define X(def, val, str) case def: return str; + LIST_OF_ERRORS + #undef X + default: return "Unknown error"; + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/fifo.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,48 @@ + +#include "scpi/fifo.h" + +void fifo_init(fifo_t * fifo) { + fifo->wr = 0; + fifo->rd = 0; + fifo->size = FIFO_SIZE; +} + +void fifo_clear(fifo_t * fifo) { + fifo->wr = 0; + fifo->rd = 0; +} + +scpi_bool_t fifo_add(fifo_t * fifo, int16_t value) { + /* FIFO full? */ + if (fifo->wr == ((fifo->rd + fifo->size) % (fifo->size + 1))) { + fifo_remove(fifo, NULL); + } + + fifo->data[fifo->wr] = value; + fifo->wr = (fifo->wr + 1) % (fifo->size + 1); + + return TRUE; +} + +scpi_bool_t fifo_remove(fifo_t * fifo, int16_t * value) { + /* FIFO empty? */ + if (fifo->wr == fifo->rd) { + return FALSE; + } + + if(value) { + *value = fifo->data[fifo->rd]; + } + + fifo->rd = (fifo->rd + 1) % (fifo->size + 1); + + return TRUE; +} + +scpi_bool_t fifo_count(fifo_t * fifo, int16_t * value) { + *value = fifo->wr - fifo->rd; + if (*value < 0) { + *value += (fifo->size + 1); + } + return TRUE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/ieee488.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,350 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_ieee488.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Implementation of IEEE488.2 commands and state model + * + * + */ + +#include "scpi/parser.h" +#include "scpi/ieee488.h" +#include "scpi/error.h" +#include "scpi/constants.h" + +#include <stdio.h> + +/** + * Update register value + * @param context + * @param name - register name + */ +static void regUpdate(scpi_t * context, scpi_reg_name_t name) { + SCPI_RegSet(context, name, SCPI_RegGet(context, name)); +} + +/** + * Update STB register according to value and its mask register + * @param context + * @param val value of register + * @param mask name of mask register (enable register) + * @param stbBits bits to clear or set in STB + */ +static void regUpdateSTB(scpi_t * context, scpi_reg_val_t val, scpi_reg_name_t mask, scpi_reg_val_t stbBits) { + if (val & SCPI_RegGet(context, mask)) { + SCPI_RegSetBits(context, SCPI_REG_STB, stbBits); + } else { + SCPI_RegClearBits(context, SCPI_REG_STB, stbBits); + } +} + +/** + * Get register value + * @param name - register name + * @return register value + */ +scpi_reg_val_t SCPI_RegGet(scpi_t * context, scpi_reg_name_t name) { + if ((name < SCPI_REG_COUNT) && (context->registers != NULL)) { + return context->registers[name]; + } else { + return 0; + } +} + +/** + * Wrapper function to control interface from context + * @param context + * @param ctrl number of controll message + * @param value value of related register + */ +static size_t writeControl(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val) { + if (context && context->interface && context->interface->control) { + return context->interface->control(context, ctrl, val); + } else { + return 0; + } +} + +/** + * Set register value + * @param name - register name + * @param val - new value + */ +void SCPI_RegSet(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t val) { + scpi_bool_t srq = FALSE; + scpi_reg_val_t mask; + scpi_reg_val_t old_val; + + if ((name >= SCPI_REG_COUNT) || (context->registers == NULL)) { + return; + } + + /* store old register value */ + old_val = context->registers[name]; + + /* set register value */ + context->registers[name] = val; + + /** @TODO: remove recutsion */ + switch (name) { + case SCPI_REG_STB: + mask = SCPI_RegGet(context, SCPI_REG_SRE); + mask &= ~STB_SRQ; + if (val & mask) { + val |= STB_SRQ; + /* avoid sending SRQ if nothing has changed */ + if (old_val != val) { + srq = TRUE; + } + } else { + val &= ~STB_SRQ; + } + break; + case SCPI_REG_SRE: + regUpdate(context, SCPI_REG_STB); + break; + case SCPI_REG_ESR: + regUpdateSTB(context, val, SCPI_REG_ESE, STB_ESR); + break; + case SCPI_REG_ESE: + regUpdate(context, SCPI_REG_ESR); + break; + case SCPI_REG_QUES: + regUpdateSTB(context, val, SCPI_REG_QUESE, STB_QES); + break; + case SCPI_REG_QUESE: + regUpdate(context, SCPI_REG_QUES); + break; + case SCPI_REG_OPER: + regUpdateSTB(context, val, SCPI_REG_OPERE, STB_OPS); + break; + case SCPI_REG_OPERE: + regUpdate(context, SCPI_REG_OPER); + break; + + + case SCPI_REG_COUNT: + /* nothing to do */ + break; + } + + /* set updated register value */ + context->registers[name] = val; + + if (srq) { + writeControl(context, SCPI_CTRL_SRQ, SCPI_RegGet(context, SCPI_REG_STB)); + } +} + +/** + * Set register bits + * @param name - register name + * @param bits bit mask + */ +void SCPI_RegSetBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits) { + SCPI_RegSet(context, name, SCPI_RegGet(context, name) | bits); +} + +/** + * Clear register bits + * @param name - register name + * @param bits bit mask + */ +void SCPI_RegClearBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits) { + SCPI_RegSet(context, name, SCPI_RegGet(context, name) & ~bits); +} + +/** + * Clear event register + * @param context + */ +void SCPI_EventClear(scpi_t * context) { + /* TODO */ + SCPI_RegSet(context, SCPI_REG_ESR, 0); +} + +/** + * *CLS - This command clears all status data structures in a device. + * For a device which minimally complies with SCPI. (SCPI std 4.1.3.2) + * @param context + * @return + */ +scpi_result_t SCPI_CoreCls(scpi_t * context) { + SCPI_EventClear(context); + SCPI_ErrorClear(context); + SCPI_RegSet(context, SCPI_REG_OPER, 0); + SCPI_RegSet(context, SCPI_REG_QUES, 0); + return SCPI_RES_OK; +} + +/** + * *ESE + * @param context + * @return + */ +scpi_result_t SCPI_CoreEse(scpi_t * context) { + int32_t new_ESE; + if (SCPI_ParamInt(context, &new_ESE, TRUE)) { + SCPI_RegSet(context, SCPI_REG_ESE, new_ESE); + } + return SCPI_RES_OK; +} + +/** + * *ESE? + * @param context + * @return + */ +scpi_result_t SCPI_CoreEseQ(scpi_t * context) { + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_ESE)); + return SCPI_RES_OK; +} + +/** + * *ESR? + * @param context + * @return + */ +scpi_result_t SCPI_CoreEsrQ(scpi_t * context) { + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_ESR)); + SCPI_RegSet(context, SCPI_REG_ESR, 0); + return SCPI_RES_OK; +} + +/** + * *IDN? + * + * field1: MANUFACTURE + * field2: MODEL + * field4: SUBSYSTEMS REVISIONS + * + * example: MANUFACTURE,MODEL,0,01-02-01 + * @param context + * @return + */ +scpi_result_t SCPI_CoreIdnQ(scpi_t * context) { + SCPI_ResultString(context, context->idn[0]); + SCPI_ResultString(context, context->idn[1]); + SCPI_ResultString(context, context->idn[2]); + SCPI_ResultString(context, context->idn[3]); + return SCPI_RES_OK; +} + +/** + * *OPC + * @param context + * @return + */ +scpi_result_t SCPI_CoreOpc(scpi_t * context) { + SCPI_RegSetBits(context, SCPI_REG_ESR, ESR_OPC); + return SCPI_RES_OK; +} + +/** + * *OPC? + * @param context + * @return + */ +scpi_result_t SCPI_CoreOpcQ(scpi_t * context) { + /* Operation is always completed */ + SCPI_ResultInt(context, 1); + return SCPI_RES_OK; +} + +/** + * *RST + * @param context + * @return + */ +scpi_result_t SCPI_CoreRst(scpi_t * context) { + if (context && context->interface && context->interface->reset) { + return context->interface->reset(context); + } + return SCPI_RES_OK; +} + +/** + * *SRE + * @param context + * @return + */ +scpi_result_t SCPI_CoreSre(scpi_t * context) { + int32_t new_SRE; + if (SCPI_ParamInt(context, &new_SRE, TRUE)) { + SCPI_RegSet(context, SCPI_REG_SRE, new_SRE); + } + return SCPI_RES_OK; +} + +/** + * *SRE? + * @param context + * @return + */ +scpi_result_t SCPI_CoreSreQ(scpi_t * context) { + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_SRE)); + return SCPI_RES_OK; +} + +/** + * *STB? + * @param context + * @return + */ +scpi_result_t SCPI_CoreStbQ(scpi_t * context) { + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_STB)); + return SCPI_RES_OK; +} + +/** + * *TST? + * @param context + * @return + */ +scpi_result_t SCPI_CoreTstQ(scpi_t * context) { + int result = 0; + if (context && context->interface && context->interface->test) { + result = context->interface->test(context); + } + SCPI_ResultInt(context, result); + return SCPI_RES_OK; +} + +/** + * *WAI + * @param context + * @return + */ +scpi_result_t SCPI_CoreWai(scpi_t * context) { + (void) context; + /* NOP */ + return SCPI_RES_OK; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/minimal.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,148 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_minimal.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI minimal implementation + * + * + */ + + +#include "scpi/parser.h" +#include "scpi/minimal.h" +#include "scpi/constants.h" +#include "scpi/error.h" +#include "scpi/ieee488.h" + +/** + * Command stub function + * @param context + * @return + */ +scpi_result_t SCPI_Stub(scpi_t * context) { + (void) context; + return SCPI_RES_OK; +} + +/** + * Query command stub function + * @param context + * @return + */ +scpi_result_t SCPI_StubQ(scpi_t * context) { + SCPI_ResultString(context, ""); + return SCPI_RES_OK; +} + +/** + * SYSTem:VERSion? + * @param context + * @return + */ +scpi_result_t SCPI_SystemVersionQ(scpi_t * context) { + SCPI_ResultString(context, SCPI_STD_VERSION_REVISION); + return SCPI_RES_OK; +} + +/** + * SYSTem:ERRor[:NEXT]? + * @param context + * @return + */ +scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context) { + int16_t err = SCPI_ErrorPop(context); + + SCPI_ResultInt(context, err); + SCPI_ResultText(context, SCPI_ErrorTranslate(err)); + + return SCPI_RES_OK; +} + +/** + * SYSTem:ERRor:COUNt? + * @param context + * @return + */ +scpi_result_t SCPI_SystemErrorCountQ(scpi_t * context) { + SCPI_ResultInt(context, SCPI_ErrorCount(context)); + + return SCPI_RES_OK; +} + +/** + * STATus:QUEStionable[:EVENt]? + * @param context + * @return + */ +scpi_result_t SCPI_StatusQuestionableEventQ(scpi_t * context) { + /* return value */ + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_QUES)); + + /* clear register */ + SCPI_RegSet(context, SCPI_REG_QUES, 0); + + return SCPI_RES_OK; +} + +/** + * STATus:QUEStionable:ENABle? + * @param context + * @return + */ +scpi_result_t SCPI_StatusQuestionableEnableQ(scpi_t * context) { + /* return value */ + SCPI_ResultInt(context, SCPI_RegGet(context, SCPI_REG_QUESE)); + + return SCPI_RES_OK; +} + +/** + * STATus:QUEStionable:ENABle + * @param context + * @return + */ +scpi_result_t SCPI_StatusQuestionableEnable(scpi_t * context) { + int32_t new_QUESE; + if (SCPI_ParamInt(context, &new_QUESE, TRUE)) { + SCPI_RegSet(context, SCPI_REG_QUESE, new_QUESE); + } + return SCPI_RES_OK; +} + +/** + * STATus:PRESet + * @param context + * @return + */ +scpi_result_t SCPI_StatusPreset(scpi_t * context) { + /* clear STATUS:... */ + SCPI_RegSet(context, SCPI_REG_QUES, 0); + return SCPI_RES_OK; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/parser.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,677 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_parser.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI parser implementation + * + * + */ + +#include <ctype.h> +#include <string.h> + +#include "scpi/config.h" +#include "scpi/parser.h" +#include "scpi/utils_private.h" +#include "scpi/error.h" +#include "scpi/constants.h" + + +static size_t cmdTerminatorPos(const char * cmd, size_t len); +static size_t cmdlineSeparatorPos(const char * cmd, size_t len); +static const char * cmdlineSeparator(const char * cmd, size_t len); +static const char * cmdlineTerminator(const char * cmd, size_t len); +static size_t skipCmdLine(const char * cmd, size_t len); + +static void paramSkipBytes(scpi_t * context, size_t num); +static void paramSkipWhitespace(scpi_t * context); +static scpi_bool_t paramNext(scpi_t * context, scpi_bool_t mandatory); + +/* +int _strnicmp(const char* s1, const char* s2, size_t len) { + int result = 0; + int i; + + for (i = 0; i < len && s1[i] && s2[i]; i++) { + char c1 = tolower(s1[i]); + char c2 = tolower(s2[i]); + if (c1 != c2) { + result = (int) c1 - (int) c2; + break; + } + } + + return result; +} + */ + +/** + * Find command termination character + * @param cmd - input command + * @param len - max search length + * @return position of terminator or len + */ +size_t cmdTerminatorPos(const char * cmd, size_t len) { + const char * terminator = strnpbrk(cmd, len, "; \r\n\t"); + if (terminator == NULL) { + return len; + } else { + return terminator - cmd; + } +} + +/** + * Find command line separator + * @param cmd - input command + * @param len - max search length + * @return pointer to line separator or NULL + */ +const char * cmdlineSeparator(const char * cmd, size_t len) { + return strnpbrk(cmd, len, ";\r\n"); +} + +/** + * Find command line terminator + * @param cmd - input command + * @param len - max search length + * @return pointer to command line terminator or NULL + */ +const char * cmdlineTerminator(const char * cmd, size_t len) { + return strnpbrk(cmd, len, "\r\n"); +} + +/** + * Find command line separator position + * @param cmd - input command + * @param len - max search length + * @return position of line separator or len + */ +size_t cmdlineSeparatorPos(const char * cmd, size_t len) { + const char * separator = cmdlineSeparator(cmd, len); + if (separator == NULL) { + return len; + } else { + return separator - cmd; + } +} + +/** + * Find next part of command + * @param cmd - input command + * @param len - max search length + * @return number of characters to be skipped + */ +size_t skipCmdLine(const char * cmd, size_t len) { + const char * separator = cmdlineSeparator(cmd, len); + if (separator == NULL) { + return len; + } else { + return separator + 1 - cmd; + } +} + +/** + * Write data to SCPI output + * @param context + * @param data + * @param len - lenght of data to be written + * @return number of bytes written + */ +static size_t writeData(scpi_t * context, const char * data, size_t len) { + return context->interface->write(context, data, len); +} + +/** + * Flush data to SCPI output + * @param context + * @return + */ +static int flushData(scpi_t * context) { + if (context && context->interface && context->interface->flush) { + return context->interface->flush(context); + } else { + return SCPI_RES_OK; + } +} + +/** + * Write result delimiter to output + * @param context + * @return number of bytes written + */ +static size_t writeDelimiter(scpi_t * context) { + if (context->output_count > 0) { + return writeData(context, ", ", 2); + } else { + return 0; + } +} + +/** + * Conditionaly write "New Line" + * @param context + * @return number of characters written + */ +static size_t writeNewLine(scpi_t * context) { + if (context->output_count > 0) { + size_t len; + len = writeData(context, "\r\n", 2); + flushData(context); + return len; + } else { + return 0; + } +} + +/** + * Process command + * @param context + */ +static void processCommand(scpi_t * context) { + const scpi_command_t * cmd = context->paramlist.cmd; + + context->cmd_error = FALSE; + context->output_count = 0; + context->input_count = 0; + + SCPI_DEBUG_COMMAND(context); + /* if callback exists - call command callback */ + if (cmd->callback != NULL) { + if ((cmd->callback(context) != SCPI_RES_OK) && !context->cmd_error) { + SCPI_ErrorPush(context, SCPI_ERROR_EXECUTION_ERROR); + } + } + + /* conditionaly write new line */ + writeNewLine(context); + + /* skip all whitespaces */ + paramSkipWhitespace(context); + + /* set error if command callback did not read all parameters */ + if (context->paramlist.length != 0 && !context->cmd_error) { + SCPI_ErrorPush(context, SCPI_ERROR_PARAMETER_NOT_ALLOWED); + } +} + +/** + * Cycle all patterns and search matching pattern. Execute command callback. + * @param context + * @result TRUE if context->paramlist is filled with correct values + */ +static scpi_bool_t findCommand(scpi_t * context, const char * cmdline_ptr, size_t cmdline_len, size_t cmd_len) { + int32_t i; + const scpi_command_t * cmd; + + for (i = 0; context->cmdlist[i].pattern != NULL; i++) { + cmd = &context->cmdlist[i]; + if (matchCommand(cmd->pattern, cmdline_ptr, cmd_len)) { + context->paramlist.cmd = cmd; + context->paramlist.parameters = cmdline_ptr + cmd_len; + context->paramlist.length = cmdline_len - cmd_len; + context->paramlist.cmd_raw.data = cmdline_ptr; + context->paramlist.cmd_raw.length = cmd_len; + context->paramlist.cmd_raw.position = 0; + return TRUE; + } + } + return FALSE; +} + +/** + * Parse one command line + * @param context + * @param data - complete command line + * @param len - command line length + * @return 1 if the last evaluated command was found + */ +int SCPI_Parse(scpi_t * context, char * data, size_t len) { + int result = 0; + const char * cmdline_end = data + len; + char * cmdline_ptr = data; + size_t cmd_len; + size_t cmdline_len; + char * cmdline_ptr_prev = NULL; + size_t cmd_len_prev = 0; + + if (context == NULL) { + return -1; + } + + while (cmdline_ptr < cmdline_end) { + result = 0; + cmd_len = cmdTerminatorPos(cmdline_ptr, cmdline_end - cmdline_ptr); + if (cmd_len > 0) { + composeCompoundCommand(cmdline_ptr_prev, cmd_len_prev, + &cmdline_ptr, &cmd_len); + cmdline_len = cmdlineSeparatorPos(cmdline_ptr, cmdline_end - cmdline_ptr); + if(findCommand(context, cmdline_ptr, cmdline_len, cmd_len)) { + processCommand(context); + result = 1; + cmdline_ptr_prev = cmdline_ptr; + cmd_len_prev = cmd_len; + } else { + SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); + } + } + cmdline_ptr += skipCmdLine(cmdline_ptr, cmdline_end - cmdline_ptr); + cmdline_ptr += skipWhitespace(cmdline_ptr, cmdline_end - cmdline_ptr); + } + return result; +} + +/** + * Initialize SCPI context structure + * @param context + * @param command_list + * @param buffer + * @param interface + */ +void SCPI_Init(scpi_t * context) { + if (context->idn[0] == NULL) { + context->idn[0] = SCPI_DEFAULT_1_MANUFACTURE; + } + if (context->idn[1] == NULL) { + context->idn[1] = SCPI_DEFAULT_2_MODEL; + } + if (context->idn[2] == NULL) { + context->idn[2] = SCPI_DEFAULT_3; + } + if (context->idn[3] == NULL) { + context->idn[3] = SCPI_DEFAULT_4_REVISION; + } + + context->buffer.position = 0; + SCPI_ErrorInit(context); +} + +/** + * Interface to the application. Adds data to system buffer and try to search + * command line termination. If the termination is found or if len=0, command + * parser is called. + * + * @param context + * @param data - data to process + * @param len - length of data + * @return + */ +int SCPI_Input(scpi_t * context, const char * data, size_t len) { + int result = 0; + const char * cmd_term; + if (len == 0) { + context->buffer.data[context->buffer.position] = 0; + result = SCPI_Parse(context, context->buffer.data, context->buffer.position); + context->buffer.position = 0; + } else { + size_t buffer_free; + int ws; + buffer_free = context->buffer.length - context->buffer.position; + if (len > (buffer_free - 1)) { + return -1; + } + memcpy(&context->buffer.data[context->buffer.position], data, len); + context->buffer.position += len; + context->buffer.data[context->buffer.position] = 0; + + ws = skipWhitespace(context->buffer.data, context->buffer.position); + cmd_term = cmdlineTerminator(context->buffer.data + ws, context->buffer.position - ws); + while (cmd_term != NULL) { + int curr_len = cmd_term - context->buffer.data; + result = SCPI_Parse(context, context->buffer.data + ws, curr_len - ws); + memmove(context->buffer.data, cmd_term, context->buffer.position - curr_len); + context->buffer.position -= curr_len; + + ws = skipWhitespace(context->buffer.data, context->buffer.position); + cmd_term = cmdlineTerminator(context->buffer.data + ws, context->buffer.position - ws); + } + } + + return result; +} + +/* writing results */ + +/** + * Write raw string result to the output + * @param context + * @param data + * @return + */ +size_t SCPI_ResultString(scpi_t * context, const char * data) { + size_t len = strlen(data); + size_t result = 0; + result += writeDelimiter(context); + result += writeData(context, data, len); + context->output_count++; + return result; +} + +/** + * Write integer value to the result + * @param context + * @param val + * @return + */ +size_t SCPI_ResultInt(scpi_t * context, int32_t val) { + char buffer[12]; + size_t result = 0; + size_t len = longToStr(val, buffer, sizeof (buffer)); + result += writeDelimiter(context); + result += writeData(context, buffer, len); + context->output_count++; + return result; +} + +/** + * Write boolean value to the result + * @param context + * @param val + * @return + */ +size_t SCPI_ResultBool(scpi_t * context, scpi_bool_t val) { + return SCPI_ResultInt(context, val ? 1 : 0); +} + +/** + * Write double walue to the result + * @param context + * @param val + * @return + */ +size_t SCPI_ResultDouble(scpi_t * context, double val) { + char buffer[32]; + size_t result = 0; + size_t len = doubleToStr(val, buffer, sizeof (buffer)); + result += writeDelimiter(context); + result += writeData(context, buffer, len); + context->output_count++; + return result; + +} + +/** + * Write string withn " to the result + * @param context + * @param data + * @return + */ +size_t SCPI_ResultText(scpi_t * context, const char * data) { + size_t result = 0; + result += writeDelimiter(context); + result += writeData(context, "\"", 1); + result += writeData(context, data, strlen(data)); + result += writeData(context, "\"", 1); + context->output_count++; + return result; +} + +/* parsing parameters */ + +/** + * Skip num bytes from the begginig of parameters + * @param context + * @param num + */ +void paramSkipBytes(scpi_t * context, size_t num) { + if (context->paramlist.length < num) { + num = context->paramlist.length; + } + context->paramlist.parameters += num; + context->paramlist.length -= num; +} + +/** + * Skip white spaces from the beggining of parameters + * @param context + */ +void paramSkipWhitespace(scpi_t * context) { + size_t ws = skipWhitespace(context->paramlist.parameters, context->paramlist.length); + paramSkipBytes(context, ws); +} + +/** + * Find next parameter + * @param context + * @param mandatory + * @return + */ +scpi_bool_t paramNext(scpi_t * context, scpi_bool_t mandatory) { + paramSkipWhitespace(context); + if (context->paramlist.length == 0) { + if (mandatory) { + SCPI_ErrorPush(context, SCPI_ERROR_MISSING_PARAMETER); + } + return FALSE; + } + if (context->input_count != 0) { + if (context->paramlist.parameters[0] == ',') { + paramSkipBytes(context, 1); + paramSkipWhitespace(context); + } else { + SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SEPARATOR); + return FALSE; + } + } + context->input_count++; + return TRUE; +} + +/** + * Parse integer parameter + * @param context + * @param value + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory) { + const char * param; + size_t param_len; + size_t num_len; + + if (!value) { + return FALSE; + } + + if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { + return FALSE; + } + + num_len = strToLong(param, value); + + if (num_len != param_len) { + SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); + return FALSE; + } + + return TRUE; +} + +/** + * Parse double parameter + * @param context + * @param value + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory) { + const char * param; + size_t param_len; + size_t num_len; + + if (!value) { + return FALSE; + } + + if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { + return FALSE; + } + + num_len = strToDouble(param, value); + + if (num_len != param_len) { + SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); + return FALSE; + } + + return TRUE; +} + +/** + * Parse string parameter + * @param context + * @param value Pointer to string buffer where pointer to non-null terminated string will be returned + * @param len Length of returned non-null terminated string + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamString(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { + size_t length; + + if (!value || !len) { + return FALSE; + } + + if (!paramNext(context, mandatory)) { + return FALSE; + } + + if (locateStr(context->paramlist.parameters, context->paramlist.length, value, &length)) { + paramSkipBytes(context, length); + paramSkipWhitespace(context); + if (len) { + *len = length; + } + return TRUE; + } + + return FALSE; +} + +/** + * Parse text parameter (can be inside "") + * @param context + * @param value Pointer to string buffer where pointer to non-null terminated string will be returned + * @param len Length of returned non-null terminated string + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamText(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { + size_t length; + + if (!value || !len) { + return FALSE; + } + + if (!paramNext(context, mandatory)) { + return FALSE; + } + + if (locateText(context->paramlist.parameters, context->paramlist.length, value, &length)) { + paramSkipBytes(context, length); + if (len) { + *len = length; + } + return TRUE; + } + + return FALSE; +} + +/** + * Parse boolean parameter as described in the spec SCPI-99 7.3 Boolean Program Data + * @param context + * @param value + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamBool(scpi_t * context, scpi_bool_t * value, scpi_bool_t mandatory) { + const char * param; + size_t param_len; + size_t num_len; + int32_t i; + + if (!value) { + return FALSE; + } + + if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { + return FALSE; + } + + if (matchPattern("ON", 2, param, param_len)) { + *value = TRUE; + } else if (matchPattern("OFF", 3, param, param_len)) { + *value = FALSE; + } else { + num_len = strToLong(param, &i); + + if (num_len != param_len) { + SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); + return FALSE; + } + + *value = i ? TRUE : FALSE; + } + + return TRUE; +} + +/** + * Parse choice parameter + * @param context + * @param options + * @param value + * @param mandatory + * @return + */ +scpi_bool_t SCPI_ParamChoice(scpi_t * context, const char * options[], int32_t * value, scpi_bool_t mandatory) { + const char * param; + size_t param_len; + size_t res; + + if (!options || !value) { + return FALSE; + } + + if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { + return FALSE; + } + + for (res = 0; options[res]; ++res) { + if (matchPattern(options[res], strlen(options[res]), param, param_len)) { + *value = res; + return TRUE; + } + } + + SCPI_ErrorPush(context, SCPI_ERROR_ILLEGAL_PARAMETER_VALUE); + return FALSE; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/units.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,325 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_units.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI units + * + * + */ + +#include <string.h> +#include "scpi/parser.h" +#include "scpi/units.h" +#include "scpi/utils_private.h" +#include "scpi/error.h" + + +/* + * multipliers IEEE 488.2-1992 tab 7-2 + * 1E18 EX + * 1E15 PE + * 1E12 T + * 1E9 G + * 1E6 MA (use M for OHM and HZ) + * 1E3 K + * 1E-3 M (disaalowed for OHM and HZ) + * 1E-6 U + * 1E-9 N + * 1E-12 P + * 1E-15 F + * 1E-18 A + */ + +/* + * units definition IEEE 488.2-1992 tab 7-1 + */ +const scpi_unit_def_t scpi_units_def[] = { + /* voltage */ + {/* name */ "UV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-6}, + {/* name */ "MV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-3}, + {/* name */ "V", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1}, + {/* name */ "KV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e3}, + + /* current */ + {/* name */ "UA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-6}, + {/* name */ "MA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-3}, + {/* name */ "A", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1}, + {/* name */ "KA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e3}, + + /* resistance */ + {/* name */ "OHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1}, + {/* name */ "KOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e3}, + {/* name */ "MOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e6}, + + /* frequency */ + {/* name */ "HZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1}, + {/* name */ "KHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e3}, + {/* name */ "MHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e6}, + {/* name */ "GHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e9}, + + /* temperature */ + {/* name */ "CEL", /* unit */ SCPI_UNIT_CELSIUS, /* mult */ 1}, + + /* time */ + {/* name */ "PS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-12}, + {/* name */ "NS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-9}, + {/* name */ "US", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-6}, + {/* name */ "MS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-3}, + {/* name */ "S", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1}, + {/* name */ "MIN", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 60}, + {/* name */ "HR", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 3600}, + + SCPI_UNITS_LIST_END, +}; + +/* + * Special number values definition + */ +const scpi_special_number_def_t scpi_special_numbers_def[] = { + {/* name */ "MINimum", /* type */ SCPI_NUM_MIN}, + {/* name */ "MAXimum", /* type */ SCPI_NUM_MAX}, + {/* name */ "DEFault", /* type */ SCPI_NUM_DEF}, + {/* name */ "UP", /* type */ SCPI_NUM_UP}, + {/* name */ "DOWN", /* type */ SCPI_NUM_DOWN}, + {/* name */ "NAN", /* type */ SCPI_NUM_NAN}, + {/* name */ "INFinity", /* type */ SCPI_NUM_INF}, + {/* name */ "NINF", /* type */ SCPI_NUM_NINF}, + SCPI_SPECIAL_NUMBERS_LIST_END, +}; + +/** + * Match string constant to one of special number values + * @param specs specifications of special numbers (patterns) + * @param str string to be recognised + * @param len length of string + * @param value resultin value + * @return TRUE if str matches one of specs patterns + */ +static scpi_bool_t translateSpecialNumber(const scpi_special_number_def_t * specs, const char * str, size_t len, scpi_number_t * value) { + int i; + + value->value = 0.0; + value->unit = SCPI_UNIT_NONE; + value->type = SCPI_NUM_NUMBER; + + if (specs == NULL) { + return FALSE; + } + + for (i = 0; specs[i].name != NULL; i++) { + if (matchPattern(specs[i].name, strlen(specs[i].name), str, len)) { + value->type = specs[i].type; + return TRUE; + } + } + + return FALSE; +} + +/** + * Convert special number type to its string representation + * @param specs specifications of special numbers (patterns) + * @param type type of special number + * @return String representing special number or NULL + */ +static const char * translateSpecialNumberInverse(const scpi_special_number_def_t * specs, scpi_special_number_t type) { + int i; + + if (specs == NULL) { + return NULL; + } + + for (i = 0; specs[i].name != NULL; i++) { + if (specs[i].type == type) { + return specs[i].name; + } + } + + return NULL; +} + +/** + * Convert string describing unit to its representation + * @param units units patterns + * @param unit text representation of unknown unit + * @param len length of text representation + * @return pointer of related unit definition or NULL + */ +static const scpi_unit_def_t * translateUnit(const scpi_unit_def_t * units, const char * unit, size_t len) { + int i; + + if (units == NULL) { + return NULL; + } + + for (i = 0; units[i].name != NULL; i++) { + if (compareStr(unit, len, units[i].name, strlen(units[i].name))) { + return &units[i]; + } + } + + return NULL; +} + +/** + * Convert unit definition to string + * @param units units definitions (patterns) + * @param unit type of unit + * @return string representation of unit + */ +static const char * translateUnitInverse(const scpi_unit_def_t * units, const scpi_unit_t unit) { + int i; + + if (units == NULL) { + return NULL; + } + + for (i = 0; units[i].name != NULL; i++) { + if ((units[i].unit == unit) && (units[i].mult == 1)) { + return units[i].name; + } + } + + return NULL; +} + +/** + * Transform number to base units + * @param context + * @param unit text representation of unit + * @param len length of text representation + * @param value preparsed numeric value + * @return TRUE if value parameter was converted to base units + */ +static scpi_bool_t transformNumber(scpi_t * context, const char * unit, size_t len, scpi_number_t * value) { + size_t s; + const scpi_unit_def_t * unitDef; + s = skipWhitespace(unit, len); + + if (s == len) { + value->unit = SCPI_UNIT_NONE; + return TRUE; + } + + unitDef = translateUnit(context->units, unit + s, len - s); + + if (unitDef == NULL) { + SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SUFFIX); + return FALSE; + } + + value->value *= unitDef->mult; + value->unit = unitDef->unit; + + return TRUE; +} + +/** + * Parse parameter as number, number with unit or special value (min, max, default, ...) + * @param context + * @param value return value + * @param mandatory if the parameter is mandatory + * @return + */ +scpi_bool_t SCPI_ParamNumber(scpi_t * context, scpi_number_t * value, scpi_bool_t mandatory) { + scpi_bool_t result; + const char * param; + size_t len; + size_t numlen; + + /* read parameter and shift to the next one */ + result = SCPI_ParamString(context, ¶m, &len, mandatory); + + /* value not initializes */ + if (!value) { + return FALSE; + } + + value->type = SCPI_NUM_DEF; + + /* if parameter was not found, return TRUE or FALSE according + * to fact that parameter was mandatory or not */ + if (!result) { + return mandatory ? FALSE : TRUE; + } + + /* convert string to special number type */ + if (translateSpecialNumber(context->special_numbers, param, len, value)) { + /* found special type */ + return TRUE; + } + + /* convert text from double - no special type */ + numlen = strToDouble(param, &value->value); + + /* transform units of value */ + if (numlen <= len) { + return transformNumber(context, param + numlen, len - numlen, value); + } + return FALSE; + +} + +/** + * Convert scpi_number_t to string + * @param context + * @param value number value + * @param str target string + * @param len max length of string + * @return number of chars written to string + */ +size_t SCPI_NumberToStr(scpi_t * context, scpi_number_t * value, char * str, size_t len) { + const char * type; + const char * unit; + size_t result; + + if (!value || !str) { + return 0; + } + + type = translateSpecialNumberInverse(context->special_numbers, value->type); + + if (type) { + strncpy(str, type, len); + return min(strlen(type), len); + } + + result = doubleToStr(value->value, str, len); + + unit = translateUnitInverse(context->units, value->unit); + + if (unit) { + strncat(str, " ", len); + strncat(str, unit, len); + result += strlen(unit) + 1; + } + + return result; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libscpi/utils.c Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,730 @@ +/*- + * Copyright (c) 2013 Jan Breuer + * Richard.hmm + * Copyright (c) 2012 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_utils.c + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Conversion routines and string manipulation routines + * + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "scpi/utils_private.h" + +static size_t patternSeparatorShortPos(const char * pattern, size_t len); +static size_t patternSeparatorPos(const char * pattern, size_t len); +static size_t cmdSeparatorPos(const char * cmd, size_t len); + +/** + * Find the first occurrence in str of a character in set. + * @param str + * @param size + * @param set + * @return + */ +const char * strnpbrk(const char *str, size_t size, const char *set) { + const char *scanp; + long c, sc; + const char * strend = str + size; + + while ((strend != str) && ((c = *str++) != 0)) { + for (scanp = set; (sc = *scanp++) != '\0';) + if (sc == c) + return str - 1; + } + return (NULL); +} + +/** + * Converts signed 32b integer value to string + * @param val integer value + * @param str converted textual representation + * @param len string buffer length + * @return number of bytes written to str (without '\0') + */ +size_t longToStr(int32_t val, char * str, size_t len) { + uint32_t x = 1000000000L; + int_fast8_t digit; + size_t pos = 0; + + if (val == 0) { + if (pos < len) str[pos++] = '0'; + } else { + if (val < 0) { + val = -val; + if (pos < len) str[pos++] = '-'; + } + + while ((val / x) == 0) { + x /= 10; + } + + do { + digit = (uint8_t) (val / x); + if (pos < len) str[pos++] = digit + '0'; + val -= digit * x; + x /= 10; + } while (x && (pos < len)); + } + + if (pos < len) str[pos] = 0; + return pos; +} + +/** + * Converts double value to string + * @param val double value + * @param str converted textual representation + * @param len string buffer length + * @return number of bytes written to str (without '\0') + */ +size_t doubleToStr(double val, char * str, size_t len) { + return snprintf(str, len, "%lg", val); +} + +/** + * Converts string to signed 32bit integer representation + * @param str string value + * @param val 32bit integer result + * @return number of bytes used in string + */ +size_t strToLong(const char * str, int32_t * val) { + char * endptr; + *val = strtol(str, &endptr, 0); + return endptr - str; +} + +/** + * Converts string to double representation + * @param str string value + * @param val double result + * @return number of bytes used in string + */ +size_t strToDouble(const char * str, double * val) { + char * endptr; + *val = strtod(str, &endptr); + return endptr - str; +} + +/** + * Compare two strings with exact length + * @param str1 + * @param len1 + * @param str2 + * @param len2 + * @return TRUE if len1==len2 and "len" characters of both strings are equal + */ +scpi_bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) { + if (len1 != len2) { + return FALSE; + } + + if (SCPI_strncasecmp(str1, str2, len2) == 0) { + return TRUE; + } + + return FALSE; +} + +/** + * Compare two strings, one be longer but may contains only numbers in that section + * @param str1 + * @param len1 + * @param str2 + * @param len2 + * @return TRUE if strings match + */ +scpi_bool_t compareStrAndNum(const char * str1, size_t len1, const char * str2, size_t len2) { + scpi_bool_t result = FALSE; + size_t i; + + if (len2 < len1) { + return FALSE; + } + + if (SCPI_strncasecmp(str1, str2, len1) == 0) { + result = TRUE; + } + + for (i = len1; i<len2; i++) { + if (!isdigit(str2[i])) { + result = FALSE; + break; + } + } + + return result; +} + +enum _locate_text_states { + STATE_FIRST_WHITESPACE, + STATE_TEXT_QUOTED, + STATE_TEXT, + STATE_LAST_WHITESPACE, + STATE_COMMA, + STATE_ERROR +}; +typedef enum _locate_text_states locate_text_states; + +struct _locate_text_nfa { + locate_text_states state; + int32_t startIdx; + int32_t stopIdx; + size_t i; +}; +typedef struct _locate_text_nfa locate_text_nfa; + +/** + * Test locate text state, if it is correct final state + */ +static scpi_bool_t isFinalState(locate_text_states state) { + return ( + ((state) == STATE_COMMA) + || ((state) == STATE_LAST_WHITESPACE) + || ((state) == STATE_TEXT) || + ((state) == STATE_FIRST_WHITESPACE) + ); +} + +/** + * Perform locateText automaton to search string pattern + * @param nfa stores automaton state + * @param c current char processed + */ +static scpi_bool_t locateTextAutomaton(locate_text_nfa * nfa, unsigned char c) { + switch(nfa->state) { + /* first state locating only white spaces */ + case STATE_FIRST_WHITESPACE: + if(isspace(c)) { + nfa->startIdx = nfa->stopIdx = nfa->i + 1; + } else if (c == ',') { + nfa->state = STATE_COMMA; + } else if (c == '"') { + nfa->startIdx = nfa->i + 1; + nfa->state = STATE_TEXT_QUOTED; + } else { + nfa->startIdx = nfa->i; + nfa->stopIdx = nfa->i + 1; + nfa->state = STATE_TEXT; + } + break; + /* state locating any text inside "" */ + case STATE_TEXT_QUOTED: + if(c == '"') { + nfa->state = STATE_LAST_WHITESPACE; + nfa->stopIdx = nfa->i; + } + break; + /* locate text ignoring quotes */ + case STATE_TEXT: + if (c == ',') { + nfa->state = STATE_COMMA; + } else if (!isspace(c)) { + nfa->stopIdx = nfa->i + 1; + } + break; + /* locating text after last quote */ + case STATE_LAST_WHITESPACE: + if (c == ',') { + nfa->state = STATE_COMMA; + } else if (!isspace(c)) { + nfa->state = STATE_ERROR; + } + break; + + default: + break; + } + + /* if it is terminating state, break from for loop */ + if ((nfa->state == STATE_COMMA) || (nfa->state == STATE_ERROR)) { + return FALSE; + } else { + return TRUE; + } +} + +/** + * Locate text in string. Text is separated by two "" + * example: "text", next parameter + * regexp: ^[ \t\r\n]*"([^"]*)"[ \t\r\n]*,? + * regexp: ^[ \t\r\n]*([^,]*)[ \t\r\n]*,? + * @param str1 string to be searched + * @param len1 length of string + * @param str2 result + * @param len2 length of result + * @return string str1 contains text and str2 was set + */ +scpi_bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) { + locate_text_nfa nfa; + nfa.state = STATE_FIRST_WHITESPACE; + nfa.startIdx = 0; + nfa.stopIdx = 0; + + for (nfa.i = 0; nfa.i < len1; nfa.i++) { + if(FALSE == locateTextAutomaton(&nfa, str1[nfa.i])) { + break; + } + } + + if (isFinalState(nfa.state)) { + + if (str2) { + *str2 = &str1[nfa.startIdx]; + } + + if (len2) { + *len2 = nfa.stopIdx - nfa.startIdx; + } + return TRUE; + } + return FALSE; +} + +/** + * Perform locateStr automaton to search string pattern + * @param nfa stores automaton state + * @param c current char processed + */ +static scpi_bool_t locateStrAutomaton(locate_text_nfa * nfa, unsigned char c) { + switch(nfa->state) { + /* first state locating only white spaces */ + case STATE_FIRST_WHITESPACE: + if(isspace(c)) { + nfa->startIdx = nfa->stopIdx = nfa->i + 1; + } else if (c == ',') { + nfa->state = STATE_COMMA; + } else { + nfa->startIdx = nfa->i; + nfa->stopIdx = nfa->i + 1; + nfa->state = STATE_TEXT; + } + break; + /* locate text ignoring quotes */ + case STATE_TEXT: + if (c == ',') { + nfa->state = STATE_COMMA; + } else if (!isspace(c)) { + nfa->stopIdx = nfa->i + 1; + } + break; + + default: + break; + } + + /* if it is terminating state, break from for loop */ + if ((nfa->state == STATE_COMMA) || (nfa->state == STATE_ERROR)) { + return FALSE; + } else { + return TRUE; + } +} + +/** + * Locate string in string. + * regexp: ^[ \t\r\n]*([^,]*)[ \t\r\n]*,? + * @param str1 string to be searched + * @param len1 length of string + * @param str2 result + * @param len2 length of result + * @return string str1 contains text and str2 was set + */ +scpi_bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) { + locate_text_nfa nfa; + nfa.state = STATE_FIRST_WHITESPACE; + nfa.startIdx = 0; + nfa.stopIdx = 0; + + + for (nfa.i = 0; nfa.i < len1; nfa.i++) { + if(FALSE == locateStrAutomaton(&nfa, str1[nfa.i])) { + break; + } + } + + if (isFinalState(nfa.state)) { + + if (str2) { + *str2 = &str1[nfa.startIdx]; + } + + if (len2) { + *len2 = nfa.stopIdx - nfa.startIdx; + } + return TRUE; + } + return FALSE; +} + + +/** + * Count white spaces from the beggining + * @param cmd - command + * @param len - max search length + * @return number of white spaces + */ +size_t skipWhitespace(const char * cmd, size_t len) { + size_t i; + for (i = 0; i < len; i++) { + if (!isspace((unsigned char) cmd[i])) { + return i; + } + } + return len; +} + +/** + * Pattern is composed from upper case an lower case letters. This function + * search the first lowercase letter + * @param pattern + * @param len - max search length + * @return position of separator or len + */ +size_t patternSeparatorShortPos(const char * pattern, size_t len) { + size_t i; + for (i = 0; (i < len) && pattern[i]; i++) { + if (islower((unsigned char) pattern[i])) { + return i; + } + } + return i; +} + +/** + * Find pattern separator position + * @param pattern + * @param len - max search length + * @return position of separator or len + */ +size_t patternSeparatorPos(const char * pattern, size_t len) { + + const char * separator = strnpbrk(pattern, len, "?:[]"); + if (separator == NULL) { + return len; + } else { + return separator - pattern; + } +} + +/** + * Find command separator position + * @param cmd - input command + * @param len - max search length + * @return position of separator or len + */ +size_t cmdSeparatorPos(const char * cmd, size_t len) { + const char * separator = strnpbrk(cmd, len, ":?"); + size_t result; + if (separator == NULL) { + result = len; + } else { + result = separator - cmd; + } + + return result; +} + +/** + * Match pattern and str. Pattern is in format UPPERCASElowercase + * @param pattern + * @param pattern_len + * @param str + * @param str_len + * @return + */ +scpi_bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) { + int pattern_sep_pos_short; + + if (pattern[pattern_len - 1] == '#') { + size_t new_pattern_len = pattern_len - 1; + + pattern_sep_pos_short = patternSeparatorShortPos(pattern, new_pattern_len); + + return compareStrAndNum(pattern, new_pattern_len, str, str_len) || + compareStrAndNum(pattern, pattern_sep_pos_short, str, str_len); + } else { + + pattern_sep_pos_short = patternSeparatorShortPos(pattern, pattern_len); + + return compareStr(pattern, pattern_len, str, str_len) || + compareStr(pattern, pattern_sep_pos_short, str, str_len); + } +} + +/** + * Compare pattern and command + * @param pattern eg. [:MEASure]:VOLTage:DC? + * @param cmd - command + * @param len - max search length + * @return TRUE if pattern matches, FALSE otherwise + */ +scpi_bool_t matchCommand(const char * pattern, const char * cmd, size_t len) { + scpi_bool_t result = FALSE; + int leftFlag = 0; // flag for '[' on left + int rightFlag = 0; // flag for ']' on right + int cmd_sep_pos = 0; + + const char * pattern_ptr = pattern; + int pattern_len = strlen(pattern); + const char * pattern_end = pattern + pattern_len; + + const char * cmd_ptr = cmd; + size_t cmd_len = SCPI_strnlen(cmd, len); + const char * cmd_end = cmd + cmd_len; + + /* now support optional keywords in pattern style, e.g. [:MEASure]:VOLTage:DC? */ + if (pattern_ptr[0] == '[') { // skip first '[' + pattern_len--; + pattern_ptr++; + leftFlag++; + } + if (pattern_ptr[0] == ':') { // skip first ':' + pattern_len--; + pattern_ptr++; + } + + if (cmd_ptr[0] == ':') { + /* handle errornouse ":*IDN?" */ + if((cmd_len >= 2) && (cmd_ptr[1] != '*')) { + cmd_len--; + cmd_ptr++; + } + } + + while (1) { + int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_end - pattern_ptr); + + if ((leftFlag > 0) && (rightFlag > 0)) { + leftFlag--; + rightFlag--; + } else { + cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_end - cmd_ptr); + } + + if (matchPattern(pattern_ptr, pattern_sep_pos, cmd_ptr, cmd_sep_pos)) { + pattern_ptr = pattern_ptr + pattern_sep_pos; + cmd_ptr = cmd_ptr + cmd_sep_pos; + result = TRUE; + + /* command is complete */ + if ((pattern_ptr == pattern_end) && (cmd_ptr >= cmd_end)) { + break; + } + + /* pattern complete, but command not */ + if ((pattern_ptr == pattern_end) && (cmd_ptr < cmd_end)) { + result = FALSE; + break; + } + + /* command complete, but pattern not */ + if (cmd_ptr >= cmd_end) { + if (cmd_end == cmd_ptr) { + if (cmd_ptr[0] == pattern_ptr[pattern_end - pattern_ptr - 1]) { + break; /* exist optional keyword, command is complete */ + } + if (']' == pattern_ptr[pattern_end - pattern_ptr - 1]) { + break; /* exist optional keyword, command is complete */ + } + } + result = FALSE; + break; + } + + /* both command and patter contains command separator at this position */ + if ((pattern_ptr[0] == cmd_ptr[0]) && ((pattern_ptr[0] == ':') || (pattern_ptr[0] == '?'))) { + pattern_ptr = pattern_ptr + 1; + cmd_ptr = cmd_ptr + 1; + } else if ((pattern_ptr[1] == cmd_ptr[0]) + && (pattern_ptr[0] == '[') + && (pattern_ptr[1] == ':')) { + pattern_ptr = pattern_ptr + 2; // for skip '[' in "[:" + cmd_ptr = cmd_ptr + 1; + leftFlag++; + } else if ((pattern_ptr[1] == cmd_ptr[0]) + && (pattern_ptr[0] == ']') + && (pattern_ptr[1] == ':')) { + pattern_ptr = pattern_ptr + 2; // for skip ']' in "]:" + cmd_ptr = cmd_ptr + 1; + } else if ((pattern_ptr[2] == cmd_ptr[0]) + && (pattern_ptr[0] == ']') + && (pattern_ptr[1] == '[') + && (pattern_ptr[2] == ':')) { + pattern_ptr = pattern_ptr + 3; // for skip '][' in "][:" + cmd_ptr = cmd_ptr + 1; + leftFlag++; + } else if (((pattern_ptr[0] == ']') + || (pattern_ptr[0] == '[')) + && (*(pattern_end - 1) == '?') // last is '?' + && (cmd_ptr[0] == '?')) { + result = TRUE; // exist optional keyword, and they are end with '?' + break; // command is complete OK + } else { + result = FALSE; + break; + } + } else { + pattern_ptr = pattern_ptr + pattern_sep_pos; + if ((pattern_ptr[0] == ']') && (pattern_ptr[1] == ':')) { + pattern_ptr = pattern_ptr + 2; // for skip ']' in "]:" , pattern_ptr continue, while cmd_ptr remain unchanged + rightFlag++; + } else if ((pattern_ptr[0] == ']') + && (pattern_ptr[1] == '[') + && (pattern_ptr[2] == ':')) { + pattern_ptr = pattern_ptr + 3; // for skip ']' in "][:" , pattern_ptr continue, while cmd_ptr remain unchanged + rightFlag++; + } else { + result = FALSE; + break; + } + } + } + + return result; +} + +/** + * Compose command from previsou command anc current command + * + * @param ptr_prev pointer to previous command + * @param len_prev length of previous command + * @param pptr pointer to pointer of current command + * @param plen pointer to length of current command + * + * ptr_prev and ptr should be in the same memory buffer + * + * Function will add part of previous command prior to ptr_prev + * + * char * cmd = "meas:volt:dc?;ac?" + * char * ptr_prev = cmd; + * size_t len_prev = 13; + * char * ptr = cmd + 14; + * size_t len = 3; + * + * composeCompoundCommand(ptr_prev, len_prev, &ptr, &len); + * + * after calling this + * + * + * + */ +scpi_bool_t composeCompoundCommand(char * ptr_prev, size_t len_prev, + char ** pptr, size_t * plen) { + char * ptr; + size_t len; + size_t i; + + /* Invalid input */ + if (pptr == NULL || plen == NULL) + return FALSE; + + /* no previous command - nothing to do*/ + if (ptr_prev == NULL || len_prev == 0) + return TRUE; + + ptr = *pptr; + len = *plen; + + /* No current command */ + if (len == 0 || ptr == NULL) + return FALSE; + + /* Common command or command root - nothing to do */ + if (ptr[0] == '*' || ptr[0] == ':') + return TRUE; + + /* Previsou command was common command - nothing to do */ + if (ptr_prev[0] == '*') + return TRUE; + + /* Find last occurence of ':' */ + for (i = len_prev; i > 0; i--) { + if (ptr_prev[i-1] == ':') { + break; + } + } + + /* Previous command was simple command - nothing to do*/ + if (i == 0) + return TRUE; + + ptr -= i; + len += i; + memmove(ptr, ptr_prev, i); + *plen = len; + *pptr = ptr; + return TRUE; +} + + + +#if !HAVE_STRNLEN +/* use FreeBSD strnlen */ + +/*- + * Copyright (c) 2009 David Schultz <das@FreeBSD.org> + * All rights reserved. + */ +size_t +BSD_strnlen(const char *s, size_t maxlen) { + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} +#endif + +#if !HAVE_STRNCASECMP && !HAVE_STRNICMP +int OUR_strncasecmp(const char *s1, const char *s2, size_t n) { + unsigned char c1, c2; + + for(; n != 0; n--) { + c1 = tolower((unsigned char)*s1++); + c2 = tolower((unsigned char)*s2++); + if (c1 != c2) { + return c1 - c2; + } + if (c1 = '\0') { + return 0; + } + } + return 0; +} +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/config.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,99 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file config.h + * @date Wed Mar 20 12:21:26 UTC 2013 + * + * @brief SCPI Configuration + * + * + */ + +#ifndef __SCPI_CONFIG_H_ +#define __SCPI_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Compiler specific */ +/* 8bit PIC - PIC16, etc */ +#if defined(_MPC_) +#define HAVE_STRNLEN 0 +#define HAVE_STRNCASECMP 0 +#define HAVE_STRNICMP 1 +#endif + +/* PIC24 */ +#if defined(__C30__) +#define HAVE_STRNLEN 0 +#define HAVE_STRNCASECMP 0 +#define HAVE_STRNICMP 0 +#endif + +/* PIC32mx */ +#if defined(__C32__) +#define HAVE_STRNLEN 0 +#define HAVE_STRNCASECMP 1 +#define HAVE_STRNICMP 0 +#endif + +/* ======== test strnlen ======== */ +#ifndef HAVE_STRNLEN +#define HAVE_STRNLEN 0 +#endif +/* ======== test strncasecmp ======== */ +#ifndef HAVE_STRNCASECMP +#define HAVE_STRNCASECMP 1 +#endif +/* ======== test strnicmp ======== */ +#ifndef HAVE_STRNICMP +#define HAVE_STRNICMP 0 +#endif + +/* define local macros depending on existance of strnlen */ +#if HAVE_STRNLEN +#define SCPI_strnlen(s, l) strnlen((s), (l)) +#else +#define SCPI_strnlen(s, l) BSD_strnlen((s), (l)) +#endif + +/* define local macros depending on existance of strncasecmp and strnicmp */ +#if HAVE_STRNCASECMP +#define SCPI_strncasecmp(s1, s2, l) strncasecmp((s1), (s2), (l)) +#elif HAVE_STRNICMP +#define SCPI_strncasecmp(s1, s2, l) strnicmp((s1), (s2), (l)) +#else +#define SCPI_strncasecmp(s1, s2, l) OUR_strncasecmp((s1), (s2), (l)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/constants.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,64 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_constants.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI Device constants + * + * + */ + +#ifndef SCPI_CONSTANTS_H +#define SCPI_CONSTANTS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* 4.1.3.6 *IDN? */ + +#define SCPI_DEFAULT_1_MANUFACTURE "CTU FEE" +#define SCPI_DEFAULT_2_MODEL "TSI3225" +#define SCPI_DEFAULT_3 "0" +#define SCPI_DEFAULT_4_REVISION "01-01" + +/* 21.21 :VERSion? + * YYYY.V + * YYYY = SCPI year + * V = SCPI revision + */ +#define SCPI_STD_VERSION_REVISION "1999.0" + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_CONSTANTS_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/debug.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,59 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_debug.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI debug function + * + * + */ + +#ifndef SCPI_DEBUG_H +#define SCPI_DEBUG_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + /* #define SCPI_DEBUG_COMMAND(a) scpi_debug_command(a) */ + #define SCPI_DEBUG_COMMAND(a) + + + scpi_bool_t SCPI_DebugCommand(scpi_t * context); + + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_DEBUG_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/error.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,77 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_error.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Error handling and storing routines + * + * + */ + +#ifndef SCPI_ERROR_H +#define SCPI_ERROR_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + void SCPI_ErrorInit(scpi_t * context); + void SCPI_ErrorClear(scpi_t * context); + int16_t SCPI_ErrorPop(scpi_t * context); + void SCPI_ErrorPush(scpi_t * context, int16_t err); + int32_t SCPI_ErrorCount(scpi_t * context); + const char * SCPI_ErrorTranslate(int16_t err); + +/* http://en.wikipedia.org/wiki/X_Macro */ +#define LIST_OF_ERRORS \ + X(SCPI_ERROR_SYNTAX, -102, "Syntax error") \ + X(SCPI_ERROR_INVALID_SEPARATOR, -103, "Invalid separator") \ + X(SCPI_ERROR_UNDEFINED_HEADER, -113, "Undefined header") \ + X(SCPI_ERROR_PARAMETER_NOT_ALLOWED,-108, "Parameter not allowed") \ + X(SCPI_ERROR_MISSING_PARAMETER, -109, "Missing parameter") \ + X(SCPI_ERROR_INVALID_SUFFIX, -131, "Invalid suffix") \ + X(SCPI_ERROR_SUFFIX_NOT_ALLOWED, -138, "Suffix not allowed") \ + X(SCPI_ERROR_EXECUTION_ERROR, -200, "Execution error") \ + X(SCPI_ERROR_ILLEGAL_PARAMETER_VALUE,-224,"Illegal parameter value") \ + + +enum { +#define X(def, val, str) def = val, +LIST_OF_ERRORS +#undef X +}; + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_ERROR_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/fifo.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,67 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_fifo.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief basic FIFO implementation + * + * + */ + +#ifndef SCPI_FIFO_H +#define SCPI_FIFO_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define FIFO_SIZE 16 + + struct _fifo_t { + int16_t wr; + int16_t rd; + int16_t size; + int16_t data[FIFO_SIZE]; + }; + typedef struct _fifo_t fifo_t; + + void fifo_init(fifo_t * fifo); + void fifo_clear(fifo_t * fifo); + scpi_bool_t fifo_add(fifo_t * fifo, int16_t value); + scpi_bool_t fifo_remove(fifo_t * fifo, int16_t * value); + scpi_bool_t fifo_count(fifo_t * fifo, int16_t * value); + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_FIFO_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/ieee488.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,91 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_ieee488.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Implementation of IEEE488.2 commands and state model + * + * + */ + +#ifndef SCPI_IEEE488_H +#define SCPI_IEEE488_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +scpi_result_t SCPI_CoreCls(scpi_t * context); +scpi_result_t SCPI_CoreEse(scpi_t * context); +scpi_result_t SCPI_CoreEseQ(scpi_t * context); +scpi_result_t SCPI_CoreEsrQ(scpi_t * context); +scpi_result_t SCPI_CoreIdnQ(scpi_t * context); +scpi_result_t SCPI_CoreOpc(scpi_t * context); +scpi_result_t SCPI_CoreOpcQ(scpi_t * context); +scpi_result_t SCPI_CoreRst(scpi_t * context); +scpi_result_t SCPI_CoreSre(scpi_t * context); +scpi_result_t SCPI_CoreSreQ(scpi_t * context); +scpi_result_t SCPI_CoreStbQ(scpi_t * context); +scpi_result_t SCPI_CoreTstQ(scpi_t * context); +scpi_result_t SCPI_CoreWai(scpi_t * context); + + +#define STB_R01 0x01 /* Not used */ +#define STB_PRO 0x02 /* Protection Event Flag */ +#define STB_QMA 0x04 /* Error/Event queue message available */ +#define STB_QES 0x08 /* Questionable status */ +#define STB_MAV 0x10 /* Message Available */ +#define STB_ESR 0x20 /* Standard Event Status Register */ +#define STB_SRQ 0x40 /* Service Request */ +#define STB_OPS 0x80 /* Operation Status Flag */ + + +#define ESR_OPC 0x01 /* Operation complete */ +#define ESR_REQ 0x02 /* Request Control */ +#define ESR_QER 0x04 /* Query Error */ +#define ESR_DER 0x08 /* Device Dependent Error */ +#define ESR_EER 0x10 /* Execution Error (e.g. range error) */ +#define ESR_CER 0x20 /* Command error (e.g. syntax error) */ +#define ESR_URQ 0x40 /* User Request */ +#define ESR_PON 0x80 /* Power On */ + + +scpi_reg_val_t SCPI_RegGet(scpi_t * context, scpi_reg_name_t name); +void SCPI_RegSet(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t val); +void SCPI_RegSetBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits); +void SCPI_RegClearBits(scpi_t * context, scpi_reg_name_t name, scpi_reg_val_t bits); + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_IEEE488_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/minimal.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,63 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_minimal.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI minimal implementation + * + * + */ + +#ifndef SCPI_MINIMAL_H +#define SCPI_MINIMAL_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + scpi_result_t SCPI_Stub(scpi_t * context); + scpi_result_t SCPI_StubQ(scpi_t * context); + + scpi_result_t SCPI_SystemVersionQ(scpi_t * context); + scpi_result_t SCPI_SystemErrorNextQ(scpi_t * context); + scpi_result_t SCPI_SystemErrorCountQ(scpi_t * context); + scpi_result_t SCPI_StatusQuestionableEventQ(scpi_t * context); + scpi_result_t SCPI_StatusQuestionableEnableQ(scpi_t * context); + scpi_result_t SCPI_StatusQuestionableEnable(scpi_t * context); + scpi_result_t SCPI_StatusPreset(scpi_t * context); + + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_MINIMAL_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/parser.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,72 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_parser.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI parser implementation + * + * + */ + +#ifndef SCPI_PARSER_H +#define SCPI_PARSER_H + +#include "scpi/types.h" +#include "scpi/debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + + void SCPI_Init(scpi_t * context); + + int SCPI_Input(scpi_t * context, const char * data, size_t len); + int SCPI_Parse(scpi_t * context, char * data, size_t len); + + + size_t SCPI_ResultString(scpi_t * context, const char * data); + size_t SCPI_ResultInt(scpi_t * context, int32_t val); + size_t SCPI_ResultDouble(scpi_t * context, double val); + size_t SCPI_ResultText(scpi_t * context, const char * data); + size_t SCPI_ResultBool(scpi_t * context, scpi_bool_t val); + + scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamString(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamText(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamBool(scpi_t * context, scpi_bool_t * value, scpi_bool_t mandatory); + scpi_bool_t SCPI_ParamChoice(scpi_t * context, const char * options[], int32_t * value, scpi_bool_t mandatory); + + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_PARSER_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/scpi.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,50 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI library include file + * + * + */ + +#ifndef SCPI_H +#define SCPI_H + +#include "scpi/parser.h" +#include "scpi/ieee488.h" +#include "scpi/error.h" +#include "scpi/constants.h" +#include "scpi/minimal.h" +#include "scpi/units.h" + + + +#endif /* SCPI_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/types.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,220 @@ +/*- + * Copyright (c) 2013 Jan Breuer + * Richard.hmm + * Copyright (c) 2012 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_types.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI data types + * + * + */ + +#ifndef SCPI_TYPES_H +#define SCPI_TYPES_H + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef FALSE + #define FALSE 0 +#endif +#ifndef TRUE + #define TRUE (!FALSE) +#endif + + /* basic data types */ + typedef bool scpi_bool_t; + /* typedef enum { FALSE = 0, TRUE } scpi_bool_t; */ + + /* IEEE 488.2 registers */ + enum _scpi_reg_name_t { + SCPI_REG_STB = 0, /* Status Byte */ + SCPI_REG_SRE, /* Service Request Enable Register */ + SCPI_REG_ESR, /* Standard Event Status Register (ESR, SESR) */ + SCPI_REG_ESE, /* Event Status Enable Register */ + SCPI_REG_OPER, /* OPERation Status Register */ + SCPI_REG_OPERE, /* OPERation Status Enable Register */ + SCPI_REG_QUES, /* QUEStionable status register */ + SCPI_REG_QUESE, /* QUEStionable status Enable Register */ + + /* last definition - number of registers */ + SCPI_REG_COUNT + }; + typedef enum _scpi_reg_name_t scpi_reg_name_t; + + enum _scpi_ctrl_name_t { + SCPI_CTRL_SRQ = 1, /* service request */ + SCPI_CTRL_GTL, /* Go to local */ + SCPI_CTRL_SDC, /* Selected device clear */ + SCPI_CTRL_PPC, /* Parallel poll configure */ + SCPI_CTRL_GET, /* Group execute trigger */ + SCPI_CTRL_TCT, /* Take control */ + SCPI_CTRL_LLO, /* Device clear */ + SCPI_CTRL_DCL, /* Local lockout */ + SCPI_CTRL_PPU, /* Parallel poll unconfigure */ + SCPI_CTRL_SPE, /* Serial poll enable */ + SCPI_CTRL_SPD, /* Serial poll disable */ + SCPI_CTRL_MLA, /* My local address */ + SCPI_CTRL_UNL, /* Unlisten */ + SCPI_CTRL_MTA, /* My talk address */ + SCPI_CTRL_UNT, /* Untalk */ + SCPI_CTRL_MSA /* My secondary address */ + }; + typedef enum _scpi_ctrl_name_t scpi_ctrl_name_t; + + typedef uint16_t scpi_reg_val_t; + + /* scpi commands */ + enum _scpi_result_t { + SCPI_RES_OK = 1, + SCPI_RES_ERR = -1 + }; + typedef enum _scpi_result_t scpi_result_t; + + typedef struct _scpi_command_t scpi_command_t; + + struct _scpi_buffer_t { + size_t length; + size_t position; + char * data; + }; + typedef struct _scpi_buffer_t scpi_buffer_t; + + struct _scpi_param_list_t { + const scpi_command_t * cmd; + const char * parameters; + size_t length; + scpi_buffer_t cmd_raw; + }; + #define SCPI_CMD_LIST_END {NULL, NULL, } + typedef struct _scpi_param_list_t scpi_param_list_t; + + /* scpi interface */ + typedef struct _scpi_t scpi_t; + typedef struct _scpi_interface_t scpi_interface_t; + + typedef size_t(*scpi_write_t)(scpi_t * context, const char * data, size_t len); + typedef scpi_result_t(*scpi_write_control_t)(scpi_t * context, scpi_ctrl_name_t ctrl, scpi_reg_val_t val); + typedef int (*scpi_error_callback_t)(scpi_t * context, int_fast16_t error); + + typedef scpi_result_t(*scpi_command_callback_t)(scpi_t *); + + /* scpi error queue */ + typedef void * scpi_error_queue_t; + + /* scpi units */ + enum _scpi_unit_t { + SCPI_UNIT_NONE, + SCPI_UNIT_VOLT, + SCPI_UNIT_AMPER, + SCPI_UNIT_OHM, + SCPI_UNIT_HERTZ, + SCPI_UNIT_CELSIUS, + SCPI_UNIT_SECONDS, + SCPI_UNIT_DISTANCE + }; + typedef enum _scpi_unit_t scpi_unit_t; + + struct _scpi_unit_def_t { + const char * name; + scpi_unit_t unit; + double mult; + }; + #define SCPI_UNITS_LIST_END {NULL, SCPI_UNIT_NONE, 0} + typedef struct _scpi_unit_def_t scpi_unit_def_t; + + enum _scpi_special_number_t { + SCPI_NUM_NUMBER, + SCPI_NUM_MIN, + SCPI_NUM_MAX, + SCPI_NUM_DEF, + SCPI_NUM_UP, + SCPI_NUM_DOWN, + SCPI_NUM_NAN, + SCPI_NUM_INF, + SCPI_NUM_NINF + }; + typedef enum _scpi_special_number_t scpi_special_number_t; + + struct _scpi_special_number_def_t { + const char * name; + scpi_special_number_t type; + }; + #define SCPI_SPECIAL_NUMBERS_LIST_END {NULL, SCPI_NUM_NUMBER} + typedef struct _scpi_special_number_def_t scpi_special_number_def_t; + + struct _scpi_number_t { + double value; + scpi_unit_t unit; + scpi_special_number_t type; + }; + typedef struct _scpi_number_t scpi_number_t; + + struct _scpi_command_t { + const char * pattern; + scpi_command_callback_t callback; + }; + + struct _scpi_interface_t { + scpi_error_callback_t error; + scpi_write_t write; + scpi_write_control_t control; + scpi_command_callback_t flush; + scpi_command_callback_t reset; + scpi_command_callback_t test; + }; + + struct _scpi_t { + const scpi_command_t * cmdlist; + scpi_buffer_t buffer; + scpi_param_list_t paramlist; + scpi_interface_t * interface; + 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; + const scpi_unit_def_t * units; + const scpi_special_number_def_t * special_numbers; + void * user_context; + const char * idn[4]; + }; + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_TYPES_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/units.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,57 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_units.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief SCPI Units + * + * + */ + +#ifndef SCPI_UNITS_H +#define SCPI_UNITS_H + +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + extern const scpi_unit_def_t scpi_units_def[]; + extern const scpi_special_number_def_t scpi_special_numbers_def[]; + + scpi_bool_t SCPI_ParamNumber(scpi_t * context, scpi_number_t * value, scpi_bool_t mandatory); + size_t SCPI_NumberToStr(scpi_t * context, scpi_number_t * value, char * str, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_UNITS_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scpi/utils_private.h Fri Nov 14 01:07:59 2014 +0000 @@ -0,0 +1,98 @@ +/*- + * 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: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 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 + * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file scpi_utils.h + * @date Thu Nov 15 10:58:45 UTC 2012 + * + * @brief Conversion routines and string manipulation routines + * + * + */ + +#ifndef SCPI_UTILS_H +#define SCPI_UTILS_H + +#include <stdint.h> +#include "scpi/config.h" +#include "scpi/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) && (__GNUC__ >= 4) + #define LOCAL __attribute__((visibility ("hidden"))) +#else + #define LOCAL +#endif + + const char * strnpbrk(const char *str, size_t size, const char *set) LOCAL; + scpi_bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) LOCAL; + scpi_bool_t compareStrAndNum(const char * str1, size_t len1, const char * str2, size_t len2) LOCAL; + size_t longToStr(int32_t val, char * str, size_t len) LOCAL; + size_t doubleToStr(double val, char * str, size_t len) LOCAL; + size_t strToLong(const char * str, int32_t * val) LOCAL; + size_t strToDouble(const char * str, double * val) LOCAL; + scpi_bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; + scpi_bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; + size_t skipWhitespace(const char * cmd, size_t len) LOCAL; + size_t skipColon(const char * cmd, size_t len) LOCAL; + scpi_bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) LOCAL; + scpi_bool_t matchCommand(const char * pattern, const char * cmd, size_t len) LOCAL; + scpi_bool_t composeCompoundCommand(char * ptr_prev, size_t len_prev, char ** pptr, size_t * plen); + +#if !HAVE_STRNLEN + size_t BSD_strnlen(const char *s, size_t maxlen); +#endif + +#if !HAVE_STRNCASECMP && !HAVE_STRNICMP + int OUR_strncasecmp(const char *s1, const char *s2, size_t n); +#endif + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +#if 0 +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SCPI_UTILS_H */ +