Close

Working editor and data storage

A project log for PotatoP

A LISP-programmable laptop with battery life measured in years

andreas-eriksenAndreas Eriksen 02/05/2023 at 05:120 Comments

I'm happy to report that moving the keyboard scanning code into uLisp went well! Initially I got some corruption on the display, but this was later fixed by disabling the keyboard interrupt while updating the screen. I also slightly rewired the keyboard to free up another SPI interface. More on that later ...

A simple text editor and REPL

It didn't take me too long to write a basic text editor in uLisp - working name "Typo". For now, it's very naive code and starts working poorly after about a screenful of text, so some optimizations along the lines of emacs's "redisplay" will eventually be required. But I can type and edit interactively on the PotatoP, with support for such niceties as the backspace key to undo my mistakes and arrow keys to move around :-)

So based on that I now have a basic working REPL, and it is suddenly possible to do further development work on the editor/REPL from the PotatoP itself. In celebration, I've tweaked the prototype display protector and reprinted it in glorious yellow:

Demo of working REPL
Planned future work on this prototype includes replacing the damaged display, adding a second display for side-by-side coding and graphics, and removing cat hair from the keyboard

Error handling

At first though, usage was severely hampered by the lack of error checking. If there was any problem at all in the code I input, the REPL crashed and had to be restarted from the serial console. Fortunately I came across an uLisp forum post where Goheeca and mgr had extended an earlier version of uLisp with some basic error handling. This couldn't be directly applied to the current version, but with a few tweaks ... it works! I am immensely grateful. I also extended the "testescape" function to respond to keyboard input, so I can interrupt execution if the runtime of my code exceeds my patience.

Some types of malformed programs can still cause the interpreter to hang, the most likely of which is forgetting to close a double-quoted string or parenthesized expression, which causes the uLisp reader to go into an infinite loop. It will also hang if the code recurses too deeply and there is a stack overflow.

For the former issue, I've started writing a basic parser (in uLisp!) that will check the validity of my expressions before submitting them to the reader. I hope that this can also be used to give more helpful error messages, making it trivial to find my mistakes. For the latter, I've no plan yet ...

Storage options

In the mean time, the presence of these bugs makes it all the more obvious that there's no easy way yet to save my work. If I define a function in the editor, I have to connect the USB-C cable, exit the REPL by sending the escape char from the serial console, "(pprint <function name>)" to display it there, then copy-paste it and save it in a file on my PC. I could streamline this process, but my goal is a stand-alone computer - so I've begun looking into how to store lisp code and text files on the device itself.

I've still only used about 1/4 of the 1Mb of flash program memory on the Apollo3, and it would be possible to use the remaining space for storage. But although that would fit quite a bit of code/text, it could be vulnerable to being overwritten by later firmware updates, and I'd have to implement it myself and ensure proper wear leveling - and making a mistake in that could kill the flash chip quickly.

So instead I soldered some wires to a microSD adapter, uncommented a #define and tried out the SD card support already present in the interpreter - and it works out of the box. It's somewhat slow and doesn't support listing files, but that should be easy enough to add. It even supports "(save-image)" and "(load-image)" to save/restore the entire workspace, although personally I want to be able to work with files more explicitly.

As usual there's an issue to overcome - updates to the display stop working after I've used the SD card. Probably related to both using SPI in some incompatible way, which I'm looking into.

Another issue for this project is the power usage for generic microsd cards - the spec seems to require up to 300mA for the card, which is at least 50X more than the rest of the system, and ~4x what the power supply in the solar harvesting AEMLION board can provide. The random one I'm testing with seems to use a lot less, but as I don't really trust it I've ordered an Adafruit SPI Flash SD card for which the spec sheet indicates a max of 30mA (and 0.2mA with the clock stopped). This should be indistinguishable from a "real" SD card from the software. 512MB should be enough for nearly indefinite coding or writing, and as long as it's only being used for intermittently for saving/loading (say, reading or writing 5% of the time) it shouldn't affect the battery life of the system much...

My updated power estimate is then a measured ~2.5 mA (for the display and CPU when running lisp code and updating the display at 10 fps), 30mA * 5% duty cycle for the SD card gives 1.5mA for a total of 4mA, which in theory is 2500 hours or ~125 days of continuous active use with the 12000 mAh PiJuice battery. That's with no contribution from the solar panel(s) I'm planning to put on the lid, and idle power consumption is < 1mA, so it still seems quite excessive - it should hold through (several!) dark Norwegian winters just fine.

Now I just need to fix that SPI bug ...

Discussions