It has gotten a bit complicated in structure, in order to make things portable and keep the actual UI code relatively simple.
There are a few different layers or components…
- There’s the hardware-specific stuff, the hwdef-*.h files and the attiny abstraction header. This helps convert hardware-specific code into a more abstract API for portability.
- There’s the UI toolkit, called FSM or “spaghetti monster”. It’s sort of a cross between a GUI toolkit and an OS kernel. It talks to the hardware, handles hardware events, does task scheduling, and exports a much friendlier API for applications to use.
- There’s the application itself, Anduril. It’s written in the abstract UI language of FSM. It defines states (modes), event handlers, transitions between states, and an idle processing loop.
- … and there are config files for Anduril. These set different options for different build targets. Mostly the build targets are one per supported hardware device. The config files set things like the ramp shape, the thermal response details, the aux LED settings, which modes to include, and other app-specific options.
The main thing you probably need to edit to make UI changes is anduril.c
. And to better understand the FSM API it’s written in, there’s a thread about how FSM works.
Or… To add support for a new type of hardware, it may be as simple as adding an Anduril config file for a new build target. It may also require a new hwdef file to map the pins and such. And depending on how different the hardware is, it could also require changing FSM itself, which I wouldn’t generally recommend for anyone who hasn’t spent a lot of time with it. Normally, people just hire me to do that because it’s not a very straightforward task. It’s called a “spaghetti monster” because all the complicated “spaghetti code” is under the hood where UI developers don’t have to care about it.