Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable Firmware #19

Closed
jeffeb3 opened this issue Nov 5, 2020 · 2 comments
Closed

Configurable Firmware #19

jeffeb3 opened this issue Nov 5, 2020 · 2 comments

Comments

@jeffeb3
Copy link

jeffeb3 commented Nov 5, 2020

Background

I think this project is great. It looks like a lot of fun, and I will end up with a pretty useful
device.

I use Linux and I have some experience with 3D printing and embedded software. I have extensive
experience in C++ and I've contributed to some projects like Marlin Firmware.

I see there is a vanilla firmware for 5 sliders and that seems very extensible. But I suspect a lot
of people would like to stretch the capability of the arduino pro micro without writing any software.

What I'd propose we do is to write a firmware that can have it's inputs and outputs generally
configurable over the serial port. This would make the firmware 20x more complicated, but we would
have confidence the code would be error free (ish) and users could add an LED, a knob, or a button
without editing the arduino C code.

Detailed Example

There are similar systems that I am taking inspiration from. The blink firmware, for example. Or the
klipper 3D printing firmware.

The idea is that we write firmware for a specific arduino, like the arduino pro micro. In that firmware,
we enable features like toggling an LED, reading a button, a knob or an encoder.

Then when the firmware connects to the golang process via serial, it is given configuration settings
for which components to enable and which pins they should be enabled on.

For example, the first serial messages to the arduino might look like this:

config_add_digital_output pin=10 id=0 inverted=true
config_add_analog_input pin=A4 id=1 inverted=false
config_add_digital_input pin=9 id=2
config_send period=30

Then there might be a message like this to the firmware:

set_binary_output id=0 state=1

And the periodic status from the firmware might look like this:

1:185|2:8,8

Which would mean the id=1 had an analog value of 185, and the digital input has read 8 presses and 8
releases.

I think the firmware would be pretty easy to build for something like this. The devil is in the
details. Can we easily configure a port from a String? How do we handle mistakes, like having two
things with the same id? What happens when a message is lost?

The golang part (which I know very little about) would then need to be able to have that
communication channel handle these flexible message lengths and be able to configure the firmware to
handle whatever the user wanted.

Once we have the basics done, we can more easily add in features like having a button responsible
for muting a mic, or having an LED respond to the muted state of the mic.

In the config file, I could imagine something like this:

volume:
 - pin: A4
   signal: master
 - pin: A1
   signal:
    - rocketleague.exe
    - pathofexile_x64.exe
   inverted: true
   noise_reduction: high
 - encoder: [D4, D5]
   signal:
   - spotify.exe
   resolution: 4

status:
 - pin: D6
   signal: mic.mute
 - pin: D7
   signal: master.mute

mute:
 - pin: D9
   signal: master
 - pin: D10
   signal: mic

connection:
  port: COM4
  baud_rate: 9600

Other benefits

This would mean that the firmware would stay relatively close to the same in most builds. The
advantages of that are:

  • A lot of people using the same software build would make it more robust.
  • Effort spent on improving the firmware would be useful to more people.
  • A lot more flexability without needing to spend much time in the firmware.
  • Some enterprising individual could sell the pro micros with the firmware already flashed. That would
    help a lot of people get started who are intimidated by the firmware. I wouldn't do that (I am too busy anyway).
  • You could add even more complicated firmware features, such as keyboard emulation, encoder knobs,
    or displays. Even input or output matrices, such as the ones used in LED cubes or olkb keyboards would be possible.
  • After defining a generic serial port interface, new boards would be able to be built with new
    firmware and concrete requirements.

How do we get there?

I think this is a lot of stuff to add. I personally am most interested in defining the serial
communications and writing the firmware for the arduino. But it won't work without the golang serial
support. And there won't be much benefit until there are new features added to the golang software
for these extra types of controls.

@omriharel
Copy link
Owner

Hi there @jeffeb3, thank you for your incredibly detailed write-up! I'm happy to hear you like deej.

