Author Topic: Brainstorming: Functional Language for firmware instead of C?  (Read 2570 times)

0 Members and 1 Guest are viewing this topic.

Offline Tye

  • Thread Starter
  • Posts: 69
Brainstorming: Functional Language for firmware instead of C?
« on: Thu, 23 February 2017, 19:34:18 »
Rule #1: Be nice. No Functional Language flame wars. Right? RIGHT????
Rule #2: Be nice. I'm brainstorming here and haven't thought this out in great detail.

So, I've been playing with firmware lately as I DIY more and more "keyboard stuff." It seems like a Functional Language would actually fit keyboards really nicely and maybe(?) smooth out a lot of interrupt and timing issues that always seem to crop up.

Haskell and MicroScheme both compile to native binaries. I know it would be difficult to run this on AVR boards but it looks like there are tiny ARM systems now that could handle this. Similarly, Clojure and Scala would probably be out unless there is some micro-JVM. I know micro-JVMs exist but I wouldn't want to get TOO obscure.

Anyway, my thinking here regarding the functional system is that our keyboards are just big lists of events. So, the simplest event would be a "key_down, timestamp" event. Its mate would be a "key_up, timestamp" event.

Starting with that basic idea, would it be feasible to write a firmware whose main function was to process a running list of events? For example, we create an events list:
"key_down x, 10ms" The firmware looks at the list, and compares the time stamp to current time. If the timestamp is x greater than current time, and there's no "key_up x" event, then keep sending x's. If the "key_down" "key_up" difference is less than 5ms then call it a debounce and purge those items from the events list.

So, taking that further:
events_list = ["key_down shift, 10ms", "key_down x, 20ms", "key_up x, 30ms", "key_up shift, 40ms"]  <-- produce a capital 'x'

event_list = ["key_down b, 10ms", "key_down c, 20ms", "key_up b, 30ms", "key_up c, 40ms"]  <-- produce a rolling key combo of "bc"

The main point being that we keep and process the state of the keyboard as a continuous list that we evaluate to determine the current state of the board, and purge events from when a key is completed. We'd still have to be careful with timing issues and "interupt-ish" types of events but that would be invisible to the function that is processing the list and sending out keystrokes.

Additionally, we could test things easier(?) because we could simulate the event_list in a REPL if it's done correctly.

Anyway, like I said... Brainstorming. Plenty of holes, no doubt. Thoughts?

Offline TalkingTree

  • Posts: 2452
  • Location: Italy (142)
    • My projects
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #1 on: Fri, 24 February 2017, 03:43:50 »
I'm not coding expert at all, but I guess C is more popular also because of the small size outputs and ICs have a very limited memory for flashing.
My opensource projects: GH80-3000, TOAD, XMMX. Classified: stuff

Offline joey

  • Posts: 2296
  • Location: UK
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #2 on: Fri, 24 February 2017, 03:58:39 »
I am writing my firmware in Rust, but trying to use a functional style where I can.
It definitely helps with the testing aspect as you said, and I just prefer writing code like that as I think it helps keep code clean.

Offline vvp

  • Posts: 886
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #3 on: Fri, 24 February 2017, 04:48:52 »
Tehre are at least two problems with that:
  • As far as I know no functional language compiles to a bare hardware without operating system. The only option is that you would put some small version of e.g. linux in your controller.
  • All functional languages use garbage collection which makes it very hard to reason about used memory or time constrains. And your MCU may have rather small memory. And the keyboard firmware will have some RT constrains too.
But you can use a functional language to generate a C code which will be compiled for your MCU. E.g. Haskell supports at least two EDSL for this: Ivory and Atom. You may want to check this thread for some more information: https://deskthority.net/workshop-f7/ivory-cadet-haskell-meets-lisp-t15635.html

