This is an old revision of the document!
Table of Contents
February 2024 newsletter
What we've been up to
Demos
- Vedran Budimcic made a train set demo at home:
- Vedran is also starting work on a Scratch-like environment:
- Forrest O. has a nice reel on Instagram emphasizing “craft computing” and the hand-made element of interacting with Folk, he makes these individual hexagon tiles
- The video is also nice because it's end-to-end, shows a lot of little process details of working with Folk, even showing the initial calibration of the table
- Integration with Cuttle:

- Andrés magazine article highlight
(Omar: Both Forrest and Vedran's demos [and the receipt printer work from last year] indicate the potential importance of custom regions and accurate calibration, instead of the hard-coded 'half-size page' that we currently have. Ideally, it would be easy to make the program region follow the outline of the hex tile or the train or whatever else.)
(I always like when there are specific physical objects, like Folk being overlaid on a book, or a toy train track, etc, instead of a featureless table. The train track in particular has a nice inherently three-dimensional character, it's not like your hand just lifting planar stuff above the table for a second. This all also motivates some of the RFID / alternative tracking, seeing how much the tags stick out visually and how much space they occupy.)
Template matching
Parallel evaluator
Omar: I've had some downtime this month, so I've mostly been continuing to work on the parallel evaluator (see also last month).
I've been saying that the pattern is that every 5 months or so, Folk starts feeling too slow, so I rewrite the Folk runtime; then it's way faster, so we pile more stuff onto it over the following 5 months, making Folk slow again, which leads me to rewrite the runtime again. (These runtime rewrites are usually surprisingly backwards-compatible and keep all the language and user programs and hardware interface intact.) This has happened like 3 or 4 times by now, including changes like:
- converted more and more Tcl code to C code (which is what makes the parallelization reasonable, the evaluator is almost all C already now)
- introduced various data structures – trie, priority queue
- removed bottlenecks/blocking and introduced limited parallelism (moved blocking operations onto dedicated processes, used shared memory instead of channels and event loop)
- graphics optimization (better framebuffer functions and then finally Vulkan)
- reordered operations to reduce wasted work (don't fully retract a statement until the new replacement statement is in place, so that any retained consequences of the old statement stay alive under the new one; don't re-Collect until as late as possible)
We have reached this point again; I'm regularly frustrated with how slow things feel on folk0 when more than 1-2 things are on the table, even though low-load performance is still pretty good. (I think a lot of people's home systems don't suffer from this as much because they don't have random stuff out, they're working on one thing at a time, and they're mostly using it on their own, not showing it off.)
In the new evaluator, I've been introducing a lot of the breaking changes that we've wanted to introduce for a while. These are only in the separate new repo right now, but we fully expect them to come into mainline Folk once the new evaluator is ready:
- In general, non-reactive / sampling / imperative language constructs (not Wish/When/Claim) now have a
!at the end:Assertis nowAssert!Retractis nowRetract!Commitis nowHold!Statements::findMatchesis nowQuery!(this is used on stuff like the web server to snapshot query the database as it is right now, without introducing any new reactive dep)
- C compiler objects are now implemented as standard Jim objects instead of with weird namespace hacks, so
[c create]is now[C]or[C new]- also feels correct because stateful objects should probably be made with
newinstead ofcreatewhich I think is more for immutable objects like dicts and lists
$cc compilenow binds C functions as methods on the$ccobject instead of making them global Tcl functions- (part of removing as much global state as we can, since we can't guarantee that code will run on the same Tcl interpreter. at least you can conceivably pass
$ccaround explicitly and then do the ferrying through statements)
- you can no longer rely on
procs from earlier in a program being available inside Whens (since procs are only state in the thread-local Tcl interpreter); for now, the pattern is to make a 'lambda' in a variable in lexical scope, which gets inherited by Whens- like
loopRegionhere which is passed through lexical closure: - ugly/tedious but should suffice to port/test most things for now, we can think of better ways to do this later
Example of how you'll be able to write programs/Whens that run concurrently, with arbitrary blocking / loops:
This is useful for talking to webcams: you can have a virtual program that is a simple infinite loop, where the body blocks on the webcam read from Linux, then Hold!s a statement with the resulting camera frame. Or for making HTTP requests: you can write a program that literally does exec curl and then uses the result without halting the rest of Folk.
Ported the web server, which (elegantly) can now just be a normal virtual program, since its blocking on clients/sockets is perfectly OK in the new evaluator.
Ported most virtual programs (camera, AprilTag, GPU/display). Also elegant: finally trashing the pi/ directory and inlining everything (talking to GPU, cameras, other libraries) into the virtual programs. (We want to do this partly to make everything live-editable inside the system; it should help with readability/understandability too.)
Even mostly works on my laptop (because we're not reliant on fork which completely breaks GPU access on macOS):
The key issue with the parallel evaluator right now is the locking, which is increasingly messy. (the naive one-big-lock implementation from last month ended up not working at all, deadlocks everywhere). So I've been trying to figure out what data structures and invariants we actually need…
Did a pass of looking at the data structures (Statement and Match) and ripping out stuff, especially reverse (child→parent) pointers.
(I think we can get rid of a lot of reverse pointers by 1. using a flat reference count instead of list of reverse pointers [flat reference count is also just a lot cleaner to deal with in C as a value, you can make it atomic] and 2. leaning on weak refs more and just letting the forward pointers get invalidated and leaving them dangling instead of needing to use reverse pointers to walk back and clean them up)
RFID
Omar: RFID work continues, on and off – we left off in January just about being able to do multiple hops on IB and wanting to continue on to OOB and live reporting and localization.
Unfortunately, this month I found that IB is still too unreliable (it breaks down after the first round for some reason). so it can continue for multiple hops, but not _that_ many hops, which means it's not feasible yet to leave it on and sync the OOB to it and do the whole live localization process. See how it breaks after 1-2 rounds (“THE TOP”) in these examples:
Anyway, in February:
- Started bringing back the live imgui GUI, at least for the IB part that currently works (the Python after-the-fact GUI was always a stopgap)
- (It still just reads the dump file, but it's a start. At least it's more customizable and interactive. Some work just to port over x-axis annotations and stuff like that to display bit boundaries and decode results.)
- Started on new IB↔PC↔OOB communications scheme (now that decoding happens on the radio, we don't want or need to stream all samples from the radios to the PC – I don't think we can spare the time on the radios anyway – we just need to stream timing and bit boundary information)
- Working out error states so that if something goes wrong during decoding, we can revert to a state where we can recover and continue normal IB functions once we see a sync pulse (within a few hundreds of microseconds). You don't ever want the system to end up in a terminal state, you want it to be able to run forever
- Now trying to speed up the IB decoder even more to give us more headroom. Simpler pulse detector that uses a window instead of needing to scan 2*buf, removing heap allocations on the decode path, stuff like that
- (Sometimes I wonder if I'd be better served writing Verilog instead…)
Friends and outreach
- We had our monthly open house on Feb 22. People were really into the editor this time, which was great to see – it's nice when people get to stick around for a few hours and make things, not just get walked through demos:
- Vedran and Forrest set up their systems this month – Forrest had a Discord thread where he ran into an issue with glslc not working out of the box, had to fix that
- Rob Ochshorn and Cristóbal Sciutto came by Hex House and we attempted to fix wobble/jitter in folk0. We concluded that a lot of it is actually physical jitter where the webcam is vibrating, not frame-to-frame variation in the tag detector…
- (You can literally put your finger against the webcam and feel it vibrate with the heater and other stuff in the warehouse.)
- We even tried hanging the webcam by its cable, just for fun:
Other work
- Got folk0's printer on USB instead of Wi-Fi after it completely failed during open house
- (It's been an irritant for a long time, it failing to get on the network or getting on the wrong one or ending up in weird dead-end states)
- Andrés fixed editor bug TODO
What we'll be up to in March
- Our next Folk open house will be on the evening of Thursday, March 21, at our studio in East Williamsburg, Brooklyn.
- New collaboration (to be announced) on deeper phone/laptop integration and knowledge management
- (Omar: I did some prototyping last weekend on localizing a phone using its camera + a tag on a laptop screen. I feel like you could do clever stuff with phone sensors and dead reckoning and smoothing to make this a nice experience even if tag tracking cuts out. Ideally you could just use a valid QR code, not even a specialized fiducial. Also thinking about Joy-Cons and Wii Remotes and how they do mouse-like pointing.)
- Polishing Folk/CNC interface for use by other people at Hex House and in general
- USB stick install / Linux distro (can we make it a turnkey install if you have a CNC machine and want a Folk UI for it?)
- System reliability (can we feel sure that people can walk up to it and use it?)
- Finishing up the 3D/high-accuracy calibration work from late last year to actually do the machine preview in Folk
- Going to the hardware store to do some jitter reduction
- RFID: Continuing to try to debug why we lose contact after 1-2 rounds of IB communication, work on the imgui GUI, hopefully start on OOB
- Parallel evaluator: continuing to work on locking and scheduling, hopefully do a table test after that to see how it performs























