Using I2C protocol to control ZRNA

Hello @nsm,

thank you for the extensive description of the I/O possibilities! One more question: could you shed some light on how to use the I2C interface to issue commands from another (embedded) microcontroller, maybe with a small example which I could try to replicate? As I am planning to use the ZRNA FPAA in a modular setup, I am thinking about controlling it from my Monome Teletype, which already supports remote control of a number of modules (https://monome.org/docs/modular/ii).

Best regards,
Tobias

@mcleinn Hey Tobias. I really appreciate that someone is working on an application of the FPAA tech at this level of sophistication! I think we’re only scratching the surface of where this technology can go. My main gig is actually in a related area working on some next generation programmable analog hardware. It’s in the very early stages and is mostly targeting higher volume commercial applications, but I think there is huge potential for audio applications in the future. Think analog modular on a chip. The current Zrna implementation is based on an older FPAA technology that has some frustrating limitations. It still has a lot of untapped potential though. What I want to do eventually is a revision of the FPAA hardware that has more processing headroom, probably four FPAA devices, and can be deployed as an expansion for Akso. I think the FPAA stuff does need some kind of visual patcher integration for mass adoption. It’s a little intimidating for non-programmers in its current form. As you get into the current implementation more, we should talk about areas that need improvement.

On I2C:

If you take a look at the Python client, there’s a basic implementation that uses the FT232H to talk I2C: https://github.com/zrna-research/zrna-api/blob/16a4fa981e5e21202a0ad78a9b18ffa298ef17d0/zrna/util.py#L32

B10 on the board is SCL and B9 is SDA.

I tested the I2C functionality originally with an Adafruit FT232 breakout. You should be able to replicate that functionality with existing client and then look at porting over to the Teletype.

It’s possible to use UART and SPI in a similar way.

Does the Zrna do I2C slave?

Yep. The same API protocol works over USB, I2C, SPI and UART.

Something I forgot to mention: you’ll need to generate an appropriate Protobuf binding for your host environment and then implement the request flow as shown in the Python client. I can’t remember how Teletype works. Is it Lua scriptable or something? Or do you work from C?

Aside: this is something Akso should be able to do. It is too USB-oriented in its current form.

I am aware of the protobuf binding. The Teletype is using a Forth-style interpreter written in C. Theoretically it should be possible to use an embedded protobuf library such as nanopb, but the developers are not really keen to integrate such a weighty solution into the firmware. They seem to prefer rather simple I2C commands (https://github.com/monome/teletype/blob/main/docs/ops/i2c.toml)

So I could either do a fork, or use the Teletype only for changing simple parameters of existing circuits (via some primitive protocol bridge, running either on the ZRNA board or some external MCU), while the FPAA is configured by some other embedded Python (or even UI-type) interface - like, https://micropython.org with an OLED. Is that what you mean by “something Akso should be able to do”?

nanopb is what the Zrna firmware runs internally (on an STM32F4 core). It looks like the Teletype runs an AVR device internally? Let me review how Teletype works and try to come up with a recommendation. We certainly could implement some simpler I2C command handling that doesn’t require protobuf. The Zrna API is fairly complex though; I’d need to give it some thought to figure out how much could be exposed without protobuf. That would be a useful feature to have for systems where protobuf is impractical.

I mean that in future Akso releases I’d like it to be fully configurable from these other interfaces rather than only from USB and an a host PC. That’s a bit of an architectural shift away from the current implementation.

Yes, it’s AVR, and platform-wise probably quite aged - on the other hand, there is an active community and ecosystem of devices around it, into which your devices would be integrated. The “generic I2C interface” I posted above is already in the latest firmware, so if one could implement a few simple command for setting or getting parameters of an existing configuration on the side of your devices, would already allow some level of control.

Earlier today, I tried to imagine how your quickstart might look like using the Teletype’s Forth and nanodb:

Z.CLEAR
Z.PAUSE
G Z.GAININV
Z.GAININV.GAIN G 100 
I Z.AUDIOIN
O Z.AUDIOOUT
Z.ADD I
Z.ADD O
Z.CONNECT I G  (as a shortcut for Z.OUT I Z.IN G) 
Z.CONNECT G O (as a shortcut for Z.OUT G Z.IN O) 
Z.RUN

It would probably help to allow shortcuts, especially for long named parameters.

For more complex programming, one could use a Micropython with a SSD1322-type 2.7" OLED connected (like in the Teletype), and some kind of keyboard. Devices like the pyBoard would be an easy way to start. Micropython does not run nanopb, as far as I see, but one might use or port the python bindings generated by nanopb - or use a micropython-based purely Python library such as https://github.com/dogtopus/minipb. The console can then be redirected to the OLED. However, such a system would not yet have a community or ecosystem, and maybe a bit limited (even though some of the pyboards come with several ADCs and DACs on board, so might be good companions)

As an alternative, one could include Micropython natively on your devices’ STM32s, at least optional? Then would only need to connect a dumb terminal to the STM32 IOs for quick control. I2C could be used to tunnel Micropython IO (REPL) to and from devices such as the Teletype, at least with a custom operation, which would sent its parameter over I2C after filling in variables. Like:

Z PAUSE()
Z G = GAIN_INV()
Z G.GAIN = {SOME_TELETYPE_VARIABLE}
Z IN = AUDIO_IN()
Z OUT = AUDIO_OUT()
Z ADD(IN)
Z ADD(AOUT)
Z IN.OUTPUT.CONNECT(G.INPUT)
Z G.OUTPUT.CONNECT(OUT.INPUT)
Z RUN()

Off the top of my head, I’m not sure if it’s theoretically possible to fit a Micropython interpreter side by side with the existing firmware. I’m a little bit reluctant to go there unless we absolutely have to. It feels a bit heavy to me.

I like the idea of doing something that is directly compatible with Teletype and the i2c ecosystem around it.

Is this relevant https://llllllll.co/t/a-users-guide-to-i2c/19219/3 ? Are we basically talking about making Zrna talk over ii ?

Are we basically talking about making Zrna talk over ii ?

Yes (as introduced on https://monome.org/docs/modular/ii), and there seem to be two ways to initiate this communication - one is as a Teletype module with its own OPs, requiring a firmware update (example: Grid, ER 301 etc.) or via the generic IIA / IIS / IIB commands introduced in the latest firmware (link in my second comment)