Two problems slowed down my efforts to build my own user interfaces on native Inferno. One was related to how native Inferno handles the keyboard differently to hosted Inferno. The other was connected to the use of the real time clock on the target device.
I implemented some shortcuts for the simple text editor widget that I was prototyping to make it easier to navigate the words in a line of text. Pressing Ctrl-Left or Ctrl-Right seeks to the next word boundary. This works fine in hosted Inferno, running in the Inferno emulator, but I found that the Ctrl-Left shortcut was only intermittently recognised.
It took me quite a while to figure out what was happening. I wrote a program to read the /dev/keyboard device and print the key codes of keys I pressed. Since I had updated the keyboard driver for the NanoNote to report values for the cursor keys, using the values in module/keyboard.m as a reference, I wondered if there was something I had done incorrectly. Things started to fall into place when I looked at the key codes that were reported when Ctrl was held down.
Pressing the left cursor key produces a code of 0xe014 (or 16re014 in Limbo), which is the expected value for the key. Up, down and right produce 0xe012, 0xe013 and 0xe015 respectively. Pressing the Ctrl-Left combination produces a code of 20, and the corresponding codes for up, down and right are 18, 19 and 21. Hosted Inferno is happy to report all these without problems and the text edit widget works as expected. On native Inferno, it would take several presses of Ctrl-Left before the key was reported, then all of them would be reported at once.
What made things clear was trying combinations like Ctrl-A, which produced a code of 1, and Ctrl with other letters. Working back from the value of 20 for Ctrl-Left, it became clear that this is equivalent to Ctrl-T. Realising that there are special shortcuts in native Inferno for debugging, I checked the cons man page, which says this:
For debugging, on native systems only, two control-T's followed by a letter generate console output: ^T^Tp prints data about kernel processes, ^T^Ts prints the kernel stack, ^T^Tx prints data about memory allocation.
Sure enough, pressing Ctrl-Left twice followed by one of these letters also had the same effect as using Ctrl-T. The next step was to stop it from doing that, which turned out to be less than obvious to the extent that, in the end, I patched the os/port/devcons.c file to disable processing of debug keys if the debug_keys variable in the os/nanonote/nanonote conf file is zero.
Using the real time clock (RTC) on the NanoNote is very simple because it is provided by the JZ4720 system on a chip (SoC). Once the RTC peripheral has been enabled by clearing the appropriate bit in the clock controller, you can simply read and write its value. As a result, the device driver is very simple to implement.
The RTC peripheral on the NanoNote provides a 32-bit counter that updates once per second. Inferno's /dev/time counts in microseconds, so some of the native ports perform a conversion from seconds to microseconds at boot time, and I tried to do the same in the os/init/nanonote.b script. Unfortunately, my implementation of the RTC device was returning a 12 character field for the number of seconds, yet my conversion function was only reading 10 of these. That should have been enough for the number itself, but the string was padded with spaces and it was reading two of those and missing the last two digits.
Fortunately, mistakes like that are easy to fix. Once the RTC had been set at the console, the system was able to pick up the time at boot, and now it should keep fairly accurate time.