-
The 4-inch board that bricks itself on reset, and what actually recovers it
a day ago • 0 commentsThe 4-inch board has a failure that looks like a dead board. After the reset button, a serial tool's RTS reset, a USB power surge, or most often the hard reset at the end of an upload, the ROM loops 'flash read err, 988' every 350 milliseconds with the panel dark.
The first guess was the GPIO12 strap, which on this board also serves as the shared MISO line. Wrong: the ROM prints boot:0x17, whose MTDI bit is clear, so 3.3 V flash was selected correctly.
The second guess was a damaged image. Also wrong. Read back while the board was looping, the bootloader at 0x1000 was byte for byte correct, and the failing read differed from it by three bits at the same address. It is a marginal read at the moment of certain resets, not corrupted flash.
The cause is still unknown. What recovers it without pulling the battery is a reset that comes from download mode rather than from the running ROM: ask esptool for the flash id with no reset afterwards, then ask for the MAC with no reset before and a hard reset after. Repeat the pair if it fails, never the second step alone.
The flashing tool now asks every board for its build after an upload and runs that recovery on any whose serial shows the loop, so a flash no longer leaves a dark 4-inch board behind.
If you own one of these and have seen the same thing, I would like to hear it.
-
A web installer that can only install the newest build has no way back
a day ago • 0 commentsThe installer used to offer exactly one firmware: whatever main last built. Then a release shipped a defect that made the two 2.8-inch boards untouchable, and the only thing anyone could install was the broken one.
A page that can only install the newest build has no way back from a bad release, which is precisely the moment somebody needs one.
So it grew a version selector. Four things about it are load-bearing.
The bytes are copied, never rebuilt. What is served for an old version is what was published as that version, so an old version cannot quietly become a new build of old source, and a tag that no longer compiles today is still installable.
They are copied rather than linked because of CORS. The obvious implementation points the manifest at the release asset URLs. That does not work: the asset host sends no Access-Control-Allow-Origin header at either hop, so the browser's fetch is blocked after the board is connected and the flash has already begun. Serving the bytes from the page's own origin removes the question.
The version list belongs to the board, not the page. A board added in a later release has no earlier build, and switching to it falls back to latest rather than leaving a stale manifest armed.
A release missing any of its four parts is skipped entirely rather than half-published, because a partial image fails after the erase has started.
-
There is no malloc in this firmware, and leaks are not the reason
a day ago • 0 commentsThere is not one new, delete, malloc or free in Braino. Every screen is a static instance and everything else is stack or a fixed member.
The obvious reading is that it therefore cannot leak. True, but leaks were never what kills a device like this.
FreeRTOS gives you a heap that can never be compacted. Many small allocations of differing sizes, made and freed over and over, chop the free space into pieces too small to satisfy a later request. Free heap looks healthy right up to the allocation that fails, hours in, in somebody else's hands. The only warning beforehand is the fragmentation percentage, which is why the System Info screen shows it.
The usual offender is Arduino String. Every concatenation allocates, every assignment may reallocate, and a String member rewritten each frame is a long-lived block being freed and remade 27 times a second.
The worked example is the row list every settings screen uses. It was 48 rows times two Strings, rebuilt every frame: about 96 long-lived allocations churning at frame rate. It is now flat char buffers that allocate nothing, ever. That cost 864 bytes of static RAM and saved 5.5 KB of flash.
Trading a few hundred bytes of always-resident RAM for zero heap traffic is nearly always the right call on a device that has to survive a long afternoon without an adult rebooting it.
-
Four consoles, one Ludo table, and dice that never go on the air
a day ago • 0 commentsChess between two consoles was one thing. Ludo needs four, and it needs a die.
The die is the hard part. If one console rolls and transmits the number, every other console has to trust it, and the first player to patch their firmware wins every game. Worse, a dropped advertisement is a roll nobody heard.
So the die never travels. Every console derives each roll from the table's seed and the turn number, and the rules refuse any move that does not fit the roll it computed for itself. When two consoles disagree, the move is rejected rather than producing two different boards.
That decision cascades.
Who moves first comes from the seed too. Between two players a coin toss inside the invitation works, because the console that asks for a game must not also claim the first move. A toss cannot seat four, so the deal becomes a shuffle nobody chooses.
A console replaces its turn only once every other console has acknowledged it. On a medium that drops things, that is what makes a bonus roll safe.
A console that goes quiet pauses the table, and once it has been silent long enough to count as gone the host may take its seat over and play it as a computer player. That is a numbered ply in values nothing else uses, so it needed no new bytes.
The wire never changed. Ludo spells its meaning into the same fields chess uses: a seat and a token, or a presence, or the host's start word.
-
Two consoles play chess in 31 bytes, and never connect
a day ago • 0 commentsA BLE advertisement carries 31 bytes. Not 31 bytes of free space: 31 bytes total, counting every AD structure's own length and type byte. With the flags, the manufacturer block header and a name long enough to be recognisable, Braino's advertisement was already exactly 31 bytes before a chess move existed.
So a move could not be added. It had to displace something.
What went was the score. When two consoles are playing each other, neither cares what the other's best score in Memory is, so those four bytes became a session number, a move number, two square numbers and an ack. Thirty-two bits is enough, because a square is six bits and there are 64 of them.
Three things follow.
The game is a broadcast, not a connection. No pairing, no bonding, no GATT, no central and no peripheral. Both consoles advertise and both scan. Everyone in range hears every move and only the two playing act on them. Walk out of range and the game pauses rather than dropping.
Every received move is checked for legality in the receiver's own position before it is played, so a hostile advertiser can waste a scan window but cannot corrupt a board.
Ending a game rides the same field. A move whose source and destination are the same square is never legal, so it cannot be mistaken for a real one, and it costs nothing in a payload with nothing to spare.
Backgammon, Sea Battle and Ludo now use the same transport. None of them knows what the others' moves mean.
-
Change Log Before Hackaday page
2 days ago • 0 comments5.12.3 (15 Sep 2026)
Wording only: the documents no longer put ages on the people using the console. Players are players.
5.12.2 (15 Sep 2026)
A new landing page that leads with the product on the boards people own, six stills where there were ninety-one, and "administrator" in place of "adult" throughout.5.12.1 (13 Sep 2026)
A licence release. Every file now states its own licence and copyright holder, checked in CI. The console behaves exactly as 5.12.0.5.12.0 (13 Sep 2026)
Two new games, Space and Roman, bring the catalogue to 40. Math gains word problems, Shapes gains three harder rounds, and going idle now ends an admin session.5.11.0 (12 Sep 2026)
Go, on 9x9 and on 19x19 for the 4-inch console. Chess gets a computer opponent at two levels, and Find my Braino makes a nearby console ring. A nearby game now pauses and says so when the other console goes quiet.5.10.0 (11 Sep 2026)
Ludo for up to four consoles and Backgammon for two, with dice that never go on the air. Sound arrives on the two 2.8-inch boards, mute is one tap away, and every theme's colours are measured against contrast floors.5.9.1 (8 Sep 2026)
A hotfix. 5.9.0 was withdrawn because a diagnostic read in the boot log corrupted the display on two of the seven boards then offered.5.9.0 (8 Sep 2026)
Two consoles can play each other: Chess and the new Sea Battle run over the Bluetooth beacon. Cursive handwriting tracing arrives, and Chess remembers an unfinished game.5.8.0 (7 Sep 2026)
Piano and Chess, the first two apps that are not drills. One octave with note names, and the full rules of chess for two players sharing a device.5.7.0 (6 Sep 2026)
Nine display themes and a once-a-day "newer firmware available" notice. Fixes sound cut short on two boards, a beacon crash, and a 4-inch board that could not wake from sleep.5.6.0 (6 Sep 2026)
A new board, the 3.2-inch E32R32P. Name the consoles around you, poke one from the Nearby list, and install an older release from the web installer.5.5.1 (5 Sep 2026)
Fixes a 5.5.0 defect that left the two 2.8-inch boards unable to read touch. The pin clash behind it is now a compile error.5.5.0 (5 Sep 2026)
Screens repaint what changed instead of the whole panel, which ends the visible flashing. Sound comes to the 4-inch board from the same synthesiser.5.4.0 (4 Sep 2026)
The 4-inch E32R40T is supported, with games scaled up to fill it. The console gets a spoken boot phrase and a sound vocabulary, and the BOOT key becomes Home.5.3.0 (2 Sep 2026)
The Freenove FNK0104B, an ESP32-S3 with capacitive touch, brought up on real hardware. Braino makes sounds for the first time.5.2.0 (27 Aug 2026)
The ESP32-2432S028 joins the installer's board picker. The build is pinned and reproducible, and the privacy statement is tightened to match the hardware.5.1.0 (27 Aug 2026)
Releasing becomes a tag: CI builds and publishes every image. Adds a security policy, a code of conduct and issue templates.5.0.0 (26 Aug 2026)
An admin profile behind a four-digit PIN, hold-to-unlock, and Elements, the periodic table, as game 31. A board is now described in two files, printable cases arrive, and the project gets its licence.4.2.0 (17 Aug 2026)
Battery work: a clearer gauge and a charge-me warning at 15%.4.1.0 (15 Aug 2026)
The console is renamed Braino!. Adds Dice, Coin Flip and Nearby, an opt-in anonymous score exchange between consoles, and moves every game onto the hardware random number generator.4.0.0 (15 Aug 2026)
A web page that flashes the board from a browser. Adds Percent and GRE Words, screen sleep, and a redesigned Trace.3.0.0 (13 Aug 2026)
The opt-in Bluetooth beacon, with a System Info screen that shows the exact bytes on the air. A performance pass removes flash reads and blocking delays from the frame loop.2.0.1 (11 Aug 2026)
Screen brightness control and a 180-degree screen flip. Fixes a Light theme that was partly invisible.2.0.0 (11 Aug 2026)
Flags, Countries and Number Line. Spaced repetition and adaptive difficulty arrive, and Cinnamon stops flashing the whole screen.1.0.1
A launcher layout fix.1.0.0
The first firmware: 20 games, themes, touch calibration and a Pong screen saver.Full notes for every release: https://github.com/iamankushpandit/Gume/blob/main/CHANGELOG.md
Ankush Pandit