I share a lot of the same sentiments with regard to users being able to extend the project and take full advantage of the hardware they're building with, however I do think that the way there needs to look differently. There are several main reasons in play here:

  • Simplicity above all else: one core reason that the project got to where it is, IMO, is how simple it is to assemble and configure it (even if you're a complete Arduino or electronics beginner - just like I was when I started it). It is crucial to maintain that. I would say a good rule of thumb is: "does the user's config file require any knowledge about pin numbers?" - if the answer is "yes", it's too complex to put in the hands of users who e.g. receive deej as a nicely wrapped gift.
  • Customizability should be trivial when possible. If users need to learn the intricacies of the serial protocol to take advantage of custom features (even if they're exposed via config - which is also somewhat tricky to teach users, even if it's simple), it has the risk of feeling like a step backwards from simply adding a few lines to your Arduino code to e.g. achieve a mute toggle or color an LED ring.
  • Similarly to the config, the serial protocol shouldn't be aware of pin numbers. Communication between the client and the firmware should happen with application-level semantics: "Slider 3 reads 765", "Button 1 has been pushed", "Display X should display icon Y". This is valuable for easier troubleshooting, but of course requires the firmware to be aware of these application-level concepts.

I do have a distant future plan for supporting a similar kind of extensibility in a different manner. My plan is to take advantage of code generation to build a custom firmware for the user's desired set of hardware features as selected during set-up. For example, the user would indicate that they have 5 sliders, 4 buttons and an LED ring. deej's setup would then generate a flashable firmware that supports these specific features, with pin numbers either being set manually by the user or suggested by deej, also depending on the user's choice.

This is still very far down the list of things I'm planning to add. With that being said, I have a shorter-term plan to add infrastructure-level support for handling button presses over deej's serial protocol. This would allow users to easily bind buttons to several different triggers from deej's config file. These will include triggering a keyboard shortcut, running an executable, software-muting a slider, etc. Further down the line, this can be expanded to allow advanced triggers such as making an HTTP request or even running custom Go code (via Golang's plugin system).

Here's where I might (understandably) disappoint you: I'm extremely passionate about my vision for the project and its future, but it is something I do in my free time and ultimately I would prefer to work on all of these major things by myself. I appreciate that you've put a lot of thought into your proposal, and I strongly encourage you to explore it in a fork if you're excited to do so.

I'd like to take this opportunity to sincerely apologize if this response at all strikes you as dismissive, or otherwise leaves any sort of bad taste. It is definitely not my intention. In the coming weeks, I intend to add more details about the project's development and scope to a ROADMAP file. I hope this will help people who find themselves in a similar situation down the line to manage their expectations.

I look forward to hearing your thoughts about any of the things we touched on here, and please also feel free to reach out privately to me via the project's Discord server if you prefer that.

@jeffeb3
Copy link
Author

jeffeb3 commented Nov 6, 2020

* "does the user's config file require any knowledge about pin numbers?" - if the answer is "yes", it's too complex to put in the hands of users who e.g. receive deej as a nicely wrapped gift.

This is a really good point. I assumed the users are involved with the soldering of the project, and they would understand where the pins were on the board.

My first thought is that maybe the configuration could be layered into a hardware abstraction layer and an application layer. The hardware layer would set up slider3 and then the application layer would look a lot the same, with the config associating slider3 with the master volume.

I think we could also create good ways to handle hardware customizations we haven't thought of. By creating a well defined serial layer, which includes specific ls for custom components, makes it easier to edit, not harder. Inevitably, someone will make an led ring and someone else will have a wheel encoder and then a third person will want both. Keeping the pin assignments on the software/golang side just makes it much easier to change. But it could also be handled in the firmware. I cringe thinking that each user is making their own serial protocol and has to reinvent new customizations.

And I'm not offended at all. I really appreciate the honestly and if I sound ungrateful or critical, understand that I am just trying to express my point clearly and quickly. No worries.

@jeffeb3 jeffeb3 closed this as completed Nov 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants