newsletters:2025-08
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| newsletters:2025-08 [2025/08/30 22:42] – [Anti-blinking: display list settling] osnr | newsletters:2025-08 [2025/09/01 01:46] (current) – [folk2 on the gadget] osnr | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== August 2025 newsletter | + | ====== August 2025 newsletter ====== |
| If you'd like to see the latest updates on Folk in person, **our next Folk open house is [[https:// | If you'd like to see the latest updates on Folk in person, **our next Folk open house is [[https:// | ||
| Line 26: | Line 26: | ||
| The idea here is that you have a LRU cache on each thread (Tcl interpreter) that maps string -> Jim object. | The idea here is that you have a LRU cache on each thread (Tcl interpreter) that maps string -> Jim object. | ||
| - | Then every time you take in a statement on that thread (when it runs a When block), you look up each term in the statement in the thread-local cache, so if you already have a shimmered Jim object that's a parsed list or code expression or something, you can reuse it and save yourself the effort of parsing the term string. | + | Then every time you take in a statement on that thread (when it runs a When block), you look up each term in the statement in the thread-local cache, so if you already have a shimmered Jim object that's a parsed list or code expression or something, you can reuse it and save yourself the effort of parsing the term string. |
| (My theory is that we are spending most of our time in folk2 reparsing stuff; every individual When block evaluation seems to take at least 50-100 microseconds, | (My theory is that we are spending most of our time in folk2 reparsing stuff; every individual When block evaluation seems to take at least 50-100 microseconds, | ||
| - | You discard any cache entries that haven' | + | (I got it to work this time by making it a more proper LRU cache with a linked list for eviction, as opposed to the hacky double-table scheme I had last time.) |
| - | I got it to work this time by making it a more proper LRU cache with a linked list for eviction. | + | The cache hasn't helped as much as I expected, although it does help. Mason reports that calibration cycle time improves from like 200ms to 160ms. |
| - | + | ||
| - | This hasn't helped as much as I expected, although it does help. Mason reports that calibration cycle time improves from like 200ms to 160ms. | + | |
| The thread-local object cache does seem to successfully prevent re-parsing of code on every eval: | The thread-local object cache does seem to successfully prevent re-parsing of code on every eval: | ||
| {{: | {{: | ||
| + | |||
| + | I'm not sure why it's not helping more. (I have the same question about Mason' | ||
| === Performance experiment: Mason' | === Performance experiment: Mason' | ||
| Line 48: | Line 48: | ||
| === Anti-blinking: | === Anti-blinking: | ||
| - | Since the spring, we've had this concept in folk2 of ' | + | Since the spring, we've had this concept in folk2 of [[newsletters/ |
| Canvases exist so that we can accurately transform page-local drawings as you lift up and skew the page, and so that we don't have to redraw page-local content when the display list doesn' | Canvases exist so that we can accurately transform page-local drawings as you lift up and skew the page, and so that we don't have to redraw page-local content when the display list doesn' | ||
| - | One problem, though, is that drawing to canvases has been a parallel process to drawing on the screen, which means that you need a way to synchronize so you don't draw a canvas to the screen while the canvas is itself being drawn onto. Until this month, we were double-buffering canvases, but this was really annoying to coordinate. I simplified everything to just run in a single loop on the GPU thread and render to canvases before then rendering to the screen. Then we can just have 1 buffer (GPU texture) per canvas, since textures are guaranteed to never be drawn to the screen in an inconsistent state. We have a decent amount of headroom on the GPU thread, so I'm hoping this is good enough for now. | + | One problem, though, is that drawing to canvases has been a parallel process to drawing on the screen, which means that you need a way to synchronize so you don't draw a canvas to the screen while the canvas is itself being drawn onto. Until this month, we were double-buffering canvases, but this was really annoying to coordinate |
| + | |||
| + | I simplified everything | ||
| === Anti-blinking: | === Anti-blinking: | ||
| Line 65: | Line 67: | ||
| If you're familiar with folk2, you might anticipate blinking problems here, because there' | If you're familiar with folk2, you might anticipate blinking problems here, because there' | ||
| - | {{newsletters: | + | {{:newsletters: |
| + | |||
| You could have a bridge period here, where you '' | You could have a bridge period here, where you '' | ||
| - | But I don't want to resort to system-wide convergence where you don't see anything until everything in the universe has converged, so I'm trying this concept of per-canvas //settle time//. Basically, the Collect statement | + | But I don't want to resort to system-wide convergence where you don't see anything until everything in the universe has converged, so I'm trying this concept of per-canvas //settle time//: |
| + | |||
| + | {{: | ||
| + | |||
| + | Basically, the Collect statement | ||
| - | TODO: Sign error | + | (among other things, had a [[https:// |
| === Camera slice blinking fix: destructor inheritance in Collect === | === Camera slice blinking fix: destructor inheritance in Collect === | ||
| Line 196: | Line 204: | ||
| Omar: I've been [[https:// | Omar: I've been [[https:// | ||
| + | === Fasteners === | ||
| + | |||
| + | Spent some time looking into fasteners to try to keep the AnyBeam projector from swiveling/ | ||
| + | |||
| + | I got some threadlocker glue, and these washers, which I haven' | ||
| + | |||
| + | {{: | ||
| + | |||
| + | === folk2 on the gadget === | ||
| + | |||
| + | folk2 is a surprisingly nice improvement for the gadget. The text is scaled to be a constant real-world size no matter where you hold the gadget, and the whole critical path of Folk runs faster, so even on this mediocre calibration, | ||
| + | |||
| + | {{: | ||
| + | |||
| + | It's hacky and not 100% correct, but to give you an idea of the differences, | ||
| + | |||
| + | < | ||
| + | < | ||
| + | < | ||
| + | # Copy this file to ~/ | ||
| + | # changes. | ||
| + | |||
| + | if {[llength [info commands Assert!]] == 0} { | ||
| + | # We're on folk1. | ||
| + | proc Assert! args { tailcall Assert {*}$args } | ||
| + | |||
| + | set fd [open |[list python3 "/ | ||
| + | fconfigure $fd -buffering line | ||
| + | fileevent $fd readable [list apply {{fd} { | ||
| + | if {[gets $fd line] < 0} { | ||
| + | if {[eof $fd]} { | ||
| + | close $fd | ||
| + | } | ||
| + | } | ||
| + | |||
| + | if {[regexp {Percent: | ||
| + | Hold battery {Claim the battery percentage is $percent} | ||
| + | } | ||
| + | }} $fd] | ||
| + | |||
| + | When display /disp/ has width /w/ height /h/ { | ||
| + | When the button is /state/ { | ||
| + | When the clock time is /t/ { | ||
| + | set color [expr {$state eq " | ||
| + | Wish to draw a dashed stroke with points \ | ||
| + | [list [list 0 0] \ | ||
| + | [list $w 0] \ | ||
| + | [list $w $h] \ | ||
| + | [list 0 $h] \ | ||
| + | [list 0 0]] \ | ||
| + | color $color width 10 dashlength 40 dashoffset [expr {fmod($t, 10)*-120}] | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | set cc [c create] | ||
| + | $cc include < | ||
| + | $cc proc gpioInit {} void { | ||
| + | // gpio mode 16 up | ||
| + | FOLK_ENSURE(wiringPiSetup() != -1); | ||
| + | pinMode(16, INPUT); | ||
| + | pullUpDnControl(16, | ||
| + | } | ||
| + | $cc proc gpioRead {} int { | ||
| + | // gpio read 16 | ||
| + | return digitalRead(16); | ||
| + | } | ||
| + | |||
| + | c loadlib / | ||
| + | $cc compile | ||
| + | exec sudo chmod 666 /dev/mem | ||
| + | |||
| + | gpioInit | ||
| + | When the clock time is /t/ { | ||
| + | set pressed [expr {![gpioRead]}] | ||
| + | Hold button \ | ||
| + | {Claim the button is [expr {$pressed ? " | ||
| + | } | ||
| + | puts stderr READY! | ||
| + | |||
| + | } else { | ||
| + | # We're on folk2. | ||
| + | |||
| + | exec v4l2-ctl --set-ctrl auto_exposure=1 | ||
| + | exec v4l2-ctl --set-ctrl exposure_time_absolute=1500 | ||
| + | |||
| + | When { | ||
| + | set fd [open |[list python3 "/ | ||
| + | fconfigure $fd -buffering line | ||
| + | while {[gets $fd line] >= 0} { | ||
| + | if {[eof $fd]} { | ||
| + | close $fd | ||
| + | } | ||
| + | |||
| + | if {[regexp {Percent: | ||
| + | Hold! -key battery \ | ||
| + | Claim the battery percentage is $percent | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | When display /disp/ has width /w/ height /h/ { | ||
| + | When the button is /state/ { | ||
| + | When the clock time is /t/ { | ||
| + | set color [expr {$state eq " | ||
| + | Wish (keep 10ms) to draw a dashed line with points \ | ||
| + | [list [list -1 -1] \ | ||
| + | [list 1 -1] \ | ||
| + | [list 1 1] \ | ||
| + | [list -1 1] \ | ||
| + | [list -1 -1]] \ | ||
| + | color $color width 0.05 dashlength 0.1 dashoffset [expr {fmod($t, 10)*-0.4}] | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | set cc [C] | ||
| + | $cc include < | ||
| + | $cc proc gpioInit {} void { | ||
| + | // gpio mode 16 up | ||
| + | FOLK_ENSURE(wiringPiSetup() != -1); | ||
| + | pinMode(16, INPUT); | ||
| + | pullUpDnControl(16, | ||
| + | } | ||
| + | $cc proc gpioRead {} int { | ||
| + | // gpio read 16 | ||
| + | return digitalRead(16); | ||
| + | } | ||
| + | |||
| + | $cc endcflags -L/ | ||
| + | set gpioLib [$cc compile] | ||
| + | exec sudo chmod 666 /dev/mem | ||
| + | |||
| + | $gpioLib gpioInit | ||
| + | When the clock time is /t/ { | ||
| + | set pressed [expr {![$gpioLib gpioRead]}] | ||
| + | Hold! -key button \ | ||
| + | Claim the button is [expr {$pressed ? " | ||
| + | } | ||
| + | } | ||
| + | |||
| + | |||
| + | |||
| + | Assert! $this wishes $::thisNode uses camera "/ | ||
| + | width 3200 height 1200 \ | ||
| + | crop {x 500 y 0 width 1000 height 800} | ||
| + | |||
| + | Assert! $this wishes $::thisNode uses display 0 | ||
| + | |||
| + | |||
| + | When the battery percentage is /percent/ { | ||
| + | Wish to draw text with text " | ||
| + | } | ||
| + | </ | ||
| + | </ | ||
| ==== Mason' | ==== Mason' | ||
| + | |||
| + | Mason has been [[https:// | ||
| + | |||
| + | {{newsletters: | ||
| ==== Projects ==== | ==== Projects ==== | ||
| - | * Rob Fielding created a full-fledged system for presenting slides that are fully controlled by programs in Folk: | + | * Rob Fielding |
| * {{youtube> | * {{youtube> | ||
| Line 205: | Line 372: | ||
| ==== Outreach ==== | ==== Outreach ==== | ||
| - | * Omar hosted [[https:// | + | * Omar hosted |
| * {{newsletters: | * {{newsletters: | ||
| * Andrés went to Taiwan and visited [[https:// | * Andrés went to Taiwan and visited [[https:// | ||
| Line 215: | Line 382: | ||
| === New installations === | === New installations === | ||
| - | * TODO: Fractal | + | * The Fractal |
| - | * TODO: Baltimore | + | * [[https:// |
| - | * TODO: Cambridge | + | * Hamish Todd has been continuing to work on his Cambridge, UK installation and was asking questions about geometry and C API in Discord |
| ===== What we'll be up to in September ===== | ===== What we'll be up to in September ===== | ||
newsletters/2025-08.1756593760.txt.gz · Last modified: by osnr
