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

Developing for the ER-301

There are a few other threads about this but since v0.6 is out now and there is a need to make a clear break, I think it would be benefecial to start this official thread on all matters pertaining to user’s developing their own software (mods really) for the ER-301.

I’ll be adding more information here and I’m happy to help people bring their pre-v0.6 libraries over to the new system.

Documentation targeting developers will grow and be collected here:

I need a few days to regenerate but feel free to start firing away with the questions.


Maybe we could get a community-built Docker image assembled which includes the build environment, emulator, and alsa for audio? Docker was a HUGE help when I got into Teletype firmware coding. In fact, I probably wouldn’t have ever started without it.


agreed that would be huge!

1 Like

An interesting way to go here could be how the Mutable Instruments dev environment works. They have a vagrant file, which essentially contains all instructions to create the VM in an automated way. All required tools and libraries get installed automatically. I find this a handy way to make sure everyone has the same version of everything and nobody needs to go through any complex installation procedures.

Have a look here: https://github.com/pichenettes/mutable-dev-environment

1 Like

14 posts were merged into an existing topic: ER-301 Emulator for Linux

@tomf and @Joe, I hope you don’t mind but I moved the emulator-specific posts to the emulator thread. :bowing_man:


In the package manager, where is the version number coming from?

core and teletype are showing as 0.6.00 but I don’t find this in their corresponding toc.lua. Mine shows 0.0.00.

It comes from the package filename. The goal is to have only one place where it is set. The relevant code is here.

-- Package version is parsed from the id: <name>-<major>.<minor>.<build>
function Package:getVersion()
  local id = self.id
  return id:match("-(%d+[.]%d+[.]%d+)") or id:match("-(%d+[.]%d+)") or
             id:match("-(%d+)") or "0.0.0"
1 Like

So, am I accessing the rear SD card correctly?

Previous code:

local libraryName = self.loadInfo.libraryName
local sampleFilename = Path.join("1:/ER-301/libs",libraryName,"assets/xoxo.wav")

New code:

local libraryName = self.loadInfo.libraryName
local sampleFilename = Path.join("2:/v0.6/libs",libraryName,"assets/xoxo.wav")

Path is coming out as below, and the file is there as far as I can tell.

But it can’t seem to load the file.

Try to avoid hard-coding drive letters and root paths. Otherwise the same code will not work on the emulator and the hardware.

Method #1

FileSystem = require "Card.FileSystem"
local libraryName = self.loadInfo.libraryName
local sampleFilename = Path.join(FileSystem.getRoot("libs"),libraryName,"assets/xoxo.wav")

Method #2 (recommended but v0.6.02+ only)

local Accents = require "Accents"
local sampleFilename = Path.join(Accents:getInstallationPath(),"assets/xoxo.wav")

Method #2 is less likely to break whereas Method #1 depends on the string “libs” and the contents of self.loadInfo.libraryName which comes from a preset file. The code to support Method #2 is already committed to the repo if you want to go that route now.

1 Like

Thanks, I’ll try Method #2 then. That looks even better, because I was thinking the code I had above would break in 0.7 even if it worked on both the emulator and the hardware today!

Working on getting a docker image together for building against am335x on OSX. So far got the basic Dockerfile. Gonna work on how to actually use this to compile code, but so far so good!


With the Accents remediation done, I’d like to dip my toe into the new lower layer development. I’m feeling a bit lost as to where to even begin to get something very simple working. So let me start with some very basic questions. Please pardon my ignorance - in addition to lacking some ER-301 specific knowledge, my experience with C++ is pretty ancient too.

Should I be creating my code files inside of the er-301 repo somewhere? Or in my own repo and just somehow include a path to the er-301 code? I assume I will have dependencies on the existing code, and will need to include some references to classes such as unit. I don’t think I’d be creating anything at the moment that I’d want to make a pull request and commit into the firmware, but rather the target would be a *.so file that lives inside a packaged mod. A binary that can be included in lua and used with the Unit.addObject method to create a new unit.

I’m assuming the bare minimum project would be a header (*.h) file and a c++ (.CPP) file. I’m thinking it would have 1 mOutlet (definitely), and possibly an mInlet (for a processor), and likely an mParameter or two. It would contain at least a process() function, which somehow gets called by upstream “stuff” once per period which is determined by the sample rate?

What other requirements am I missing for a minimalistic project?
What is flawed in my understanding so far?


Before I answer your questions, allow me to create a small example project that lives outside of the er-301 source tree and when compiled results in an installable package containing a new Unit (coded in lua) which uses a new Object (coded in C++) in it’s DSP graph.

I’ll have it ready in a day or two. In the meantime, I would recommend picking your favorite unit from the core package and drilling down into its implementation as far as you can (using F12 to jump to the definition of a symbol in vscode for example).


Sounds great - I think that would be super helpful!

1 Like

This would be really great! I was attempting to do this with the Teletype mod by stripping everything I thought was unnecessary out of it

1 Like

I’m interested in working on this next as well, in particular cross compiling for am335x on a docker machine.

In the er-301 repo, scripts/mod-builder.mk shows generally how to create the libcore.so artifact. I think projects will need to define their own scripts though and reference the 301 headers when building.


If anyone wants for inspiration/ideas on lower layer-touching projects:

  1. ER-301 as a I2C follower:
  • Addition of a I2C response framework (if not existing)
  • I2C command contains channel, response from ER-301 is voltage sampled from “I2C sample” unit.
  • “I2C sample” unit has a chain input for channel, but is totally transparent to signal.
  1. ER-301 as an I2C leader:
  • Addition of a I2C leader framework (if not existing) with GUI enhancements for enabling.
  • Unit(s) for selecting target module address, command, (optional) outgoing data, and (optional) expected return message length.

Dunno if this sounds fun to anybody, but it might relieve a lot of pressure from the “CV EXPANDER WHEN??” crowd. TXo and Ansible are perfect candidates for CV expanders. I could help on Teletype code for the follower enhancements!


Is the ER-301 hardware capable of I2S? That could open some interesting doors.

I don’t know; are you envisioning more audio output channels?

I find it kinda difficult to get excited about hypothetical new hardware when we have perfectly good existing hardware just waiting to be introduced!