Bad Apple on a Minitel
Why
I really enjoyed the work of HxC2001, and I’ve always wanted do do something like this with a Minitel.
How
The first thing to do was to buy a Minitel. I bought the same model I had at home for close to nothing:
It’s an Alcatel branded one, and it is actually quite different from the Philips of HxC2001. Hopefully, there is a lot of information about it here, including a detailed technical description and schematics.
The next question was how to run some code on it. I stumbled upon PicoROM (a ROM emulator based on the RP2040) some time ago, and I thought it may be a perfect fit for my need. As the RP2040 is (unoficially) 5v tolerant, I simply used a Raspberry Pi Pico connected to the expansion port of the Minitel, with some adaptation of the PicoROM firmware to handle the multiplexed bus of the 8051 MCU.
Minitel | RP2040 | Function |
---|---|---|
1 | Vin | +5v |
2 | GPIO0 | AD0 |
3 | GPIO1 | AD1 |
4 | GPIO2 | AD2 |
5 | GPIO3 | AD3 |
6 | GPIO4 | AD4 |
7 | GPIO5 | AD5 |
8 | GPIO6 | AD6 |
9 | GPIO7 | AD7 |
10 | GND | EA |
11 | GPIO16 | ALE |
12 | GPIO17 | PSEN |
13 | GPIO15 | A15 |
14 | GPIO14 | A14 |
15 | GPIO13 | A13 |
16 | GPIO12 | A12 |
17 | GPIO11 | A11 |
18 | GPIO10 | A10 |
19 | GPIO9 | A9 |
20 | GPIO8 | A8 |
32 | GND | GND |
The bodge wire is the reset signal, and some bridges needs to be cut to disconnect the keyboard, as described in the technical description.
After studying a little bit the TS9347 “semi-graphic display processor”, I through it was a perfect fit for Bad Apple: lots of infills, with only the outline of the characters that are really graphics, that can be rendered using the custom characters available with the TS9347.
Using ffmpeg, ImageMagick, and a Python script, I quickly extracted the black or white only zones, and a list of custom characters per frame. Some frames require more than 300 characters. That may fit in the available memory, but to achieve a decent framerate without flickering, double buffering is needed leaving only 192 custom characters available per frame. Some frames will be miss details, but not too much, thanks to the semi-graphic ROM characters present.
After some tries, I ended on using an unrolled assembly code to copy the frame in the video memory. This way, I managed to have a 30 Hz refresh rate but each frame takes about 20 kB of ROM space, so how to fit the required 6573 frames of the original video?
Then came the last part of the equation: I have a programmable ROM emulator, so I could just implement some bank switching with it. I actually cheated a bit as I’m just patching the ROM image in the RP2040 RAM directly. At about 4 kB of data per frame, some compression with LZ4 was used to fit the entire 6573 frames in the maximum 16 MB of flash available on some RP2040 boards. To make the story short, parsing the assembly listing generated by the compiler proved to be very useful to get the offsets to patch in the ROM. The bank switch occurs when reading at specific addresses in the emulated ROM. So when page 0 is displayed, page 1 gets loaded in the video memory, and page 0 in the ROM is updated with the next frame.
Along this, Bad Apple without audio is a bit tasteless, so I decided to cheat a little bit and added a 4 bit DAC in place of some control lines of the modem (after all, cuttable bridges were here for expansion according to the technical description), and connected the output to the built-in audio amplifier:
Audio was downsampled to 7680Hz (leading to 256 samples per frames), also served with the bank switching trick.
Afterthought
This model of Minitel is a bit of a hack: for example, an address line of the video processor is used to control the power/standby LED.
The design is very neat: no screws, the PCBs are cleverly interlocked together, and a lot of room for expansion was provided.
The PicoROM is awesome, enabling super easy test iteration on the real hardware.