Using uLisp with the Keyboard FeatherWing


I’d like to draw your attention to a very similar device (currently not available anymore) called “Keyboard FeatherWing” (

Since I have one of those sitting around I wonder how difficult it might be to adapt the Lisp Lilygo firmware for it.
The device can hold MCUs like the Feather M0 oder M4 series etc. The keyboard is attached via I2C, but the screen uses SPI and the ILI 9341 driver. The resolution is the same as on the Lilypad, though.

I’d be willing to make necessary modifications of the firmware myself since I’m somewhat “fluent” in C, but I’d be grateful for some hints:

  1. Do you think it’s feasible for an ordinary mortal to make these modifications in a finite time frame?
  2. Could you provide me with some insight concerning the firmware parts that would need to be modified? Where should I start? I guess one would need to work with the M0/M4 version of uLisp, of course.

I’d be grateful for some thoughts on this idea.

(I’m new to uLisp and appreciate its existence very much! I actually had a Lisp course at university many years ago - and hated it because it seemed like endless counting of parentheses and not much else… clear misjudgement. But uLisp just brought me back to Lisp since it’s a real high level language that runs on ATMega MCUs as well. It’s quite irresistible. Thank you for providing us with this awesome software!)


Initial thoughts:

  • I’m familiar with the Keyboard FeatherWing, although I’ve never played with one. I assume the I2C keyboard interface is similar to the LilyGO T-Deck one, so you should be able to copy the keyboard code from the T-deck firmware.

  • The version of uLisp you start from depends on which Feather board you choose. An M4 one would be a good choice. In this case you should start from the ARM version of uLisp. This already has graphics display support, so you could probably drive the Keyboard FeatherWing display without much change to the code.

It sounds like you should be able to do the necessary changes yourself, but feel free to ask if you have problems.


Having done some of the initial port for the t-deck and knowing mostly C and never having touched ulisp before I’d say it was quite straightforward and took me probably less than 10 hours (tho @johnsondavies finished it in ways I couldn’t have). Just get the arm or t-deck port, make a list of drivers/features you’d want and do them one by one while checking the t-deck version for reference on design decisions.


Thanks for your suggestions and your encouragement! I’ll try my best and hopefully get back with some results.


Success! The Keyboard FeatherWing already is running as intended (REPL on on-board screen, typing/programming with thumb keyboard) - thanks to all your work already done before. So indeed it wasn’t really hard to modify the ARM version of uLisp appropriately. The existing keyboard firmware for KBFW delivers key events just as needed, so no hassle there. Currently, I even use a Feather M0 for this, since that was readily available right now. Still works perfect, just scrolling is a bit slow which I don’t mind.
Now I will add functionality for the other hardware features and adapt the .ino for other ARM feather types like M4, NRF and RP2040 one by one.
In what way do you want me to share the firmware once I feel it should be tidy enough for others to use?


In what way do you want me to share the firmware once I feel it should be tidy enough for others to use?

I suggest a GitHub repository, plus an announcement on this forum about its availability, if that’s convenient - thanks!


So here’s an initial working release on GitHub:

As reported these initial steps to make it work on Feather M0 and M4 Express were quite simple really. I haven’t added any additional functionality yet and I’m still struggling with the Git process a bit. Haven’t done this really often before, but I’ll probably get the hang again.
Next steps, I guess: I’ll make it work with Feather NRF52840 (by core modifications like the existing ones), test the SD card functionality, then try to add features using the extension mechanism.


I suggest changing the title of this topic to something like:

Using uLisp with the Keyboard FeatherWing


Using uLisp with the Keyboard FeatherWing and Feather M0 or M4 Express


Done. Also fixed function “testescape” to work correctly with KBFW locally (using a press of the built-in joystick). Had to revert to the slow test via I2C since it’s the only chance to query the joystick. Still I kept the faster version in comments for use with a button one may connect directly to the Feather board.


Works with Feather RP2040 now as well. But the communication with the screen seems unusually slow - it’s slower than on the Feather M0. This may be a consequence of some Pi Pico SPI specialties, at least that’s what some web sites suggest. They refer to an alternative SPI library which is said to be much faster on the Pico than Arduino’s “SPI” library:

Tried to figure out how to integrate that one into uLisp, but on the first few glances this doesn’t look trivial at all. Thanks for opinions on this!


Added default support for built-in NeoPixel, special keys now active (toggle backlight, ‘<’, ‘>’, clear screen).
Changed keyboard translations:
$ translates to =
[microphone] translates to ~
_ translates to \

(@ not translated)


Touch screen support added as well. Conclusion: The Keyboard FeatherWing with its built-in features is now fully supported when using the Feather M0 or Feather M4. Another self-contained Lisp machine.
Have fun!

Thanks to David and all contributors to the LilyGO T-Deck version as well as earlier KBFW contributors.


New year’s surprise: RFM69 support added. Not a big undertaking, really, but not so easy to test. Anyway - it’s working now, have fun!
Note a special “define” in ulisp-kbfw.ino:
#define autoforcetft
If this constant is not set (i.e. commented out), the automatic refresh of the KBFW’s screen is suppressed. When using other SPI components, the internal screen will look freezed afterwards then. You can reactivate it anytime calling the new command “(force-tft)” manually. Reason for this mechanism: The automatic TFT refresh after other SPI module calls causes a short flicker which may be unwelcome while running a real application on the KBFW. With the manual refresh you can control when this should happen.


Local REPL history added, see here:


Servo support added for arbitrary number of servos, using the Arduino standard Servo library. Currently tested on Feather M4 without KBFW only. Have fun! (You may switch on and off the capabilities of the extension file using the #defines in the main ulisp-kbfw.ino file.)


Although the Keyboard FeatherWing is no longer available, LILYGO have just released a keyboard that looks as if it might be usable in a similar way:

See: LILYGO T-Keyboard


Fixed small but important bug in relation to an external LispLibrary file.
Consider lines 7320ff:

if (ch == ';') {
  do { ch = gfun(); if (ch == ';' || ch == '(') setflag(NOECHO); }

Here, the NOECHO flag is set when the reader encounters a semicolon. This affects line 6973:

if (!tstflag(NOECHO)) Display( c ); // Don’t display on KBFW screen when paste in listing

This sensible line has one caveat: When an internal LispLibrary file enclosing the uLisp code with

const char LispLibrary[] PROGMEM = R"lisplibrary(

is used, the reader encounters the semicolon. The NOECHO flag is set when uLisp boots and gets never cleared, thus all output of the REPL/uLisp itself to the internal screen is suppressed (not affecting the input from the internal keyboard).
So I simply extended line 7775:

if (!tstflag(LIBRARYLOADED)) { setflag(LIBRARYLOADED); loadfromlibrary(NULL); clrflag(NOECHO); }

I describe this in detail here since IMHO this probably affects the LilyGO uLisp version in the same way, and I propose that should be fixed as well. (Can’t test it though, line numbers taken from ulisp-kbfw.)


@ginkgo Thank you for reporting this. This is fixed in Lisp Badge LE Release 2:

Lisp Badge LE on GitHub