Hi, just discovered uLisp last week and I am essentially obsessed. I had a bunch of old(ish) Adafruit boxes from their subscription service just languishing; I actually cancelled the subscription because they had gone from providing useful supplies to outfit a nascent electronics bench to these projects that were, essentially, “take the paper off the acrylic and screw the laser cut case onto the board with a couple of peripherals.” And then they ran CircuitPython. Okay, great, but that implementation is sad and I don’t like Python…
Adafruit has an example of “CircuitScheme” which they apparently decided in some sort of cruel joke to implement in CircuitPython. That’s just sad. Hey, wait, this mentions uLisp …
…and it doesn’t support the display. Well, crap, so much for that. Hey, wait, maybe it isn’t actually that hard to hack in support for the TFT. (It wasn’t; just needed to put some #ifdefs in the right spots and import the right library. Can even do it with the 8-bit bus on this board!)
…Okay, now I have it printing out stuff to the screen. What’s the filesystem story like? Oh god, really? This thing is going to save like 10KB to the same first four blocks of my 8MB flash?? That really won’t do. I remember LittleFS was a good choice here, oh it already kind of supports it, but it’s cordoned off into another set of #defines I really don’t want to hack around.
…Two days later I’ve got LittleFS hooked into the dataflash and now I feel like this thing might be something I’ll spend some time on. Note that at this point, I’ve written like four lines of Lisp into the thing, just tests of functionality; I’ve spent days just hacking stuff into the “kernel”, dealing with asserts in a filesystem without a debugger.
But I’m not done yet; the other major feature of this board that uLisp doesn’t support is the AirLift wifi coprocessor. I got halfway through reimplementing the first wifi method and discovered that the ESP version has wifi extensions (obvi) so it was much smoother to just copy/paste those in and tweak slightly.
…And then debug why the interpreter would hang (it was because I played fast and loose with the various builtin tables)
Finally, I stop to make a cool looking boot screen.
Lisp is much better than BASIC…
I grew up on C64s, I loved the ability to just edit anything live. I’m finally happy with this port. I actually got the same build running on a Trellis M4 I also had in one of those boxes, so now I have two Lisp machines…
I’m not done hacking the kernel yet though. I really think Lisp on these higher end machines (8MB of flash, 512KB of RAM … and some boards can use huge expansions of insane numbers of megabytes of ram…) could use more of an “operating system”.
For example, I got LFS working on the dataflash - but the only “file” support is in the SD card module. Really, what I want is a VFS where I mount the SD card on /sd
and /
is on the dataflash (the “hard drive”). And I want to run LittleFS on the SD card too, because I like data consistency. So I’m planning to flesh out the filesystem tools. I only implemented spit
and slurp
on my LFS interface right now, but that’s enough for…
I also want to build some robust code loading/unloading things. With a filesystem we have much better organization of files; with file streams we can just (with-lfs-open (s "repeat.lisp") (eval (read-from-stream s)))
and when we’re done with that code we can makundef
it away, freeing up the memory again.
With that we then pave the way to run lisp code files as “binaries” which would mean you’d read it in, execute something (not unlike the workspace images, but as text, not binary - although that too could be used for this)
and then once it had completed, remove it from memory, load your “main process” again and continue on.
I’ve seen complaints that the interpreter goes away when the system is doing something interesting. It should be possible to build something like Clojure’s async system, or maybe some other Lisp did it in a more appropriate way for uLisp. That’d also pave the way for utilizing multiple cores well.
I don’t think uLisp supports interrupts yet, but I have some ideas around being able to build an event pump that ISRs could just drop things on top of.
CircuitPython boards present USB mass storage that they save the raw Python files on. I am basically only targeting uCs that can run CircuitPython. I expect to be able to provide a similar interface for uLisp, hopefully presenting the LittleFS partition’s files.
In case you couldn’t tell by the length of this post I’m really excited for what I’ll be able to build with this software. Thanks so much for working hard on it and posting your work. I hope I can contribute some of this back into uLisp core and make this a good option for those CircuitPython boards suffering with such a poor language.