Future development ideas for T-Deck


Anyone have some desired additions that they’re working on, or want accomplished for the T-Deck? Off the top of my head, here are some that I’ve been thinking about as extensions or lisp functions.

MP3 player: I got mp3 playing working on the bare bones hardware, but when I went to integrate it with uLisp, I ran into a mismatch between the Audio libraries used. This shouldn’t be too difficult to remedy.

More filesystem functionality: delete-file, move-file, make-directory, rename-file, etc. I assume this is just mapping out existing LittleFS functions to uLisp. On top of this a more or less stream reader would be nice.

Lora support: it would be nice to include a RadioLib library support for Lora messages. I’ve gotten this working on the base hardware, but haven’t bothered integrating it with uLisp. I’m currently working on C++ version of the Secure Scuttlebutt gossip protocol that works over lora, so eventually I’d like to be able to compose messages and send it out over a mesh network of lora devices.

NTP time, calendar and scheduling: with wifi support, and the time.h library one can call a NTP server and update the real time clock. It would be nice a persistent line on the screen that had the time, and some other OS level information. Maybe the ability to schedule function calls.

RTOS Tasks: It would be nice to be able to use both cores, and the task functionality of the underlying RTOS. Not sure how this is accomplished in CL. Interrupt handling would also be a nice to have to go with this.

Edit files, and text: The current editor is progressing greatly. It would be nice to add the ability to open up a file, move around through text and save your edits. I’m assuming a screen buffer with a cursor position would be in order to accomplish this.

Persistent database(s): integration with sqlite, or the the more lispy query language for use in storing calendar events, contact info, sensor data, or what have you.

Packages: I took a first stab at this, but I was unsure what functionality and conventions would be needed going forward. Are uLisp packages stored as .ul files, and therefore the function just needs the package name?

Macros, nlambda or fexpr’s: I’m unsure how much this is needed, but it seems like with backquote implemented, we are half way to nlambda, which is like function templates, which reduces macro expansion memory problems (I’m told :)).

Graphical Calc Mode: It would be nice if the repl didn’t alway overwrite any graphical images that you generate. Perhaps a mode can be entered where the a plot or other graphical data remains in one part of the display, and the bottom line is the repl input.

Others ideas??!


Thanks for these great suggestions!

As well as responses to these suggestions it would be interesting to know how many people are using uLisp on a T-Deck.


I’m thinking we need more OS primitives like multitasking/isolation, running multiple VMs, driver interfaces, window management, etc. You already listed filesystem functionality, that’s a good one. I don’t know much about how to implement these in lisp, or c for that matter, but I can sense myself running into the absence of these features at times when trying to make things that resemble applications. It’s also possible that these things would add unnecessary complexity and bloat to the project so we should be strategic about how we touch these concepts. Or if not then maybe some guidelines or standards for how to approach such interfaces so that they can interoperate


@johnsondavies I get what you’re saying about how many folks are actually using T-Decks, but I assume that most of the additions could be used on other esp32 devices (which there are many), if not other robust microcontrollers like the Teensy, and all of the RISC-V chips that are coming out recently. I’d much rather folks use uLisp than micropython. As long as they are minimal c functions written as extensions, with the rest written as uLisp libraries or packages then they should be easy to use on other platforms.

@hasn0life the esp32 already has an underlying FreeRTOS (real time operating system) that allows you to assign tasks to either of the two cores, queue messages between processes, share resources with semaphores or mutexes, do interrupt event handling, etc. In the least, it may be possible to pin the garbage handler, graphics and/or keyboard to core 0, where the wifi components are already pinned, and let the repl run on core 1. But it could also be cool to set up scheduled events, or allow some tasks to be non blocking.


I agree with thinking beyond the t-deck. I can see many of these developments being used a ulisp badge or some future lisp machine style computers. I’m personally focusing on the t deck cause it’s the most available device at the moment. I would have gladly used the adafruit featherwing keyboard if I could buy one.

In that sense I don’t want to rely on the esp32s rtos for functionality, I’d rather think of how to implement them in ulisp to potentially benefit other systems. Something like copy pasting or switching between two running programs wouldn’t really be served by the rtos either. I think lisp has ways of approaching these things from a high level but I don’t know what that would be. But feel free to correct me if that’s not the case.


Graphical Calc Mode: It would be nice if the repl didn’t alway overwrite any graphical images that you generate

I think a good solution to this would be a control character that switches the screen into a windowed mode where some of the lines scroll, such as the bottom three lines of the screen, and the rest of the display is static and can be used for graphics.

Selecting this mode would position the cursor at the start of the scrolling area.

How flexible should it be? Should the scrolling section be the bottom n lines of the screen, or any range of lines? Should graphics be windowed to the non-scrolling area? Should clear-screen reset to normal mode?


@hasn0life the RTOS that is used on the esp32, FreeRTOS, is sort of the industry standard for multi-core microcontrollers, especially in the open source arduino scene. I think there should be a lot of crossover uses with other processors.

Many Lisps do implement coprocesses, although that is less to do with multicore tasks, and more to do with continuation passing, or async tasks on one thread.

