-
Ghosting
05/01/2017 at 12:44 • 0 commentsWhen I realized that the IS31FL3733 chip is not going to handle the button scanning well enough for this use case, I decided to design a new prototype board, with the buttons connected directly to the GPIO pins of the Feather.
However, I want this to work with all Feather boards, including the ESP8266-based Feather HUZZAH, which means that I only have a few GPIO pins to work with. A quick count gave me 7 pins: GPIO0, GPIO2, GPIO12, GPIO13, GPIO14, GPIO15 and GPIO16. However, there are some caveats. The GPIO15 pin has to be pulled low at boot, otherwise the ESP8266 will boot into some weird mode. The same with GPIO0 and GPIO2 being pulled high. And finally the GPIO16 is a bit special and doesn't have an internal pull-up.
I have 6 buttons, so with the naive approach I will need 6 of the GPIO pins. I made a quick go at the PCB for that, together with six external pull-down resistors. That turned out to be much more complex than anticipated. Also, I really can't leave those pull-down resistors on GPIO2 or GPIO0, so I'm one pin short.
I considered my options. I could ditch the resistors (which would simplify the design a lot) and use internal pull-ups (which would also solve the problem of the pin state at boot). Hmmm... a quick redesign, and it already looks much better. But I can't use GPIO16 (no pull-up), and the GPIO2 has a LED on it, which lights when you press the button. It would be nice to at least leave that one free...
Fortunately there other ways of connecting buttons. I can make a key matrix and scan it. Let's see, I have 6 buttons, so the best matrix I can make is 3x2, requiring a total of 5 pins. Not much, but progress. I quickly made another PCB design using that, leaving the GPIO16 and GPIO2 pins free. Perfect! At this point I was pretty late, so I saved the design, generated the gerber files and ordered the prototype PCB at OSHPark. And went to bed.
And then, lying in the bed, I realized that my design has a fatal flaw: ghosting. It's a game console, and people are not going to just press one button at a time like the cultured citizens they are. They are going to be mashing all the buttons at once, trying to beat the game. And the simple key matrices, the kind that I used in this design, have a problem when several keys are pressed at once: the keys connect together several rows and columns of the matrix, and in effect the microcontroller thinks that more buttons are pressed than actually are. A simple solution for that problem is to add diodes to every button, so that it won't connect the columns and rows in both ways -- this way preventing the columns that are not currently selected by the scanning algorithm from getting power. However, at this point the PCB was ordered and there was simply no room to add 6 additional diodes to it anyways.
For now I decided to just test the prototype when it arrives and work on the software and the games a little bit, ignoring the ghosting problem, and later I will look for a separate I²C chip that will handle the keys for me.
-
The Concept
05/01/2017 at 12:18 • 0 commentsHere are some more details about the whole concept of this board.
The board will be the size of a standard FeatherWing shield -- same as the Adafruit Feather boards, and of course it will plug into those boards. It should work with any of the Feather boards, but I only plan to make the drivers and library available in CircuitPython -- so if you want to use it with any of the boards that don't run CircuitPython, you will need to write the software yourself -- but then again, you are then probably pretty experienced anyways.
The board will have a bi-color 8x8 LED matrix for display, and 6 buttons for input. It will also contain the electronics for handling the display and buttons. I might add some way of making sounds, but that's not decided yet.
The FeatherWing will communicate with the Feather using I²C protocol and the two standard pins traditionally used for that on the Feather boards, using a few fixed addresses. All the other pins will be free to be used with other add-ons. The prototypes may be using additional pins for experimenting, but ultimately I want them to be free.
The power is drawn from the Feather board, which in turn can be powered either through USB, or with a LiPo battery connected to the battery connector. A #Battery FeatherWing can also be used.
Since the top side of the board is pretty much all taken by the display and buttons, the components have to be placed on the bottom side of the board. They should however be as flat as possible, as to not collide with the components on the top side of the board below.
There will be a number of CircuitPython libraries for the low-level components of the board, as well as a high-level library dedicated to this particular board and to making games with it. That high-level library might use some simplifications and may add limitations to what can be done, for the sake of making things simpler. Experienced users can bypass that limitation by calling the low-level libraries instead.
There will be a number of example games implemented for this board, as well as at least one tutorial describing in detail the steps required to write such a game. All those games will be written in CircuitPython. Some of the larger games might not work on all the Feather boards, due to memory limitations.
Apart from playing games, the board can also be used for controlling other devices -- if a Feather board that has WiFi, Bluetooth or packet radio capabilities is used, or if an add-on giving such capabilities is connected. This will not be covered in the main library, though. (Also, multiplayer games could be possible, but that is also outside the scope for now.)
-
The Buttons
05/01/2017 at 11:41 • 2 commentsWhen I started planning this board, I only knew the HT16K33 LED driver chip (well, ok, also the MAX 7129, but that's ancient). That chip has a pretty cool feature -- by adding a diodes to the column pins you can re-use them to scan a matrix keypad at the same time as they drive the LED matrix. The chip even does de-bouncing for you, you just have to read the state of the keys from its registers. Super-convenient for a device like this.
Unfortunately, the IS31FL3733 chip that I'm using now, while it allows me to control the brightness of each individual pixel, doesn't have such a keyboard-scanning feature. But wait, the datasheet mentions something similar -- it has an open/short LED detection. Isn't a closed button pretty much electrically equivalent to a shorted LED? I could use this, together with the extra column pins that I don't use (the chip supports 12x16 matrixes, I only have 8x16) to scan the buttons!
I designed the first prototype with that idea in mind. The buttons are connected -- through resistors, for safety -- in place of LEDs on an extra column. Once the PCB arrived and I assembled it, I could start my tests.
Turns out getting this mechanism to work properly is a little bit involved. First, the LEDs need to be enabled by writing 1s to the corresponding registers on the page 0. Then, the power register on page 3 needs to be set to 1, the minimum power setting. I experimentally determined that this step is not actually strictly necessary for the mechanism to work, but it's probably there for safety, and it prevents the LED matrix from flashing brightly while the chip tests all the lines. Finally, you have to trigger the testing by writing 1 to a bit field in the config register on page 3. Then you have to wait 3.264ms, and finally you can set the current back to what it was, clear the bit field in the config register, and read the LED status from the registers on page 0. Easy.
I got my code to work, and decided to try and write a simple snake game to see how well it all works. Turns own that it works pretty bad.
You see, to get a decent responsiveness from the buttons, I need to scan them often. At the minimum once per the game's animation frame. Humans are very sensitive in delays in tactile and visual areas -- especially tactile. So I need to scan often. But you see, to scan I need to drop the current to the minimum setting, which effectively switches the display off. And if I do it for 3.265ms every frame, I get a nasty flickering. The board also makes some suspicious high-pitched noises, which can't be good.
So that's it for the first prototype. I need to find a better way of handling the buttons. That prototype was going to be trashed anyways, because I made the holes for the matrix pins too small -- that's why the matrix is soldered on top, and not flush with the board on the photos.
-
The Display
05/01/2017 at 11:17 • 0 commentsI could use an OLED or a TFT display, but there are several problems with that. First and foremost, the pixels are tiny on those, especially on the ones that would fit on a FeatherWing. Second, they aren't very easy to handle, unless I'm using a ready module, which in turn looks pretty bad. Finally, they are rather brittle and easy to damage.
There is also the problem of graphic design. While I personally have no problems making pixelart for my own games, I expect this to be a problem for someone just starting, and also a big distraction from our goal of teaching the programming of interactive interfaces. So we definitely want to go low-resolution, because then you only have a few pixels you have to care about, and everything goes faster.
The limited memory and processing power of the devices I am targeting also plays an important role here. Iterating over 8x8 array is almost instant, while doing that with a 320x280 RGB display takes some time.
So I decided to use a 8x8 LED matrix. But a single-color matrix is a bit limiting, especially when you can only switch the pixels on or off. Sure, you can make a Flappy Bird or a very cramped version of Tetris, but it's not very exciting. That's why I decided to use a bi-color matrix, which looks very pretty with its combination of green and red pixels. I also found a chip that lets me easily control the brightness of individual pixels (or rather their red and green components), which gives me a very nice palette of colors to choose from. There is no blue, unfortunately -- an RGB matrix could be even nicer -- but that would bring the number of pins I need to control to 32, and I simply couldn't find a chip that could handle this.
So I made the first prototype board using the IS31FL3733 chip and a bi-color 8x8 LED matrix. It took some work, especially as I initially worked with the chips in QFN packages, and couldn't get them to work reliably due to my soldering them by hand being sub-par. But finally the PCB with a TQFP foortprint arrived, and that allowed me to easily solder those huge pins and then it was just a matter of a few hours re-reading the datasheet to figure out which registers I need to modify to bring this thing to life.
I might need to add some gamma correction for this in software, but it looks better in real life than on the photo -- my phone camera tends to get the color of lights wrong.