My friends and I play a game called Blates with a pair of 6-sided dice. I thought it’d be cool to make an electronic 2d6. There’s a demo video below if you’d rather skip the lecture.
First design problem, the hardware…
Displaying die values, ideally as die-face-like sets of dots, is one of only two things this device needs to do, so that’s awful important. Discrete LEDs is the top choice here, and as for layout, clearly a 3-by-3 grid does the job:
1 = E
2 = AI or CG
3 = AEI or CEG
4 = ACGI
5 = ACEGI
6 = ABCGHI or ADGCFI
… but 18 bits for a two-die display is a heavy price. There are plenty of symmetries to exploit, and the different orientations of the same face aren’t critical. I whittled it down to this:
1 = D
2 = A or C
3 = AD or CD
4 = AC
5 = ACD
6 = ABC
With this a six-sided die’s face can be done with 4 bits. 2d6 for 8 bits, that’s more like it. “6” can only be shown in one orientation, but “2” and “3” can still be jazzed-up with two orientations.
Speaking of jazzing up, I had a bunch of these wacky LEDs waiting around for a job to do:
They’re simple and self-contained: they get power, they do their light show, and there is no fine control. Besides the two obvious states available, “off” and “apeshit”, there’s a third that can be squeezed out. The sequence these things play out is deterministic, so by rapidly switching them off-and-back-on they can be held in limbo in the first fraction of a second of their routine. Fortunately that routine begins with some slow fades, and this third state comes out as a steady blueish-white, so I’ve got “off”, “on”, and “apeshit”. The game I’m targeting rewards matching pairs, so the “apeshit” state is reserved for decorating those.
I went with a PIC 16F688 for the CPU because it’s the simplest PIC I had on-hand; it’s a little overkill but not too bad. The 688 has enough I/O pins to directly handle everything, and it has “High-current source/sink for direct LED drive”. There is some fine print, however: each pin can handle 25mA, but the chip can only do 90mA total. Each of these wild LEDs is in fact 3 very bright LEDs, and most of them would be wired up in parallel pairs. Directly driving up to twelve of these things with the PIC isn’t safe enough for my tastes.
Luckily I wasn’t stuck wiring up a bunch of transistors because I had TPIC6B595, a suspiciously perfect fit for this job: 8-bit shift register, latch, and power transistors in one package. This thing can do 150mA continuous on every output, and with the latch in the middle it can shift-in the 8-bit state and then update the outputs simultaneously. With this the LEDs can be controlled with just 3 signals: data, clock, latch.
Add a piezo beeper and a button and you’re looking at 5 I/O pins total, which means all of the ICSP pins can be left wide open.
I’d rather not use batteries for power. Batteries are a pain in the ass, and even a simple boost converter would double the number of components in there. Thanks to USB’s ubiquity you can get +5VDC just about anywhere, so I just put a power jack on there. There’s nothing defensive between the jack and the circuit, but that capacitor there will certainly “notify” you if you hook up the wrong voltage.
Now on to the software…
Of course it would be nice if these dice were random, right?
Usually for a lightweight PRNG I turn to multiply-with-carry, but even that is pretty hardcore for this little chip; it only understands 35 instructions, and multiply isn’t one of them.
I found an even lighter machine in EternityForest’s xabcrand. This thing’s internal state is only 4 bytes, and it uses little more than XOR and ADD. The heaviest part of it is its 256-byte substitution table. The 688 only has 256 total bytes of general-purpose memory, not even contiguous, but it can read instruction memory directly into the ALU, so this table can reside in the more generous 4K Flash ROM.
Tiny state, simple math, PRNG is a go.
Of course it would be nice if these dice were actually random, right?
All is for nothing if this gadget comes up with the same sequence of “random” rolls every time it’s powered on; without a chaotic seed that’s all a PRNG can give you.
There’s an ADC, it could use electrical noise…
There’s an EEPROM, it could save state after every roll…
In fact there’s a source of entropy already waiting there: the button. The moment in time you press it, the moment you release it, the length of time you hold it, these are effectively random if you slice time thin enough. I set up the PIC’s TMR0 to increment at 2MHz, overflowing every 128 microseconds. When you push or release the button, TMR0’s accumulator at that moment is mixed into the PRNG’s state. With this you could theoretically rig your roll, but you would have to know the internal state of the machine and hit a half-microsecond window with your button actions, so, in practice, you can’t.
Philosophically this device is a lot like real dice. The system is essentially deterministic, and you are completely in control, but a human has nothing close to the intellect or dexterity it would take to direct the outcome. Whatever happens is your fault, but you can’t take credit. Implementing a kind of momentum and allowing extra button presses mid-roll enables you to roll these dice with your own style or lucky technique.
As for the future, the only ideas I’ve got are aesthetic. Maybe the “apeshit” light show could be reigned-in by periodically resetting the LEDs to keep them synchronized, or maybe the sequence could be cut short to omit the flashing and only do the fading. The beeper gadget could be replaced with a bare piezo to enable variety in sound effects or even some short melodies for especially good or bad Blates rolls. Force-feedback could be neat; the box could “pop” a little every time the faces change, but a lot of this thing is held together by friction and I’d be concerned about the chips and LEDs being shaken loose. Going way out, if I were to build a successor, I’d use diffuse NeoPixels and an accelerometer/gyro rather than a button, so you could actually shake the device to roll.