We want to build a real life TIS-100, that looks and feels like the one in the game (http://www.zachtronics.com/tis-100/). That means lots of modules, each with its own display, which can be connected in different configurations. It also means a connected keyboard, which allows editing of the code, just like in the game.As much computation and control as possible should be done in the modules, to mirror the distributed behavior in the game. All features and quirks of the game should be accurately emulated.This is of course entirely impractical, and not of use to anyone. Nice gizmo though. Cheers, Uncle Randy!
During the last months we have experimented with some hardware. We found a cheap 2.2 inch display on Ebay with a 176x220 pixel resolution called ILI9225. It was the cheapest display we could find (about $4) that had enough pixels to display the TIS-100 GUI.
We also bought some AVR ATMEGA328P-PU microcontrollers, the same one as the Arduino UNO R32 uses, but we ended up using an Arduino board for the tests so far.
The next step was to try out the display. We assumed that since the display seemed popular, there would be many graphics libraries that supported it. It turned out to not be widely supported. We found the u8glib library that had a nice API and supported many displays (but not ours). We tried to add a driver for our display to it and actually got it working. However, the limited clock speed of the AVR MCU combined with the design of the library made it very slow for us. The framerate was less than 1 Hz.
The u8glib library supports drawing many kinds of graphics (text, polygons, etc) using a limited amount of memory. It does so by running the graphics code multiple times. Each time it masks away everything except a few lines, an thus only needs to use memory for those lines. Our driver was also using an inefficient method to send pixel data, but we did not know that yet. For our uses it made the wrong trade-off between CPU and memory.
We then decided to write our own code for just what we needed: a matrix of characters, and a character to pixels mapping (that is, a font), dirty rectangle handling, and a way to turn rectangles of pixels into SPI commands. After some optimization of how we sent the pixel data and extensive debugging, it worked! We got an update rate of about 30 Hz.
When we were thinking about how the communication between the modules should work, we realized that we did not know how TIS-100 behaved in certain cases.
The first unknown was when reads and writes to neighboring nodes occur during a machine tick. For example, is it even possible for a node to read and write during a single tick? Consider the following program:
Node A Node B
MOV 1, RIGHT | MOV LEFT, LEFT
ADD RIGHT |
Its behavior can be described like this. Each game tick can be divided into a read phase and a write phase. Each instruction first executes its read operation (if any). If no value could be read, the node stalls for the whole tick and tries again in the next read phase. Then the instruction executes its write operation (if any). This signals to a neighboring node that data is available to read. Since writes occur after reads, the writing operation can never complete during its first tick. This "wasted" tick is not counted as idle time by the game.
The behavior of the code above can therefore be described as follows:
Node A Node B
1R - | 1R No value to read
1W Signal value available | 1W -
2R Transmit value | 2R Receive value
2W - | 2W Signal value available 3R Receive value | 3R Transmit value
3W - | 3W -
Since Node B has no value to read for the first tick, it is idle here. This means it has 33% idle time, which is consistent with the value shown in the game. Both programs turn out to take exactly three ticks per iteration.
This cleared up our intuition for a while. Then we thought about ANY... Stay tuned for the next post!
Hi @Rasmus Svensson, The manual describes a "light-weight" messaging protocol. I've been designing a blocking 1-wire protocol that would allow for comm-negotiation over 1 wire between any of the 4 adjacent nodes (as long as they weren't already blocking). If I can get it to work, I think that it would fit in with the feel of transmission in game. I.E. Block incoming messages - signal an intent to pass message - transmitting packet - then waiting for an ACK.
Also, as you know, @Gabriel Smith was considering using ATTINY micros for his build. I like the idea of this because they are small, simple modules that are cheap -- which is the only way a multi-core beast like this would have been built in 1980. The protocol I've described above uses exactly the number of pins needed to have a 1-to-1 link with the surrounding nodes, and a single pin to signal communication blocking (which will be checked by incoming senders).
I am also writing an interpreter for the ASM commands to be run on any Arduino compatible board. In this case the boards would not be programmed with the assembly, but rather they would store the program in an array and use C to act on the array and interpret the commands accordingly.
If any of this is of interest to you, I can share my notes as I work through it.
Hi @Rasmus Svensson, The manual describes a "light-weight" messaging protocol. I've been designing a blocking 1-wire protocol that would allow for comm-negotiation over 1 wire between any of the 4 adjacent nodes (as long as they weren't already blocking). If I can get it to work, I think that it would fit in with the feel of transmission in game. I.E. Block incoming messages - signal an intent to pass message - transmitting packet - then waiting for an ACK.
Also, as you know, @Gabriel Smith was considering using ATTINY micros for his build. I like the idea of this because they are small, simple modules that are cheap -- which is the only way a multi-core beast like this would have been built in 1980. The protocol I've described above uses exactly the number of pins needed to have a 1-to-1 link with the surrounding nodes, and a single pin to signal communication blocking (which will be checked by incoming senders).
I am also writing an interpreter for the ASM commands to be run on any Arduino compatible board. In this case the boards would not be programmed with the assembly, but rather they would store the program in an array and use C to act on the array and interpret the commands accordingly.
If any of this is of interest to you, I can share my notes as I work through it.
Peter