Falling down rabbit holes

A project log for PotatoP

A LISP-programmable laptop with battery life measured in months

Andreas EriksenAndreas Eriksen 03/20/2022 at 22:070 Comments

To quickly sum up the progress I've made since last time - I can now type on the keyboard, and the words show up on the screen! Those letters in the picture are pretty chunky - but that is for your easy viewing pleasure. I can comfortably read with the default 5x7 font which lets me display 53x30 characters. Moving it closer and adding another one or two next to it should give me sufficient screen real estate.

I've measured current consumption from the battery at 6mA, or about 22 mW, while scanning the keyboard and constantly updating the screen. That should give me about 83 days of battery life (given constant use) with the laptop-size battery I've ordered.

It's certainly better than my standard laptop, but not quite as good as could be hoped for - it's 4x the quoted 5 mW power for the Artemis module. Disconnecting the screen or putting the CPU to sleep didn't seem to make much of a difference either, and that means I won't be able to recharge using only the solar panels, certainly not with indoor light at least.

I suspect most of the power draw is from other components on the board, like the voltage regulator, power LED and possibly more. I've cut the traces to the PDM microphone earlier, but I don't want to start desoldering the other components just yet.

The keyboard scanning rabbit hole

I was able to get the timer driven interrupt working, and posted a simple example in the Sparkfun forums in hope that it might help others. The rest was supposed to be simple! But when I coded up the keyboard scanning routine, using the standard Arduino pinMode and digitalWrite / digitalRead calls, it was slow ... unacceptably slow.

It took about two milliseconds to scan the whole keyboard matrix, which I had naively been hoping to do tens of thousands of times per seconds - but I could barely scan it 500 times per second, and even then the CPU would have been 100% busy scanning the keyboard and have no time left to do anything else.

I realized I would have to leave the easy and comfortable world of Arduino tutorials, and started digging into the guts below. Happily I discovered that all the source code for the underlying software is included in my ~/.arduino folder!

Turns out that Sparkfun's Arduino core for the Artemis boards is based on Mbed OS, and every call to pinMode or digitalWrite will spend some time looking up the right mbed::DigitalInOut object. Keeping references to and calling these directly saved about half of the time, getting it down to 1 ms per scan. Reducing the scan rate to 256 times per second seemed acceptable enough for now - that's 25% of the CPU, but I can fix it later.

Or so you'd think, but I just couldn't accept that. So I dug down through another layer ... the implementation of Mbed OS for the Apollo3 ends up calling functions from the Ambiq SDK. These have somewhat more arcane names, like am_hal_gpio_input_read, but have even less overhead - calling these directly got me down to about 240 microseconds per scan, or about 6.6% of the total CPU time.

There is yet another layer I could chip away at - there is a "fast GPIO" function, or I could even directly read and write from the I/O registers - but I spent a whole evening trying without much success, and 240 microseconds at 48Mhz is 11520 clock cycles, about ~103 clock cycles per key scanned, and I think I'll be able to live with that ... for now.

The hardware SPI rabbit hole

Once I had come to terms with the keyboard scanning, my next step was to display the results on the screen, and I promptly fell into another hole. Screen updates are just a little too slow with software-driven SPI for typing to be responsive. Using he same shortcuts as for the keyboard helps, but it's not great, and getting hardware SPI to work with the Adafruit library on the Sparkfun board is still giving me trouble.

After consulting the display data sheet and programming app note I was able to write data to the display using hardware SPI without using the Adafruit library, so now I know it can work on this chip! And if I really can't figure it out, I'll have the option of writing my own display routines.

It could be a lot faster as I could do partial refresh of only the lines that need to change. And I could even offload the data transfer to be done using the DMA functionality of the Apollo3 IO Modules ... yeah, this one goes pretty deep too, and I'm still in it. Hoping I can crawl my way out over the coming week.

Next steps

Once I get that part out of the way, I'll finally get to write some LISP code - a basic text editor with a keyboard shortcut to (eval '(my code)) so I can start programming on the device itself! Oh, and I'll need to design and 3d print a case to make it all tidy, compact and nice(r) looking.