The #PewPew Standalone is pretty much where I wanted it to be in terms of balance between size, simplicity, ease of use, functionality and, last but not least, price. However, if I sacrificed a little bit of convenience and size, maybe I could make something with more functionality and better price?
I just made the final fixes for the next version: moved the "z" button closer to the "o" and "x" buttons, made contacts and cutout for the piezo speaker (and a resistor for it), added a footprint for a voltage regulator. I also increased the sizes for the button holes so they should be easier to fit now, and moved the display minimally further from the edge, to make sure the flex tape doesn't stick out. Oh, and made a cutout for the USB port in the top plate, as it's slightly thicker than 2.5mm, and I don't feel like filling it down to size. Also added labels for tx/rx pins on the back, and made the screw holes in the inner plate smaller, so they will also be caught by the screws — to compensate for the thinner top plater.
I specified the top plate to be 1mm thick, we will see if they follow the instructions.
After yesterday night experiments, today I sat down and made better graphics for the "pixels", and also centered the display and made sure the edges have no garbage, etc. I'm quite happy with the result:
As a bonus, you can use pewpew's game chooser to also choose the µGame games.
Next on the agenda is to finish the graphical game chooser.
Last time I implemented the pew library for this TFT display using CircuitPython's displayio, and it it was fast enough, only had very noticeable tearing. So I thought I will need to either blast the data directly over SPI to it, or even write that part in C to be fast. But today I thought: wait, what if I just used the Stage library that I already use for those games? Would it be fast enough? Turns out that it totally is!
I basically did the simplest thing that could possibly work: loaded a set of tiles from the Jumper Wire game, defined a grid for it, and in the show function I'm updating that grid and then rendering the whole screen. And it works very well, no noticeable tearing! And you know what is cool about this approach? You can have a 16x256 image that defines the tiles, drawn specifically for the given game. So for Tetris you would have just boxes (maybe with some 3D effect and/or shading), for snake you would have the head, body parts and apples, for Sokoban walls, crates and a worker, etc. — so the game would still use the simplified 8x8 display, but now the different "colors" would be actual images.
I am not yet entirely sure how I want to do it, and I might still go for a custom C function for drawing this, for example to make the blocks 20x16 instead of 16x16 to fill the whole screen, but we will see.
Let's talk about screws. When I made the acrylic back for the #PewPew Standalone, I made the holes the right size to use M1.8 screws I had left over from hobby servos. They look somewhat unusual, as they have something that looks like a built-in washer on their heads:
But then it turned out that they are pretty much impossible to buy without the servos, and when I run out of them, I had to find something equivalent. So I bought some random M1.8 screws that looked small enough. Turns out that there is more to a screw than the diameter — there is also the depth of the thread, and the ones I got fit into the holes slightly too loosely.
So this time I made the holes 1.4mm in diameter, to ensure a tight fit, and I didn't think much about one more parameter — the length of the screw. After the parts arrived and I assembled them, it turned out that the pointy part of the screw is sticking out a little bit. The PCB is 1mm, the inner layer of acrylic is 2.5mm, and the outer is 2mm, which gives 5.5mm together, and the screws are 6mm long. So I did what every hacker would do in that situation — cut them. But that is not a solution if I want to have them produced in bulk, so I need to find the right screws.
After a bit of looking around, I found screws that are M1.8 and have a flat end — not pointy. Now, the new version will still have 2.5mm inner layer, but the top layer will be only 1mm thick. With 1mm thick PCB that would give me 4.5mm for the length. The screws come in 4mm and 5mm lengths. But wait a minute, they are countersunk, so they will probably sink at least 0.5mm into the larger hole in the PCB. But is the length measure including the head, or not? Hmmm... I could also use thicker PCB, and add that 0.5mm there, if needed. But I need to know the exact dimensions of the screws to do that.
For now, I ended up ordering both the 4mm and the 5mm ones, and I will see how they work.
Another iteration of the PCBs arrived, and this time also with the laser-cut acrylic plates that form the case of the device. I have been thinking about doing this ever since µGame, but only tried it now, and I am very happy with the results. It looks like this:
(Sorry for a bad photo, but it's dark already, I will make better photos tomorrow.)
As you can see, the device is a sandwich of three layers: the PCB, a filler layer, and the front cover. The front cover has to be transparent so that we can see the display, and has cutouts for the buttons. The filler can be made of anything — in this case it's also transparent acrylic, like the front cover, but it doesn't have to be. It has cutouts for all the components on the PCB, and it's exactly 2.5mm thick, just like the display. And finally the PCB holds all the components, and has its back completely clear of any exposed pads. At the back there is also the battery holder, and that's it. It's held together with six screws, that screw into the smaller holes in the front plate. The tips of the screws had to be cut, so that they don't stick out, but I hope to find screws with flat tips instead. The whole thing is 6.5mm thick right now, but I want to use a bit thinner front plate in the future, so it will be 6mm.
Of course it's not perfect, there are a few changes that still need to be done for the final version:
the buttons don't stick out enough, I need a thinner, 1.5mm (instead of current 2mm) front cover,
the holes for the buttons are too tight — the buttons have to be in just the right places for the covers to fit, I need to add some more leeway in there,
the USB socket is minimally too thick. I will need a cutout for it,
I need room for a piezo speaker, since I decided to be adding one in there,
I need some decorations on the PCB and maybe etched on the laser-cut parts as well.
I also finally tested how the displayio-based Pew library works on the SAMD51, and it's much better than on the SAMD21, though you can still see a lot of tearing. I still need to try with direct SPI writes, and if that doesn't work better, a C module. But it might as well be unnecessary, because there is going to be a change to how display is refreshed in CircuitPython 5.x, and that might as well resolve this problem.
I also tested connecting a small piezo speaker to the DAC pin and playing some sounds, and while it is relatively quiet, as expected, it's unexpectedly good, even without an amplifier. I might add that to the next version, or make an audio shield for it.
I have build a few more prototypes, to test different kinds of buttons and see what could be done for the display attachment:
The displays are a bit of a problem: they don't stay perfectly flat on the PCB, and there is light leaking from underneath. The two-sided tape that is supposed to hold them in place is attached to the white plastic foil on the bottom, which comes off easily, and the the display no longer stays where it should. It all feels very flimsy and unreliable. As you can see, I have tried hot glue, and that does the job if done carefully, but looks awful and is a lot of manual work. So the next plan to try is to make a laser-cut case, consisting of two layers of transparent acrylic, to hold the display in place and also give the PCB some bulk for more comfortable holding.
But that brings us back to the problem of buttons. The white silicone buttons on the right side of the photo worked pretty well with the case-less design: they are as flat as the display, so the device has consistent thickness. They are clicky, but not too much, and they have a nice feel. But they wouldn't stick out of the case if I added 2mm of acrylic on top.
So next are the standard "6x6mm tactile switch" buttons that I have used in all the PewPew consoles to date. They come in a variety of heights, so I can always find one that sticks out enough, and there are also plastic caps available that come on top of the buttons, that further make them stick out more. But the base of the button is higher than the display, so I would need some extra padding under the display, or it wouldn't be held in place securely anymore.
The third ones are some buttons I found on Mouser. They are very nice, soft-click, silicone buttons, with the legs wrapped under them, so I wouldn't even have exposed solder joints visible, and with a pretty orange color. The main body s the same height as the display, not counting the flange. The problem is, they are rather expensive, and I haven't found another source of them.
So for the next prototype I decided to try to get back to the silicone buttons I used in #µGame. They are not clicky at all, but feel good enough. Their bodies are 4.5mm high, which is perfect for the 2.5mm height of the display plus 2mm of a cover. They only have two legs, so I save a little bit on soldering. And they are black, so they look good with any color.
So I switched for the new buttons, moved things around a bit to make it easier to laser-cut a sturdy inner layer, and ordered both the PCB and the laser-cutting at @Elecrow. The PCB looks something like this:
So the PCBs arrived again (a day earlier than expected, yay DHL), and this time with a correct footprint. So you know the drill. Disassemble the old one, move all the components to the new one. Connect to the programmer and... oh no, the dreaded "memory erase" message! But wait, after a few of those it says "connected", so maybe it works after all? Well, only one way to find out. I flash the bootloader from itsybitsy M4 express, and it showed as a USB drive! Great. So now flash the firmware and it should work! Hmm... it doesn't.
That's weird. A few experiments later I determined that it works perfectly fine when connected to the JLink, but not on its own. A quick test revealed the problem: I need a pull-up resistor on the reset pin. For now a quick bodge wire solved that, but I will need another version of the PCB. Oh well. I will need to move the display connector even further towards the center of the board, because the display is still sicking out a bit.
I will also experiment a bit with the capacitors, to see if I can have fewer of them and still have the device work reliably.