SlideServe
Menu
Préférences
© SlideServe · v2026

Converting Asynchronous Code to Synchronous Using Lua for Medical Diagnostic Protocols

kanoa avatar
28 diapositives · 458 Views · Jul 26, 2014

This talk explores the use of Embedded Lua to simplify the development of custom test protocols for a medical diagnostic device. By integrating a lightweight scripting language, we can add new functionality without revisiting the firmware. The presentation covers the advantages of Lua, including its small footprint, easy embedding in C, and coroutine support, making it ideal for real-time applications. Practical examples will be shared to demonstrate how to implement synchronous operations to manage complex testing scenarios effectively.

Converting Asynchronous Code to Synchronous Using Lua for Medical Diagnostic Protocols - slide 1
01 / 28Converting Asynchronous Code to Synchronous Using Lua for Medical Diagnostic Protocols
1 / 17

Télécharger la présentation

Converting Asynchronous Code to Synchronous Using Lua for Medical Diagnostic Protocols
Une image / un lien ci-dessous est fourni (tel quel) pour télécharger la présentation

Politique de téléchargement : le contenu du site vous est fourni TEL QUEL pour votre information et votre usage personnel ; il ne peut être vendu, concédé sous licence ni partagé sur d’autres sites sans l’accord de son auteur.Le contenu vous est fourni TEL QUEL, pour votre information et votre usage personnel uniquement. Téléchargez la présentation en cliquant sur ce lien. Lors du téléchargement, si vous ne parvenez pas à télécharger une présentation, l’éditeur a peut-être supprimé le fichier de son serveur.Pendant le téléchargement, si vous ne parvenez pas à obtenir une présentation, le fichier a peut-être été supprimé par l’éditeur.

F I N

Plus de contenu associé