Offline algernon

  • Posts: 311
  • A tiny mouse, a hacker.
    • Diaries of a Madman
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #4 on: Fri, 24 February 2017, 05:37:03 »
While I love functional languages, they may not be the best choice for keyboard firmware. I have little experience with ARM, but for AVR, you want to cut corners everywhere, and stay close to the metal - so to say. Why? Because there's a HUGE difference between a 3ms and a 10ms main loop. And when you want to cram a lot of neat stuff into the firmware (oneshots, layers, tap-dance, you name it), speed and efficient use of resources is paramount. With most functional languages, you sacrifice a lot of control for convenience. That's a reasonable compromise in most cases, but when you are trying to fit into <8ms main loops, without pauses, without bursts, then you will need all the control you can have. Or a stupidly overpowered MCU. You can use some functional patterns, and they may even turn out to be useful. But using too much would be detrimental to the practicality of the firmware.

Also, your proposed list contains too much state: the firmware would have to compare timestamps to figure out if a keycode needs to be added to the report. There's a much easier way: don't record keyup & keydown events. Record key states. If a key is pressed, add it to the report. All you need is the current state and the last, no need for the whole list thing with timestamp comparison. In Clojure, this would be: (map handle-key previous-states current-states), and what most firmware do, is actually quite similar. This is still functional, but you have less data, less state, and an easier time processing events.

Offline pr0ximity

  • Posts: 2705
  • Location: Maine
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #5 on: Fri, 24 February 2017, 05:48:37 »
I am writing my firmware in Rust, but trying to use a functional style where I can.
It definitely helps with the testing aspect as you said, and I just prefer writing code like that as I think it helps keep code clean.

Which firmware is that? I'd be interested in taking a look, Rust would be my choice as well.
| Flickr | KMAC 1.2 | Koala | GSKT-00-Z | GSKT-00-AEK | GON NerD60 | Jane V2 CE | Whale | J80S | Ibis | Pro2 | Pro1 | 356mini | 356CL DGE | G80-5000 HAMDE | IBM 1390120 | IBM F AT | IBM F122 | IBM 3101 | Zenith Z-150

Offline joey

  • Posts: 2296
  • Location: UK
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #6 on: Fri, 24 February 2017, 05:51:40 »
I am writing my firmware in Rust, but trying to use a functional style where I can.
It definitely helps with the testing aspect as you said, and I just prefer writing code like that as I think it helps keep code clean.

Which firmware is that? I'd be interested in taking a look, Rust would be my choice as well.
You can find it here: https://gitlab.com/jgouly/keyboard-app/commits/master
It's not very fully featured... at all. I've mostly been spending time getting the basics 'well-designed'. Plus I haven't touched it for a month, working on some PCB stuff before I get back to it.

Offline Findecanor

  • Posts: 5036
  • Location: Koriko
Re: Brainstorming: Functional Language for firmware instead of C?
« Reply #7 on: Fri, 24 February 2017, 06:45:18 »
Functional languages for embedded systems has been done before, but is relatively unusual.
A long time ago I attended a lecture for a specialized microcontroller and programming language for realtime embedded systems - the language inspired by Haskell. The designers tried to get funding for their idea, but they failed.
It was indeed based on data-timestamp pairs like in your suggestion. Expressions modified the data and modified the timestamp to introduce delays with guarantees on their upper bounds.
I don't think they used any GC - it was much too simplistic. There are realtime GC algorithms though... if you want to write your own language and runtime.

Look also at:
* Erlang - I think that it was developed to run on Ericsson's telephone switchboard.
* Atom - a domain-specific language in Haskell for embedded systems.

I have my own firmware for the AVR. RAM and program memory is very limited.
I write it in C. I think about how my code will translate into machine code. There is no library - it is against bare metal. There are no dynamic data structures and no dynamic memory allocation.
The main bulk of keyboard firmware is about all the features necessary for the USB function as the protocol is relatively complex, then it is about timing and about hardware.
Key press-timestamp pairs would be a contrived data model for keyboard firmware in my opinion. The path where your main data is a key press/release event is very short. There are no timestamps - you would want to process an event as fast as possible, build it into the next USB HID packet right away and flag it for transmission. There is no queueing and no list processing.
« Last Edit: Fri, 24 February 2017, 07:03:02 by Findecanor »