From f7a934e2fc5c0b573ae47ac6fa8d1b89cd0af4ad Mon Sep 17 00:00:00 2001 From: Martin Vladic Date: Mon, 2 Aug 2021 19:51:51 +0200 Subject: [PATCH] input widget debugging --- .vscode/settings.json | 3 +- src/eez/flow/flow.cpp | 5 +- src/eez/flow/flow.h | 1 + src/eez/flow/private.cpp | 38 ++++++++- src/eez/flow/private.h | 2 +- src/eez/platform/simulator/cmsis_os.cpp | 105 +++++++++++++++--------- src/eez/platform/simulator/cmsis_os.h | 39 ++++++--- src/eez/scripting/flow.cpp | 26 ++++-- src/eez/scripting/thread.cpp | 9 +- 9 files changed, 162 insertions(+), 66 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 807095d89..7dcc739ad 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,7 +25,8 @@ "ostream": "cpp", "streambuf": "cpp", "limits": "cpp", - "cmath": "cpp" + "cmath": "cpp", + "functional": "cpp" }, "C_Cpp.errorSquiggles": "Disabled", "cmake.configureOnOpen": true diff --git a/src/eez/flow/flow.cpp b/src/eez/flow/flow.cpp index 9b36c8537..ad43959bb 100644 --- a/src/eez/flow/flow.cpp +++ b/src/eez/flow/flow.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include #include #include @@ -140,7 +142,8 @@ void dataOperation(unsigned flowHandle, int16_t dataId, DataOperationEnum operat } else if (operation == DATA_OPERATION_GET_UNIT) { value = unit; } else if (operation == DATA_OPERATION_SET) { - setValueFromGuiThread(assets, flowState, component, dataId, value); + setValueFromGuiThread(assets, flowState, dataId, value); + scripting::executeFlowAction(widgetCursor, inputWidget->action); } } } diff --git a/src/eez/flow/flow.h b/src/eez/flow/flow.h index 45f04f425..bd6363944 100644 --- a/src/eez/flow/flow.h +++ b/src/eez/flow/flow.h @@ -32,6 +32,7 @@ void stop(); void *getFlowState(int16_t pageId); void executeFlowAction(unsigned flowHandle, const WidgetCursor &widgetCursor, int16_t actionId); +void doSetFlowValue(); void dataOperation(unsigned flowHandle, int16_t dataId, DataOperationEnum operation, const WidgetCursor &widgetCursor, Value &value); } // flow diff --git a/src/eez/flow/private.cpp b/src/eez/flow/private.cpp index 29767aa25..4dddd7bb5 100644 --- a/src/eez/flow/private.cpp +++ b/src/eez/flow/private.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -116,19 +117,50 @@ void propagateValue(Assets *assets, FlowState *flowState, ComponentOutput &compo //////////////////////////////////////////////////////////////////////////////// struct { + bool isActive; Assets *assets; FlowState *flowState; - Component *component; uint16_t dataId; Value value; } g_setValueFromGuiThreadParams; -void setValueFromGuiThread(Assets *assets, FlowState *flowState, Component *component, uint16_t dataId, const Value& value) { +void setValueFromGuiThread(Assets *assets, FlowState *flowState, uint16_t dataId, const Value& value) { + while (g_setValueFromGuiThreadParams.isActive) { + osDelay(1); + } + + g_setValueFromGuiThreadParams.isActive = true; g_setValueFromGuiThreadParams.assets = assets; g_setValueFromGuiThreadParams.flowState = flowState; - g_setValueFromGuiThreadParams.component = component; g_setValueFromGuiThreadParams.dataId = dataId; g_setValueFromGuiThreadParams.value = value; + + scripting::setFlowValueInScriptingThread(); +} + +void doSetFlowValue() { + if (scripting::isFlowRunning()) { + Assets *assets = g_setValueFromGuiThreadParams.assets; + FlowState *flowState = g_setValueFromGuiThreadParams.flowState; + uint16_t dataId = g_setValueFromGuiThreadParams.dataId; + + auto flowDefinition = assets->flowDefinition.ptr(assets); + auto flow = flowDefinition->flows.item(assets, flowState->flowIndex); + + WidgetDataItem *widgetDataItem = flow->widgetDataItems.item(assets, dataId); + if (widgetDataItem) { + auto component = flow->components.item(assets, widgetDataItem->componentIndex); + auto propertyValue = component->propertyValues.item(assets, widgetDataItem->propertyValueIndex); + + Value dstValue; + if (evalAssignableExpression(assets, flowState, propertyValue->evalInstructions, dstValue)) { + assignValue(assets, flowState, component, dstValue, g_setValueFromGuiThreadParams.value); + } else { + throwError("doSetFlowValue failed"); + } + } + } + g_setValueFromGuiThreadParams.isActive = false; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/eez/flow/private.h b/src/eez/flow/private.h index 3502e620e..ce4b11084 100644 --- a/src/eez/flow/private.h +++ b/src/eez/flow/private.h @@ -65,7 +65,7 @@ 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 setValueFromGuiThread(Assets *assets, FlowState *flowState, Component *component, uint16_t dataId, const Value& value); +void setValueFromGuiThread(Assets *assets, FlowState *flowState, uint16_t dataId, const Value& value); void assignValue(Assets *assets, FlowState *flowState, Component *component, Value &dstValue, const Value &srcValue); bool evalExpression(Assets *assets, FlowState *flowState, const uint8_t *instructions, EvalStack &stack, int *numInstructionBytes = nullptr); diff --git a/src/eez/platform/simulator/cmsis_os.cpp b/src/eez/platform/simulator/cmsis_os.cpp index 8fc2e3774..3e531bbb9 100644 --- a/src/eez/platform/simulator/cmsis_os.cpp +++ b/src/eez/platform/simulator/cmsis_os.cpp @@ -13,6 +13,8 @@ std::map g_handles; #include #endif +//////////////////////////////////////////////////////////////////////////////// + #ifdef __EMSCRIPTEN__ #define MAX_THREADS 100 struct Thread { @@ -73,6 +75,8 @@ osThreadId osThreadGetId() { #endif } +//////////////////////////////////////////////////////////////////////////////// + #ifdef __EMSCRIPTEN__ void eez_system_tick() { for (int i = 0; i < MAX_THREADS; ++i) { @@ -134,21 +138,46 @@ uint32_t osKernelSysTick() { #endif } -osMessageQId osMessageCreate(osMessageQId queue_id, osThreadId thread_id) { - queue_id->tail = 0; - queue_id->head = 0; - queue_id->overflow = 0; - return queue_id; +//////////////////////////////////////////////////////////////////////////////// + +Mutex *osMutexCreate(Mutex &mutex) { + return &mutex; +} + +osStatus osMutexWait(Mutex *mutex, unsigned int timeout) { +#ifndef __EMSCRIPTEN__ + mutex->lock(); +#endif + return osOK; +} + +void osMutexRelease(Mutex *mutex) { +#ifndef __EMSCRIPTEN__ + mutex->unlock(); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +osMessageQId osMessageCreate(osMessageQId queue, osThreadId thread_id) { + queue->tail = 0; + queue->head = 0; + queue->overflow = 0; + return queue; } -osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec) { +osEvent osMessageGet(osMessageQId queue, uint32_t millisec) { if (millisec == 0) millisec = 1; - while (queue_id->tail == queue_id->head) { - if (queue_id->overflow) { - queue_id->overflow = 0; + queue->mutex.lock(); + + while (queue->tail == queue->head) { + if (queue->overflow) { + break; } + queue->mutex.unlock(); + #ifdef __EMSCRIPTEN__ return { osOK, @@ -166,57 +195,53 @@ osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec) { }; } #endif + + queue->mutex.lock(); } - uint16_t tail = queue_id->tail + 1; - if (tail >= queue_id->numElements) { + + uint16_t tail = queue->tail + 1; + if (tail >= queue->numElements) { tail = 0; } - queue_id->tail = tail; - uint32_t info = ((uint32_t *)queue_id->data)[tail]; - if (queue_id->overflow) { - queue_id->overflow = 0; + queue->tail = tail; + uint32_t info = ((uint32_t *)queue->data)[tail]; + if (queue->overflow) { + queue->overflow = 0; } + + queue->mutex.unlock(); + return { osEventMessage, info }; } -osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec) { - for (uint32_t i = 0; queue_id->overflow && i < millisec; i++) { +osStatus osMessagePut(osMessageQId queue, uint32_t info, uint32_t millisec) { + queue->mutex.lock(); + for (uint32_t i = 0; queue->overflow && i < millisec; i++) { + queue->mutex.unlock(); osDelay(1); + queue->mutex.lock(); } - if (queue_id->overflow) { + if (queue->overflow) { + queue->mutex.unlock(); printf("overflow\n"); - return osOK; + return osError; } - uint16_t head = queue_id->head + 1; - if (head >= queue_id->numElements) { + uint16_t head = queue->head + 1; + if (head >= queue->numElements) { head = 0; } - ((uint32_t *)queue_id->data)[head] = info; - queue_id->head = head; - if (queue_id->head == queue_id->tail) { - queue_id->overflow = 1; + ((uint32_t *)queue->data)[head] = info; + queue->head = head; + if (queue->head == queue->tail) { + queue->overflow = 1; } - return osOK; -} -uint32_t osMessageWaiting(osMessageQId queue_id) { - return queue_id->head - queue_id->tail; -} + queue->mutex.unlock(); -Mutex *osMutexCreate(Mutex &mutex) { - return &mutex; -} - -osStatus osMutexWait(Mutex *mutex, unsigned int timeout) { - mutex->lock(); return osOK; } - -void osMutexRelease(Mutex *mutex) { - mutex->unlock(); -} diff --git a/src/eez/platform/simulator/cmsis_os.h b/src/eez/platform/simulator/cmsis_os.h index 531d408f2..a74f02fd8 100644 --- a/src/eez/platform/simulator/cmsis_os.h +++ b/src/eez/platform/simulator/cmsis_os.h @@ -1,10 +1,14 @@ #pragma once #include + +#ifndef __EMSCRIPTEN__ #include +#endif typedef enum { osOK = 0, + osError = 1, osEventMessage = 0x10 } osStatus; @@ -14,6 +18,8 @@ typedef enum { osPriorityAboveNormal = 1 } osPriority; +//////////////////////////////////////////////////////////////////////////////// + typedef void (*os_pthread)(void const *argument); #ifdef EEZ_PLATFORM_SIMULATOR_WIN32 @@ -68,6 +74,8 @@ osStatus osThreadTerminate(osThreadId thread_id); osThreadId osThreadGetId(); +//////////////////////////////////////////////////////////////////////////////// + osStatus osKernelStart(void); osStatus osDelay(uint32_t millisec); @@ -87,11 +95,30 @@ struct osEvent { } value; }; +//////////////////////////////////////////////////////////////////////////////// +// Mutex + +#ifdef __EMSCRIPTEN__ +typedef bool Mutex; +#else +typedef std::mutex Mutex; +#endif + +#define osMutexDef(mutex) Mutex mutex +#define osMutexId(mutexId) Mutex *mutexId +#define osMutex(mutex) mutex + +Mutex *osMutexCreate(Mutex &mutex); +osStatus osMutexWait(Mutex *mutex, unsigned int timeout); +void osMutexRelease(Mutex *mutex); + +//////////////////////////////////////////////////////////////////////////////// // Message Queue struct MessageQueue { void *data; uint8_t numElements; + Mutex mutex; volatile uint16_t tail; volatile uint16_t head; volatile uint8_t overflow; @@ -110,16 +137,4 @@ typedef MessageQueue *osMessageQId; osMessageQId osMessageCreate(osMessageQId queue_id, osThreadId thread_id); osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec); osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec); -uint32_t osMessageWaiting(osMessageQId queue_id); - -// Mutex - -typedef std::mutex Mutex; -#define osMutexDef(mutex) Mutex mutex -#define osMutexId(mutexId) Mutex *mutexId -#define osMutex(mutex) mutex - -Mutex *osMutexCreate(Mutex &mutex); -osStatus osMutexWait(Mutex *mutex, unsigned int timeout); -void osMutexRelease(Mutex *mutex); \ No newline at end of file diff --git a/src/eez/scripting/flow.cpp b/src/eez/scripting/flow.cpp index ce0b8ccfd..407278877 100644 --- a/src/eez/scripting/flow.cpp +++ b/src/eez/scripting/flow.cpp @@ -31,9 +31,6 @@ namespace scripting { static unsigned g_flowHandle; -WidgetCursor g_actionWidgetCursor; -int16_t g_actionId; - bool loadFlowScript(int *err) { int localErr = SCPI_RES_OK; if (!err) { @@ -90,20 +87,35 @@ void executeScpiFromFlow(const char *commandOrQueryText) { executeScpi(commandOrQueryText, true); } +//////////////////////////////////////////////////////////////////////////////// + +static struct { + bool isActive; + WidgetCursor widgetCursor; + int16_t actionId; +} g_executeFlowAction; + void executeFlowAction(const WidgetCursor &widgetCursor, int16_t actionId) { - // TODO check overwrite - g_actionWidgetCursor = widgetCursor; - g_actionId = actionId; + while (g_executeFlowAction.isActive) { + osDelay(1); + } + + g_executeFlowAction.isActive = true; + g_executeFlowAction.widgetCursor = widgetCursor; + g_executeFlowAction.actionId = actionId; executeFlowActionInScriptingThread(); } void doExecuteFlowAction() { if (isFlowRunning()) { - flow::executeFlowAction(g_flowHandle, g_actionWidgetCursor, g_actionId); + flow::executeFlowAction(g_flowHandle, g_executeFlowAction.widgetCursor, g_executeFlowAction.actionId); } + g_executeFlowAction.isActive = false; } +//////////////////////////////////////////////////////////////////////////////// + bool isFlowRunning() { return g_flowHandle != 0; } diff --git a/src/eez/scripting/thread.cpp b/src/eez/scripting/thread.cpp index d9f3cbd78..4993f4fb2 100644 --- a/src/eez/scripting/thread.cpp +++ b/src/eez/scripting/thread.cpp @@ -32,6 +32,7 @@ enum { QUEUE_MESSAGE_START_MP_SCRIPT, QUEUE_MESSAGE_START_FLOW_SCRIPT, QUEUE_MESSAGE_EXECUTE_FLOW_ACTION, + QUEUE_MESSAGE_SET_FLOW_VALUE, QUEUE_MESSAGE_STOP_FLOW, QUEUE_MESSAGE_SCPI_RESULT }; @@ -80,7 +81,11 @@ void startFlowScriptInScriptingThread() { } void executeFlowActionInScriptingThread() { - osMessagePut(g_mpMessageQueueId, QUEUE_MESSAGE_EXECUTE_FLOW_ACTION, 1000); + osMessagePut(g_mpMessageQueueId, QUEUE_MESSAGE_EXECUTE_FLOW_ACTION, 500); +} + +void setFlowValueInScriptingThread() { + osMessagePut(g_mpMessageQueueId, QUEUE_MESSAGE_SET_FLOW_VALUE, 500); } void stopFlowInScriptingThread() { @@ -112,6 +117,8 @@ void oneIter() { startFlowScript(); } else if (event.value.v == QUEUE_MESSAGE_EXECUTE_FLOW_ACTION) { doExecuteFlowAction(); + } else if (event.value.v == QUEUE_MESSAGE_SET_FLOW_VALUE) { + flow::doSetFlowValue(); } else if (event.value.v == QUEUE_MESSAGE_STOP_FLOW) { flow::stop(); } else if (event.value.v == QUEUE_MESSAGE_SCPI_RESULT) {