Home | ER-101 | ER-102 | ER-301 | Wiki | Contact

Middle Layer SDK (aka patching with Lua)



A post was merged into an existing topic: Middle Layer Adventure - Revolver


By the way, I’m looking for a better terminology than just Object. Whenever I need to start a hierarchy of classes and its not obvious to me what to name the root, I just go with Object so that I can move on and get stuff done. Usually I will go back and rename it but in this case I haven’t yet. :sweat_smile:


I generated some annotation of relevant parts of the C++ code hierarchy using doxygen. Unzip them on your computer somewhere and open up the index.html file to start browsing the class hierarchies.

These are all of the DSP objects.
er-301-objects-doxygen-v0.3.18.zip (1.7 MB)

These are all of the Graphics objects.
er-301-graphics-doxygen-v0.3.18.zip (1.0 MB)

Of course, eventually I would like to have this online when I figure out how. :sweat_smile:


Oh yeah, this is going to be super helpful. I’m no longer flying blind!! :heart_eyes:


Is it possible to somehow do something similar and dump the contents of the “app” LUA table? Or is it already in there and I missed it?


One sec. I changed my mind and I’m going to doxygen the entire application layer instead of doing it in pieces. I hope its not too overwhelming though. At least I’ve managed to leave the os layer out…


Here we go:

Doxygen of ER-301 Application Layer (App): er-301-app-doxygen-v0.3.18.zip

This contains the objects and graphics hierarchies, so this should be all you need to look at.

Take a look at app/lua/app.i for the full contents of the app table (notice it will also include objects.i and graphics.i). These *.i files are SWIG definition files. SWIG is the tool that I mentioned earlier that generates the wrappers so that these C++ classes and constants are accessible in Lua.


Hmm, app.i does not contain quite was I was looking for. I was looking for choice type definitions, e.g.


I can see references if I full text search the directory structure but I’m not quite sure to navigate to those pages via the HTML files. Thanks for the Doxygen files - these are going to be really useful in understanding what can be done in the middle layer and how to interact with the DSP objects through LUA.

Also, we posted above at about the exact same time. You may just not have an answer ready which is fine, but wanted to make sure it didn’t get missed in the cross-post. :slight_smile:


Navigate to the Choice class. You will find all of its derived classes listed conveniently there.


Hey Brian - I’m looking for a little more information about the controls being set up in onLoadViews. Looking through the documentation you posted above, I can’t seem to correlate anything to the properties defined in these wrappers. Rather those docs seem to correlate to the DSP objects. For example, from Countdown.lua.

function Countdown:onLoadViews(objects,controls)
  controls.input = InputComparator {
    button = "input",
    description = "Unit Input",
    unit = self,
    edge = objects.input,

  -- A GainBias control wraps any object with a Bias and Gain parameter.
  controls.count = GainBias {
    button = "count",
    description = "Count",
    branch = self:getBranch("Start"),
    gainbias = objects.start,
    range = objects.start,
    biasMap = Encoder.getMap("int[1,256]"),
    biasUnits = app.unitInteger,

  -- A Comparator control wraps a comparator object (passed into the edge parameter).
  controls.reset = Comparator {
    button = "reset",
    description = "Reset Counter",
    branch = self:getBranch("Reset"),
    edge = objects.reset,
    param = objects.counter:getParameter("Value"),
    readoutUnits = app.unitInteger

Each one seems to contain a button, description, and could contain a branch if it was defined in onLoadGraph. But from there on, the attributes for each seem to vary depending on the Control. If I look up Comparator in the documentation you posted above, it does not seem to contain an attribute called edge or readoutUnits.

Are these defined somewhere in the docs you’ve already provided? Or can you elaborate a bit more? :slight_smile:


Ah yes. I’ll give you some info on those tomorrow but really quickly (because I’m tapping this on my phone) let me point out that Comparator is not a global. Also we are not referencing something like app.Comparator. Therefore it must be defined somewhere in the same file. Look at the top of the file and you will find a bunch of calls to require() whose return values are assigned to local variables.

-- A graphical control for comparator objects
local Comparator = require "Unit.ViewControl.Comparator"

So you can see that this Comparator is actually a Unit.ViewControl.Comparator which is a class defined on the Lua side. This is also why you cannot find it in the C++ hierarchy. The UI event framework is all implemented in Lua.


One more useful point is that I always list the globals used in a file at the top of the file. This helps the linter find errors as well as document dependencies.


Oh, I see now. I thought those were comments to help humans and wondered why they were a little inconsistent. They are linter hints. :slight_smile:


This is all great stuff - following with great interest! :heart_eyes:

Just out of interest, I would like to know how many folk out there are interested in developing at this level using this technology.

Super simple poll: Simply like this post if, and only if, you are interested and plan to at least try :slight_smile:


Is there any possibility of a host-side Lua interpreter to catch syntax errors and the like? It would be nice to verify that a script is valid before transferring it to the 301.


A Lua linter will cover the generic stuff. Those are readily available. The luxurious option is of course a full desktop emulation of the ER-301. Which I’m sure you already know is definitely possible but requires dev time. I’m seriously considering it though, to the point where I’ve done a little research into cross-platform application frameworks like Electron. There is also the possibility of using the USB device port on the ER-301 as a kind of debugging interface but at first glance this seems like the more complicated option to build. Still need to think about that one.


I think something that verifies that the topology of the unit is valid would be very handy. Something that instantiates the nodes and makes sure that there are no invalid connections. Seem practical?


Definitely practical. Seems to me that would be just as much work as a headless non-realtime emulation of the ER-301.

That could be just as “simple” as linking the application layer behind a command-line interface…:thinking:


Well, I mean just dummy nodes… No DSP code or anything. Just static analysis of the graph.

EDIT: Hmm, I think “semantic analysis” is the term I was looking for.


I can see some big advantages of an emulator, or even a topology checker as miminashi suggests. Would enable development while not sitting next to the 301. Not to mention an ER-301 in a permanent home - the USB is not so readily accessible.