Paraprogramming Dispatches


About Time


Lisp
Eugene Zaikonnikov

This week I put together a small NTP client. To keep dependencies at minimum and to avoid forcing a permanently running process onto users, it does not attempt to adjust system RTC clock, compensate jitter or evaluate time server quality. As I see it, much of that behaviour is easy enough to add via mixins with the defined NTP class.

NTP timestamp is two 32-bit values: seconds and fraction of a second. NTP conveniently counts seconds from Jan 1 1900, just like universal time in Common Lisp. There is however no portable Common Lisp representation for fractions of a second. Thus the client sticks to using NTP formatted fraction for that. It is way more precision than any existing CL implementation has in INTERNAL-TIME-UNITS-PER-SECOND, but this makes the value comparable across implemenations. The new GET-ADJUSTED-UNIVERSAL-TIME method then returns a pair of values: universal time and NTP fraction. The fraction can be converted to the implementation’s internal time scale with FRACTION-TO-INTERNAL.

Internally we define no special arithmetic on NTP timestamps but provide two conversion macros for single integer space. BIG-TIME converts NTP stamp into a large integer. We then do all calculations in that domain, and convert back to NTP timestamp using SMALL-TIME when it’s time to send it over the wire. An NTP instance stores adjusted time as an offset from internal real time. The offset is roughly intialized with universal time and then adjusted after each server request.

Sifting through ImageNet dataset in Lisp


Lisp
Eugene Zaikonnikov

..there is no shortage of rainy evenings in the rain capital of the world, so I used a few of them to put together this small application that I called (perhaps overly ambitiously) cl-imagenet. It uses a bunch of Lisp libraries: opticl and cl-jpeg for image processing, cxml for extracting bounding boxes from the annotations, cl-fad for filesystem operations, and trivial-channels in combination with clx for streaming to display.

The code tries to detect how many cores the host machine has, then creates the corresponding number of worker units. The workset ImageNet subunits list is built up, which are then assigned to the workunits. Each workunit fetches annotation file, extracts the bounding boxes and image file reference, decodes the corresponding JPEG file, handles processing with OptiCL and sends the result via shared channel to display thread. It is impressive how compact the code can be when leveraging random bits of the ecosystem available through Quicklisp.

In this setup only the luminance component of JPEG is extracted and then thresholded from medium gray. The video is filmed on an old quad i5-2500. On my 8-core i7-6700 box with visualisation off, it averages some 200K processed images per hour.

Tested lightly with SBCL on Linux. One known problem place is the message channel gradually eating up memory with visualization on, but as it’s only used in tests it hasn’t been a pressing need to fix yet.

Symbolics-inspired WASD keyboard layout


Lisp
Eugene Zaikonnikov

I’m enjoying my customized mechanical WASD keyboard since last summer:

Symbolics tribute keyboard

Its signage and cap colors are inspired by early Lisp machine ‘space cadet’ keyboards. Not anywhere a close functonal match certainly but I do like the looks. And unlike the the original it comes in short, messy-desk-space-preserving 87-key version.

The inscriptions are changed to oldskool. Alt is META, AltGr is GREEK, caps is HYPER and left-Win is SUPER. SUPER is bound to X11 layout switch in my system, GREEK is just the normal European 2nd-level shift. HYPER is remapped to.. well actual Hyper. This adds a bunch of new keybinding space in Emacs:

(when (eq window-system 'x)
  (shell-command "xmodmap -e 'remove Mod4 = Hyper_L' -e 'add Mod3 = Hyper_L'")
  (shell-command "xmodmap -e 'clear Lock' -e 'keycode 66 = Hyper_L'"))

(global-set-key (kbd "H-k") 'kill-this-buffer)
(global-set-key (kbd "H-f") 'find-file)
(global-set-key (kbd "H-h") 'hyperspec-lookup)
(global-set-key (kbd "H-3") 'split-window-right)
(global-set-key (kbd "H-2") 'split-window-below)
(global-set-key (kbd "H-1") 'delete-other-windows)
(global-set-key (kbd "H-0") 'delete-window)
(global-set-key (kbd "H-s") 'save-buffer)
(global-set-key (kbd "H-a") 'mark-whole-buffer)
(global-set-key (kbd "H-r") 'raise-sexp)
(global-set-key (kbd "H-c") 'slime-selector)

Norwegian-based layout is available here.

MS1201.02 single-board PDP-11 clone


Hadrware Vintage PDP
Eugene Zaikonnikov

Among the first computer related-books I read was a PDP-11 programmer’s manual, borrowed in a library. It was a bit too dense for someone who never seen a computer in their life. Save for the random bits like bus arbitrage or advantages of magnetic domain memory over core, nothing stuck really. A bit later came my first real programming experience, a few simple BASIC programs on DVK, a DEC PDP-11 clone, under RT-11.

Then this winter, browsing eBay junkyards, I came across an MS-1201.02: a Q-Bus board at heart of DVK. A couple weeks later, it was on my desk:

MS1201.02

Looks like a finest specimen of Soviet electronic manufacture, but robbed of its KM type platinum/palladium capacitors by precious metal scavengers. It’s a wonder that the processor (16-bit K1801VM2) in gold-plated contact CERDIP package wasn’t removed. The CPU has a crack in the package however, which might prevent it’s function.

The board has three jumper blocks for configuration. Or at least it had in theory.. in reality, communist DIP jumpers were so bad the factories stopped installing them after a while. So if you wanted to change a serial port speed or boot address, you had to do it like Real Men do: with bare hands and soldering iron.

Jumper block

The board has 64Kb physical memory, only 56Kb (28 Kwords) of which are however addressable - the upper 8Kb are I/O mappings in PDP-11 architecture.

So as you see, some work to be done here. Immediate plan is:

  • Order all the missing caps and repopulate them
  • Find a replacement CPU chip and replace if necessary
  • Install less manly, capitalist DIP piano switch blocks
  • Build a backplane to install the card in
  • Build a current loop serial interface to RS-232c converter
  • As the board uses two “power good” signals in startup sequence, build a small flip circuit for start-up
  • Boot the board to the built in serial monitor prompt

Out of that, the caps, CPU and backplane components already ordered. Schematics are fortunately available on the net.

To be continued.

« Older Posts