From f7020a99acd45c3206e424e7143fab1236f83d02 Mon Sep 17 00:00:00 2001 From: Martin Vladic Date: Sun, 1 Aug 2021 23:27:44 +0200 Subject: [PATCH] input widget encoder support --- src/eez/flow/components/scpi.cpp | 25 ++++++++++++---- src/eez/flow/components/set_variable.cpp | 6 ++-- src/eez/flow/flow.cpp | 18 ++++++++---- src/eez/flow/flow_defs_v3.h | 17 +++++++++++ src/eez/flow/private.cpp | 37 ++++++++++++++---------- src/eez/flow/private.h | 9 +++--- src/eez/gui/assets.h | 5 ++-- src/eez/gui/data.cpp | 30 ++++++++++++++++--- src/eez/gui/data.h | 4 ++- src/eez/gui/widgets/input.h | 4 +-- src/eez/modules/psu/gui/data.cpp | 7 +++++ src/eez/modules/psu/gui/edit_mode.cpp | 1 + src/eez/unit.cpp | 4 ++- src/eez/value_types.h | 1 + 14 files changed, 126 insertions(+), 42 deletions(-) diff --git a/src/eez/flow/components/scpi.cpp b/src/eez/flow/components/scpi.cpp index c7277163e..92217fa58 100644 --- a/src/eez/flow/components/scpi.cpp +++ b/src/eez/flow/components/scpi.cpp @@ -123,8 +123,23 @@ void executeScpiComponent(Assets *assets, FlowState *flowState, Component *compo #if FLOW_DEBUG printf("SCPI_PART_EXPR\n"); #endif - //uint8_t inputIndex = specific[i++]; - // TODO + + Value value; + int numInstructionBytes; + if (!evalExpression(assets, flowState, instructions + scpiComponentExecutionState->instructionIndex, value, &numInstructionBytes)) { + throwError("scpi component eval assignable expression"); + return; + } + scpiComponentExecutionState->instructionIndex += numInstructionBytes; + + char valueStr[256]; + value.toText(valueStr, sizeof(valueStr)); + + stringAppendString( + scpiComponentExecutionState->commandOrQueryText, + sizeof(scpiComponentExecutionState->commandOrQueryText), + valueStr + ); } else if (scpiComponentExecutionState->op == SCPI_PART_QUERY_WITH_ASSIGNMENT) { #if FLOW_DEBUG printf("SCPI_PART_QUERY_WITH_ASSIGNMENT\n"); @@ -143,9 +158,9 @@ void executeScpiComponent(Assets *assets, FlowState *flowState, Component *compo return; } - Value *pDstValue; + Value dstValue; int numInstructionBytes; - if (!evalAssignableExpression(assets, flowState, instructions + scpiComponentExecutionState->instructionIndex, &pDstValue, &numInstructionBytes)) { + if (!evalAssignableExpression(assets, flowState, instructions + scpiComponentExecutionState->instructionIndex, dstValue, &numInstructionBytes)) { throwError("scpi component eval assignable expression"); return; } @@ -155,7 +170,7 @@ void executeScpiComponent(Assets *assets, FlowState *flowState, Component *compo Value srcValue(resultText, resultTextLen); - assignValue(*pDstValue, srcValue); + assignValue(assets, flowState, component, dstValue, srcValue); } else if (scpiComponentExecutionState->op == SCPI_PART_QUERY) { #if FLOW_DEBUG printf("SCPI_PART_QUERY\n"); diff --git a/src/eez/flow/components/set_variable.cpp b/src/eez/flow/components/set_variable.cpp index f6b9a3148..ca3d981ed 100644 --- a/src/eez/flow/components/set_variable.cpp +++ b/src/eez/flow/components/set_variable.cpp @@ -44,8 +44,8 @@ void executeSetVariableComponent(Assets *assets, FlowState *flowState, Component }; auto setVariableActionComponent = (SetVariableActionComponent *)component; - Value *pDstValue; - if (!evalAssignableExpression(assets, flowState, setVariableActionComponent->assignableExpressionEvalInstructions, &pDstValue)) { + Value dstValue; + if (!evalAssignableExpression(assets, flowState, setVariableActionComponent->assignableExpressionEvalInstructions, dstValue)) { throwError("setvariable component eval dest assignable expression"); return; } @@ -57,7 +57,7 @@ void executeSetVariableComponent(Assets *assets, FlowState *flowState, Component return; } - assignValue(*pDstValue, srcValue); + assignValue(assets, flowState, component, dstValue, srcValue); } } // namespace flow diff --git a/src/eez/flow/flow.cpp b/src/eez/flow/flow.cpp index fe3bb9942..4927e7931 100644 --- a/src/eez/flow/flow.cpp +++ b/src/eez/flow/flow.cpp @@ -126,19 +126,27 @@ void dataOperation(unsigned flowHandle, int16_t dataId, DataOperationEnum operat if (widgetDataItem) { auto component = flow->components.item(assets, widgetDataItem->componentIndex); if (component->type == WIDGET_TYPE_INPUT) { - auto widget = (InputWidget *)widgetCursor.widget; + auto inputWidget = (InputWidget *)widgetCursor.widget; - auto unitValue = get(widgetCursor, widget->unit); + auto unitValue = get(widgetCursor, inputWidget->unit); Unit unit = getUnitFromName(unitValue.toString(assets)); if (operation == DATA_OPERATION_GET_MIN) { - value = Value(get(widgetCursor, widget->min).toFloat(), unit); + value = Value(get(widgetCursor, inputWidget->min).toFloat(), unit); } else if (operation == DATA_OPERATION_GET_MAX) { - value = Value(get(widgetCursor, widget->max).toFloat(), unit); + value = Value(get(widgetCursor, inputWidget->max).toFloat(), unit); + } else if (operation == DATA_OPERATION_GET_PRECISION) { + value = Value(get(widgetCursor, inputWidget->precision).toFloat(), unit); } else if (operation == DATA_OPERATION_GET_UNIT) { value = unit; } else if (operation == DATA_OPERATION_SET) { - // TODO + Value dstValue; + if (!evalAssignableExpression(assets, flowState, inputWidget->storeInto.ptr(assets), dstValue)) { + throwError("setvariable component eval dest assignable expression"); + return; + } + + assignValue(assets, flowState, component, dstValue, value); } } } diff --git a/src/eez/flow/flow_defs_v3.h b/src/eez/flow/flow_defs_v3.h index f2e7533e2..e23496192 100644 --- a/src/eez/flow/flow_defs_v3.h +++ b/src/eez/flow/flow_defs_v3.h @@ -45,6 +45,8 @@ enum ComponentTypes { COMPONENT_TYPE_SCROLL_BAR_WIDGET = 20, COMPONENT_TYPE_PROGRESS_WIDGET = 21, COMPONENT_TYPE_CANVAS_WIDGET = 22, + COMPONENT_TYPE_GAUGE_EMBEDDED_WIDGET = 23, + COMPONENT_TYPE_INPUT_EMBEDDED_WIDGET = 24, COMPONENT_TYPE_START_ACTION = 1001, COMPONENT_TYPE_END_ACTION = 1002, COMPONENT_TYPE_INPUT_ACTION = 1003, @@ -165,6 +167,21 @@ enum Component_CANVAS_WIDGET_Properties { CANVAS_WIDGET_PROPERTY_DATA = 0 }; +enum Component_GAUGE_EMBEDDED_WIDGET_Properties { + GAUGE_EMBEDDED_WIDGET_PROPERTY_DATA = 0, + GAUGE_EMBEDDED_WIDGET_PROPERTY_MIN = 1, + GAUGE_EMBEDDED_WIDGET_PROPERTY_MAX = 2, + GAUGE_EMBEDDED_WIDGET_PROPERTY_THRESHOLD = 3 +}; + +enum Component_INPUT_EMBEDDED_WIDGET_Properties { + INPUT_EMBEDDED_WIDGET_PROPERTY_DATA = 0, + INPUT_EMBEDDED_WIDGET_PROPERTY_MIN = 1, + INPUT_EMBEDDED_WIDGET_PROPERTY_MAX = 2, + INPUT_EMBEDDED_WIDGET_PROPERTY_PRECISION = 3, + INPUT_EMBEDDED_WIDGET_PROPERTY_UNIT = 4 +}; + enum Component_SET_VARIABLE_ACTION_COMPONENT_Properties { SET_VARIABLE_ACTION_COMPONENT_PROPERTY_VALUE = 0 }; diff --git a/src/eez/flow/private.cpp b/src/eez/flow/private.cpp index f9b37828c..6af673695 100644 --- a/src/eez/flow/private.cpp +++ b/src/eez/flow/private.cpp @@ -115,20 +115,26 @@ void propagateValue(Assets *assets, FlowState *flowState, ComponentOutput &compo //////////////////////////////////////////////////////////////////////////////// -void assignValue(Value &dstValue, const Value &srcValue) { - if (dstValue.isInt32OrLess()) { - dstValue.int32_ = srcValue.toInt32(); - } else if (dstValue.isFloat()) { - dstValue.float_ = srcValue.toFloat(); - } else if (dstValue.isDouble()) { - dstValue.float_ = srcValue.toDouble(); +void assignValue(Assets *assets, FlowState *flowState, Component *component, Value &dstValue, const Value &srcValue) { + if (dstValue.getType() == VALUE_TYPE_FLOW_OUTPUT) { + auto &componentOutput = *component->outputs.item(assets, dstValue.getUInt16()); + propagateValue(assets, flowState, componentOutput, srcValue); + } else { + Value *pDstValue = dstValue.pValue_; + if (pDstValue->isInt32OrLess()) { + pDstValue->int32_ = srcValue.toInt32(); + } else if (pDstValue->isFloat()) { + pDstValue->float_ = srcValue.toFloat(); + } else if (pDstValue->isDouble()) { + pDstValue->float_ = srcValue.toDouble(); + } + // TODO } - // TODO } //////////////////////////////////////////////////////////////////////////////// -bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, EvalStack &stack, int *numInstructionBytes) { +bool evalExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, EvalStack &stack, int *numInstructionBytes) { auto flowDefinition = assets->flowDefinition.ptr(assets); auto flow = flowDefinition->flows.item(assets, flowState->flowIndex); @@ -145,6 +151,8 @@ bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, stack.push(&flowState->values[flow->nInputValues + instructionArg]); } else if (instructionType == EXPR_EVAL_INSTRUCTION_TYPE_PUSH_GLOBAL_VAR) { stack.push(flowDefinition->globalVariables.item(assets, instructionArg)); + } else if (instructionType == EXPR_EVAL_INSTRUCTION_TYPE_PUSH_OUTPUT) { + stack.push(Value((uint16_t)instructionArg, VALUE_TYPE_FLOW_OUTPUT)); } else if (instructionType == EXPR_EVAL_INSTRUCTION_TYPE_OPERATION) { if (!g_evalOperations[instructionArg](stack)) { return false; @@ -164,10 +172,10 @@ bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, return true; } -bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, Value &result) { +bool evalExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, Value &result, int *numInstructionBytes) { EvalStack stack; - if (evalExpression(assets, flowState, instructions, stack)) { + if (evalExpression(assets, flowState, instructions, stack, numInstructionBytes)) { if (stack.sp == 1) { auto finalResult = stack.pop(); @@ -185,20 +193,19 @@ bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, return false; } -bool evalAssignableExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, Value **result, int *numInstructionBytes) { +bool evalAssignableExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, Value &result, int *numInstructionBytes) { EvalStack stack; if (evalExpression(assets, flowState, instructions, stack, numInstructionBytes)) { if (stack.sp == 1) { auto finalResult = stack.pop(); - if (finalResult.getType() == VALUE_TYPE_VALUE_PTR) { - *result = finalResult.pValue_; + if (finalResult.getType() == VALUE_TYPE_VALUE_PTR || finalResult.getType() == VALUE_TYPE_FLOW_OUTPUT) { + result = finalResult; return true; } } } - *result = nullptr; return false; } diff --git a/src/eez/flow/private.h b/src/eez/flow/private.h index 714aa719b..82836ff47 100644 --- a/src/eez/flow/private.h +++ b/src/eez/flow/private.h @@ -25,6 +25,7 @@ namespace flow { using eez::gui::Value; using eez::gui::Assets; +using eez::gui::Component; using eez::gui::ComponentOutput; struct FlowState { @@ -64,11 +65,11 @@ void recalcFlowDataItems(Assets *assets, FlowState *flowState); void pingComponent(Assets *assets, FlowState *flowState, unsigned componentIndex); void propagateValue(Assets *assets, FlowState *flowState, ComponentOutput &componentOutput, const gui::Value &value); -void assignValue(Value &dstValue, const Value &srcValue); +void assignValue(Assets *assets, FlowState *flowState, Component *component, Value &dstValue, const Value &srcValue); -bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, EvalStack &stack, int *numInstructionBytes = nullptr); -bool evalExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, Value &result); -bool evalAssignableExpression(Assets *assets, FlowState *flowState, uint8_t *instructions, Value **result, int *numInstructionBytes = nullptr); +bool evalExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, EvalStack &stack, int *numInstructionBytes = nullptr); +bool evalExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, Value &result, int *numInstructionBytes = nullptr); +bool evalAssignableExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, Value &result, int *numInstructionBytes = nullptr); void throwError(const char *errorMessage); diff --git a/src/eez/gui/assets.h b/src/eez/gui/assets.h index aef1c081a..5bee9b3cd 100644 --- a/src/eez/gui/assets.h +++ b/src/eez/gui/assets.h @@ -204,8 +204,9 @@ static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_CONSTANT = (0 << 13); static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_INPUT = (1 << 13); static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_LOCAL_VAR = (2 << 13); static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_GLOBAL_VAR = (3 << 13); -static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_OPERATION = (4 << 13); -static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_END = (5 << 13); +static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_OUTPUT = (4 << 13); +static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_OPERATION = (5 << 13); +static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_END = (6 << 13); struct PropertyValue { uint8_t evalInstructions[1]; diff --git a/src/eez/gui/data.cpp b/src/eez/gui/data.cpp index 88195c0b8..a20652989 100644 --- a/src/eez/gui/data.cpp +++ b/src/eez/gui/data.cpp @@ -507,6 +507,14 @@ void VALUE_PTR_value_to_text(const Value &value, char *text, int count) { } } +bool compare_FLOW_OUTPUT_value(const Value &a, const Value &b) { + return a.getUInt16() == b.getUInt16(); +} + +void FLOW_OUTPUT_value_to_text(const Value &value, char *text, int count) { + text[0] = 0; +} + bool compare_RANGE_value(const Value &a, const Value &b) { return a.getUInt32() == b.getUInt32(); } @@ -846,6 +854,12 @@ Value getDef(const WidgetCursor &widgetCursor, int16_t id) { return value; } +Value getPrecision(const WidgetCursor &widgetCursor, int16_t id) { + Value value; + DATA_OPERATION_FUNCTION(id, DATA_OPERATION_GET_PRECISION, widgetCursor, value); + return value; +} + Value getLimit(const WidgetCursor &widgetCursor, int16_t id) { Value value; DATA_OPERATION_FUNCTION(id, DATA_OPERATION_GET_LIMIT, widgetCursor, value); @@ -876,13 +890,21 @@ void getLabel(const WidgetCursor &widgetCursor, int16_t id, char *text, int cou value.toText(text, count); } -bool getEncoderStepValues(const WidgetCursor &widgetCursor, int16_t id, StepValues &stepValues) { +void getEncoderStepValues(const WidgetCursor &widgetCursor, int16_t id, StepValues &stepValues) { Value value(&stepValues, VALUE_TYPE_POINTER); DATA_OPERATION_FUNCTION(id, DATA_OPERATION_GET_ENCODER_STEP_VALUES, widgetCursor, value); - if (stepValues.encoderSettings.mode != ENCODER_MODE_AUTO) { - stepValues.encoderSettings.accelerationEnabled = false; + if (value.getType() == VALUE_TYPE_INT32 && value.getInt()) { + if (stepValues.encoderSettings.mode != ENCODER_MODE_AUTO) { + stepValues.encoderSettings.accelerationEnabled = false; + } + } else { + stepValues.count = 0; + stepValues.encoderSettings.accelerationEnabled = true; + stepValues.encoderSettings.mode = ENCODER_MODE_AUTO; + stepValues.encoderSettings.range = getMax(widgetCursor, id).toFloat() - getMin(widgetCursor, id).toFloat(); + Value precisionValue = getPrecision(widgetCursor, id); + stepValues.encoderSettings.step = precisionValue.toFloat(); } - return value.getType() == VALUE_TYPE_INT32 && value.getInt(); } void setEncoderMode(const WidgetCursor &widgetCursor, int16_t id, EncoderMode encoderMode) { diff --git a/src/eez/gui/data.h b/src/eez/gui/data.h index abfa0351a..4355b06db 100644 --- a/src/eez/gui/data.h +++ b/src/eez/gui/data.h @@ -573,6 +573,7 @@ enum DataOperationEnum { DATA_OPERATION_GET_MIN, DATA_OPERATION_GET_MAX, DATA_OPERATION_GET_DEF, + DATA_OPERATION_GET_PRECISION, DATA_OPERATION_GET_LIMIT, DATA_OPERATION_GET_NAME, DATA_OPERATION_GET_UNIT, @@ -650,6 +651,7 @@ bool getAllowZero(const WidgetCursor &widgetCursor, int16_t id); Value getMin(const WidgetCursor &widgetCursor, int16_t id); Value getMax(const WidgetCursor &widgetCursor, int16_t id); Value getDef(const WidgetCursor &widgetCursor, int16_t id); +Value getPrecision(const WidgetCursor &widgetCursor, int16_t id); Value getLimit(const WidgetCursor &widgetCursor, int16_t id); const char *getName(const WidgetCursor &widgetCursor, int16_t id); Unit getUnit(const WidgetCursor &widgetCursor, int16_t id); @@ -657,7 +659,7 @@ bool isChannelData(const WidgetCursor &widgetCursor, int16_t id); void getLabel(const WidgetCursor &widgetCursor, int16_t id, char *text, int count); -bool getEncoderStepValues(const WidgetCursor &widgetCursor, int16_t id, StepValues &stepValues); +void getEncoderStepValues(const WidgetCursor &widgetCursor, int16_t id, StepValues &stepValues); void setEncoderMode(const WidgetCursor &widgetCursor, int16_t id, EncoderMode encoderMode); Value get(const WidgetCursor &widgetCursor, int16_t id); diff --git a/src/eez/gui/widgets/input.h b/src/eez/gui/widgets/input.h index 71d753257..ffd8d8260 100644 --- a/src/eez/gui/widgets/input.h +++ b/src/eez/gui/widgets/input.h @@ -22,12 +22,12 @@ namespace eez { namespace gui { struct InputWidget : public Widget { - uint16_t flags; + AssetsPtr storeInto; // assignableExpressionEvalInstructions + uint16_t flags; int16_t min; int16_t max; int16_t precision; int16_t unit; - AssetsPtr storeInto; // assignableExpressionEvalInstructions }; } // namespace gui diff --git a/src/eez/modules/psu/gui/data.cpp b/src/eez/modules/psu/gui/data.cpp index bd7957904..0b977258c 100644 --- a/src/eez/modules/psu/gui/data.cpp +++ b/src/eez/modules/psu/gui/data.cpp @@ -4269,6 +4269,8 @@ void data_channel_list_voltage(DataOperationEnum operation, const WidgetCursor & stepValues->encoderSettings.range = g_channel->params.U_MAX; stepValues->encoderSettings.step = g_channel->params.U_RESOLUTION; stepValues->encoderSettings.mode = edit_mode_step::g_listVoltageEncoderMode; + + value = 1; } else if (operation == DATA_OPERATION_SET_ENCODER_MODE) { edit_mode_step::g_listVoltageEncoderMode = (EncoderMode)value.getInt(); } @@ -4326,6 +4328,8 @@ void data_channel_list_current(DataOperationEnum operation, const WidgetCursor & stepValues->encoderSettings.range = g_channel->params.I_MAX; stepValues->encoderSettings.step = g_channel->params.I_RESOLUTION; stepValues->encoderSettings.mode = edit_mode_step::g_listCurrentEncoderMode; + + value = 1; } else if (operation == DATA_OPERATION_SET_ENCODER_MODE) { edit_mode_step::g_listCurrentEncoderMode = (EncoderMode)value.getInt(); } @@ -5839,6 +5843,7 @@ void data_channel_voltage_ramp_duration(DataOperationEnum operation, const Widge value = 1; } else if (operation == DATA_OPERATION_GET_ENCODER_STEP_VALUES) { getRampAndDelayDurationStepValues(value); + value = 1; } else if (operation == DATA_OPERATION_SET_ENCODER_MODE) { edit_mode_step::g_rampAndDelayDurationEncoderMode = (EncoderMode)value.getInt(); } @@ -5886,6 +5891,7 @@ void data_channel_current_ramp_duration(DataOperationEnum operation, const Widge value = 1; } else if (operation == DATA_OPERATION_GET_ENCODER_STEP_VALUES) { getRampAndDelayDurationStepValues(value); + value = 1; } else if (operation == DATA_OPERATION_SET_ENCODER_MODE) { edit_mode_step::g_rampAndDelayDurationEncoderMode = (EncoderMode)value.getInt(); } @@ -5933,6 +5939,7 @@ void data_channel_output_delay(DataOperationEnum operation, const WidgetCursor & value = 1; } else if (operation == DATA_OPERATION_GET_ENCODER_STEP_VALUES) { getRampAndDelayDurationStepValues(value); + value = 1; } else if (operation == DATA_OPERATION_SET_ENCODER_MODE) { edit_mode_step::g_rampAndDelayDurationEncoderMode = (EncoderMode)value.getInt(); } diff --git a/src/eez/modules/psu/gui/edit_mode.cpp b/src/eez/modules/psu/gui/edit_mode.cpp index 3d66b5a83..ac583a155 100644 --- a/src/eez/modules/psu/gui/edit_mode.cpp +++ b/src/eez/modules/psu/gui/edit_mode.cpp @@ -457,6 +457,7 @@ static Value getCurrentEncoderStepValue() { float getEncoderStepValue() { StepValues stepValues; + edit_mode_step::getStepValues(stepValues); if (stepValues.encoderSettings.mode == ENCODER_MODE_AUTO) { diff --git a/src/eez/unit.cpp b/src/eez/unit.cpp index 072819722..8dfe23039 100644 --- a/src/eez/unit.cpp +++ b/src/eez/unit.cpp @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include + #include #include @@ -116,4 +118,4 @@ int getScpiUnit(Unit unit) { return g_scpiUnits[unit]; } -} // namespace eez \ No newline at end of file +} // namespace eez diff --git a/src/eez/value_types.h b/src/eez/value_types.h index 65177ca72..21a91d058 100644 --- a/src/eez/value_types.h +++ b/src/eez/value_types.h @@ -39,6 +39,7 @@ VALUE_TYPE(ASSETS_STRING) \ VALUE_TYPE(VERSIONED_STRING) \ VALUE_TYPE(VALUE_PTR) \ + VALUE_TYPE(FLOW_OUTPUT) \ VALUE_TYPE(RANGE) \ VALUE_TYPE(PASSWORD) \ VALUE_TYPE(ENUM) \