After thinking about it for awhile, I think the main addition would be to have an additional repl pinned to core0, that can be sent messages from the main repl (which is already pinned to core1 as it runs in the arduino loop. This would be accomplished by creating a RTOS Task and queue of char pointers, or perhaps a stream buffer would be more appropriate as they have variable lengths and would allow us to pass the strings of ulisp objects themselves. There may need to be a similar buffer for the return values. Essentially each core’s repl could have a stdin/standout that could be rerouted to different streams, even using different portions of the screen if a minimal window manager is created.

With that you could create a with-repl0 or with-core wrapper function that would send the containing object to the alternate repl/core. I’m not sure how garbage handling and what not would be effected by all of this. It’s possible that the garbage handler could be allocated to a task that is can be run on either core and could be handled by the scheduler.

@johnsondavies It seems like you could give ScrollDisplay a starting line number, as apposed to always using 0, so we could dynamically allocate the first two lines to the repl, the last two lines to the repl, or what not. Eventually you could do the same with columns, if you wanted to split the display vertically.


It seems like you could give ScrollDisplay a starting line number

@nanomonkey yes, that’s exactly how I was thinking of doing it. But rather than providing a new Lisp function to control it I thought it would be neater to do it with a printer control code.


But rather than providing a new Lisp function to control it I thought it would be neater to do it with a printer control code.

While I’m sure this has been done in other contexts, one model I’ve seen for it is in the Raspberry Pi bare metal framework Circle, here. IIRC, clearing the screen still clears everything, but in general I like the complement of escape codes provided by the screen library there.


I added support for network time protocol (NTP) client support, for use when the T-Deck has access to wifi, along with a local-time ulisp function that returns a list containing the (year, month, day, hour, minute, second) that was saved internally to the esp32’s real time clock.

I also added some file handling utilities for the sd-card reader, including make-dir (make a directory), delete-dir (remove a directory), move-file (for renaming and moving files), directoryp (returns true if the filename path given is a directory), and list-dir (like directory but you can give it a directory path and it gives you the contents). I will likely add file-size and something like tree for listing out the nested structure of files and directories, although you can do that pretty simply in uLisp using directoryp and list-dir recursively.

You can see the ulisp-extension.ino on the edits branch of my github repo.

So far I’ve been checking the battery with the following function
(defun bat nil (+ 0.2 (* (analogread 4) (/ 6.6 4095.0)))) which tracks pretty closely to what a multimeter reads, when not charging.

With the date, time and battery reading, I may have to dedicate the top row to a status bar of sorts using format?!

I think I may have a short somewhere on my board unfortunately, as I sometimes have to flex the board to get it to start, and the other day while charging over usb the back got incredibly hot and wouldn’t boot up. Since then I haven’t been leaving it plugged in, and the only part that gets warm to the touch is the TP4065B IC, the IR camera says it’s only about 40C. Weird.


Great work!

One comment:

list-dir (like directory but you can give it a directory path and it gives you the contents)

I think this would be better handled by an optional argument for directory, although perhaps that’s not possible in an Extension File.

I think I may have a short somewhere on my board unfortunately

My board has a problem too: if you wiggle the USB lead it resets uLisp. My conclusion is that the T-Deck is a bit too fragile to be used as a portable Lisp machine - perhaps mounting it in a case would solve this.


Yeah, the list-dir function is just a temporary modification of your directory function to test out the functionality. I also contemplated a second level argument where you could give the number of sub directories to recursively list, but I wasn’t sure what the best return for that would be, and wanted some feedback from you all. For example, should directories have a forward slash added to them? Would they be the first item in a nested list, or proceed them and be outside the list?

("lisp.txt" "packages/" ("string.ul" "ui.ul" "time.ul") "mp3s/" ("test.mp3"))


("lisp.txt" ("packages/" "string.ul" "ui.ul" "time.ul")  ("mp3s/" "test.mp3"))

or even association lists

("lisp.txt" ("packages" . ("string.ul" "ui.ul" "time.ul")) ("mp3s" . ("test.mp3")))

Also curious how closely people want to stick with Common Lisps conventions for filepaths and directories, ie using

(ensure-directories-exist "foo/bar/baz/")

instead of make-dir.

One could also create a *current-dir* variable and a change-dir function that allows you to walk through directories and list their contents over displaying the tree structure, or specifying the full path when doing file manipulation. Not sure what the convention is here.


The case does help with protecting the board. I ended up removing my roller ball, as the case I printed did not have a hole for it, and it may have been causing my earlier problem. I’ve noted that the ball was used as a boot button in the schematics. I’m not sure if holding it down was causing my previous problem…it also looked misaligned, perhaps it was also shorting.

Hopefully you can reflow the grounding pins that secure the usb port.

The case only allows for a very small lipo battery. I happened to have one lying around, but I’ve also found that folks discard disposable vape pens on the streets around here, and they all have small lipo batteries that can be repurposed. Just wear gloves, the nicotine substance probably isn’t the greatest and made my hands tingle when I broke a few open.