Transcription de la présentation
  1. Converting Asynchronous Code to Synchronous Code with Embedded Lua MoCo Programming Language Junkies Josh Handley February 6, 2014 http://www.meetup.com/mcpjunkies/

  2. Motivation • How do we support custom test protocols for a medical diagnostic device? • Simple scripting language • Add new protocols without new firmware • Hide complexity

  3. What we Had voidTestingPage::instructionPageCancelled() { switch (screen_) { caseElectrodeSetup: test_->cancelTest(); // Mark this specific test as cancelled. A retry will make a new test. gotoConfirmCancelScreen(); break; caseAlignPupil: caseTesting: qCritical("instructionPageCancelled when aligning or testing pupil?"); // Can't happen. break; caseErrorOccurred: gotoConfirmCancelScreen(); break; caseConfirmingCancel: caseConfirmingSkip: emitrestartTest(); // User said no to cancel or skip. Tell the controller to restart the test. break;     } }

  4. What we Wanted connectElectrodes() alignPupil() setTestConfiguration(testParams) results = runTest() showResultsScreen(results)

  5. What Language to Use • Custom language Too much work • Python Too big • Javascript No coroutines • Scheme Too many parentheses • Lua Just right

  6. Overview of Lua • Small • 20,000 lines of C code • < 250K compiled • no dependencies • Easy to embed in C • Has coroutines • Significant commercial use • Game engines (Angry Birds, WoW) • Adobe Lightroom • Ginga(Brazillian Digital TV Spec)

  7. Basic Types -- Number print(12) -- 12 print(1.2) -- 1.2 print((1.2 + 0.8)/2) -- 1 -- Bool print(trueorfalseandtrue) -- true -- String print("hello") -- hello print("hello "..tostring(1)) -- hello 1 print(string.format("hello %d", 1)) -- hello 1

  8. DynamicTyping v = 12 print(type(v)) –- number v = "hello" print(type(v)) -- string

  9. Functions - Recursion functionfactorial(n) if n == 0 then return 1 else return n * factorial(n - 1) end end print(factorial(10)) -- 3628800

  10. Functions – Multiple Return Values functionaddVector(x1, y1, x2, y2) return x1 + y1, x2 +y2 end x, y = addVector(1, 6, 2, 4) print(x,y) -- 7 6

  11. Functions – First Class function curry(f, x) returnfunction (y, ...) returnf(x,y,...) end end plusOne= curry(function(x, y) return x + y end, 1) print(plusOne(2)) -- 3

  12. Global by Default -- global n = 12 s = "hello" functionsqr(x) return x * x end -- local to file localn_local = 12 locals_local = "hello2" localfunctionsqr_local(x) return x * x end -- local to block function foo() local message = "dude"-- not visible outside function print(message) print(s_local) -- locals in this file are in foo closure ("up values") end

  13. Loops -- repeat i = 1 repeat print(i) i = i + 1 untili == 5 -- while i= 1 whilei < 5 do print(i) i = i + 1 end -- for fori = 1, 4 do print(i) end

  14. Tables – THE Data Structure -- Arrays localarr = {1, 2, 3, 4, "foo"} print(arr[1]) -- 1 print(arr[5]) -- foo arr[8] = 12 print(arr[8]) – 12 print(arr[7]) -- nil

  15. Tables – THE Data Structure -- Dictionaries localdict = { firstName = "John", lastName = "Doe", dateOfBirth = {year = 1999, month = 12, day = 15} } print(dict.firstName) -- John print(dict.dateOfBirth.year) -- 1999 print(dict["firstName"]) -- John

  16. Tables - Iteration -- Arrays fori, v inipairs(arr) do print(i.." = "..tostring(v)) end -- Dictionaries for k, v in pairs(dict) do print(k.." = "..tostring(v)) end

  17. Errors -- error function error("This will abort the program and show this message") -- assert function assert(foo == 6, "Error: foo is not 6") -- nil, message pattern local file, errorMessage = io.open("myfile.txt", "r") if file == nilthen error("Error opening file: "..errorMessage) end -- nil, message with assert local file2 = assert(io.open("loops.lua", "r"))

  18. pcall localfunctionparseConfigFile(filename) … end local status, resultOrErrorMessage = pcall(parseConfigFile, "config.txt") if status then print(string.format("Sucessfully parsed config file.")) for k, v in pairs(resultOrErrorMessage) do print(k, v) end else print("Failed to parse config file. "..resultOrErrorMessage) end

  19. Coroutines - Generators localevenNumbers = coroutine.create(function() locali = 2 whiletruedo coroutine.yield(i) i = i + 2 end end ) print(evenNumbers) -- thread: 002FF108 print(coroutine.resume(evenNumbers)) -- true 2 print(coroutine.resume(evenNumbers)) -- true 4

  20. Coroutines – Producer/Consumer local producer = coroutine.create(function() fori = 1, 4 do print("Enter something:") coroutine.yield(io.read("*line")) end end ) local consumer = coroutine.create(function(prod) whiletruedo local status, value = coroutine.resume(prod) print("Consume: "..value) end end ) coroutine.resume(consumer, producer)

  21. CallingLuafrom C #include<lua.h> #include<lauxlib.h> #include<lualib.h> int main(intargc, char *argv[]) { lua_State* L = luaL_newstate(); luaL_openlibs(L); constchar *luaCode= "print('Hello World')"; luaL_dostring(L, luaCode); lua_close(L); return 0; }

  22. Exposing C functions to Lua intmyCFunction(lua_State* L) { constchar *arg = luaL_checkstring(L, -1); lua_pushstring(L, "Hello from C"); return 1; } int main(intargc, char *argv[]) { lua_State* L = luaL_newstate(); luaL_openlibs(L); lua_pushcfunction(L, myCFunction); lua_setglobal(L, "myCFunction"); constchar* luaCode = "local answerFromC = myCFunction('Hello From Lua')" "print('C says: '..answerFromC)"; luaL_dostring(L, luaCode); lua_close(L); return 0; }

  23. Back to the Original Problem • Create Lua bindings for our existing C++ objects/functions • Load Lua protocol script from disk • Create coroutine for the script • C++ resumes the coroutine • Lua scripts yield back to C++ to wait for events

  24. Coroutines Straight Line Code • C++ Event Loop • onStartTest() • Load protocol script • Create Luacoroutine • Resume coroutine • Back to event loop • onEventForLua() • Resume coroutine • If coroutine done end test • Back to event loop Lua showConnectElectrodeScreen() localevt repeat evt = waitForEvent() -- yields until evt.id == Event_Next

  25. Protocols Look Synchronous functionrunTests(testParameterList) localpreliminaryResults = {} teststeps.doConnectElectrodes() teststeps.doAlignPupil() ui.showTestingScreen() -- Run the tests fori = 1, #testParameterListdo localparams = testParameterList[i] localtestStimulus = stimconfig.buildStimulusConfig(params.flash, params.background) table.insert(preliminaryResults, teststeps.doTest(testStimulus)) ui.showTestingProgress(i, #testParameterList) end returnpreliminaryResults end

  26. Wrap Everything in a pcall whiletruedo localok,results_or_err = pcall(runTests, testParams) if ok then saveTestResults(results_or_err) break end local err = results_or_err -- If the user cancelled or skipped a test, confirm before taking action if err == RffID.Event_UI_Cancelledthen ifui.doConfirmCancelScreen() ~= RffID.Event_UI_Nextthen err = RffID.Event_UI_Restart end elseif err == RffID.Event_UI_Skippedthen ifui.doConfirmSkipScreen() ~= RffID.Event_UI_Nextthen err = RffID.Event_UI_Restart end end if err == RffID.Event_UI_Skippedthen break elseif err == RffID.Event_UI_Restartthen -- Back to top of loop to restart else -- Cancel or some other error, throw it again and let C++ (or another Luapcall) handle it error(err, 0) end end

  27. Lovin’ Lua • 4,000+ lines of Lua code • Beyond protocol scripts • On-board diagnostics • Interactive Lua shell for testing on device • Windows Lua shell controls device via RPC • Report generation • Viewing saved test results • Manufacturing/calibration

  28. Resources • Programming in Lua • http://www.lua.org/pil/ • Lua reference manual • http://www.lua.org/manual/5.2/ • luausers.org wiki • http://lua-users.org/wiki/ • Source code from this talk • http://github.com/jhandley/mcp-junkies-lua