Hackaday Badge Nyan Cat Bugs

I had a great time at 2018 Hackaday Superconference and I think Nyan Cat was a success as part of the conference badge. I’m happy with it, even though I found two minor problems with my Nyan Cat app during the weekend.

The first problem was that it does not tell the badge it is running, which is required to prevent automatic power-down. The auto-sleep feature was added after my code was merged into master, shortly before the badges started getting flashed en masse. I knew this power saving feature was going in but I was busy with badge production. So I didn’t have the chance to add code to keep the badge from going to sleep while Nyan Cat is running. My life was filled with rows and rows of badges.

Acrylic back installation

What this means is that Nyan Cat couldn’t just keep running on a badge forever. The badge will go to sleep and need to be awakened for animation to resume.

Somewhat related to the above, there’s a problem with timer synchronization upon wake. It appears that when the badge is asleep, the main timer still advances at some rate. I believe this is a side effect of loop_badge() in badge.c. Called by timer #5 every 15 milliseconds to check the status of the power button. During this check, the main system timer (running on timer #1) clicks upwards even though the rest of the badge is asleep.

What this means is that, if the badge is running Nyan Cat when it goes into low power mode, the timer will advance even though the animation & music does not. As a result, when the badge wakes up, the loops in charge of animation and timing will frantically try to catch up. It only takes a second or two to get back in sync, but in that brief moment we get a comically distorted kitty running and singing at warp speed.

This second problem can be reproduced by:

  1. Launch Nyan Cat with ‘nya’ to see and hear dancing singing pop tart cat.
  2. Push the power button to put the badge in low power mode.
  3. Wait about 30 seconds.
  4. Push the button again to wake up the badge.
  5. See and hear cat in hyperdrive for a few seconds before slowing down to normal speed.

I might go back and fix these bugs in the future, but they’re not horrendous embarrassments (and Nyan Cat in hyperdrive is pretty hilarious) so I’m content to leave them as-is for now.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat At Supercon

NyanCat Badge 1024w

In my pull request for Nyan Cat to go in the Hackaday Superconference 2018 badge, I included a way to launch it by typing ‘nya’ at the main menu. It existed mainly because I felt silly to create a pull request for a feature that was impossible to launch. This was originally intended to be a placeholder and be replaced by something else, but due to time crunch that “something else” never happened. So the final badge firmware flashed to every unit distributed to Supercon attendees had Nyan Cat launched via ‘nya’. It’s not the original intention, but also not the end of the world.

What this meant was that Nyan Cat badge app is now also an unplanned social experiment. By default only people who comb through badge firmware source code will find it. I didn’t think that would be enough, so on Friday I walked around telling people about it while the animation was playing on the badge around my neck. I think I told roughly one dozen people (some of them in groups) by the time Friday evening’s official kickoff party was done. Saturday morning at the official opening ceremony, I saw a person I didn’t recognize with Nyan Cat running on their badge. At that point I felt the knowledge seeding stage was complete, and it was time to let the word-of-mouth propagation take over.

One thing I thought was interesting: I had programmed a mute button to the app so it’s possible to play the animation without the music. Every time I told someone about Nyan Cat, I also mentioned ‘0’ would mute and ‘9’ would resume playback. However, as the weekend went on, I realized not everyone who knew about ‘nya’ knew about the mute button! It’s possible these people found out about ‘nya’ by reading the badge main menu source code (which launched the app) but not the app’s own source code (where the mute code lives.) It was also possible it got lost in the word-of-mouth propagation.

I knew there was a risk that people (including myself) would be annoyed at the music by the end of the weekend. But the sheer number of people packed in a small created a noisy enough environment that the music is actually a little difficult to hear over ambient noise. I didn’t encounter any complaints about it being a nuisance. Whew!

 

 

 

 

 

 

(Cross-posted to Hackaday.io)

Hackaday Badge: The Cat And The Hack

After all the work, my Nyan Cat is now running on an actual Supercon badge, running the default firmware which will be part of every 2018 Supercon badge. Woohoo!

NyanCat Badge 1024w

This specific unit of hardware actually has a minor assembly error: one of the battery trays is installed backwards. Here’s a picture of the back – both springs should be on the bottom, so both batteries have their positive end pointing up. The battery tray on the left is reversed from the way it should be.

Defective Badge Rear

The correct fix is to desolder the battery tray and solder it back on in the correct orientation. The simple hack is to jam a battery in there in the correct electrical orientation but against the tray orientation. Since this is a common mistake, the tray actually has a guard against reverse insertion. There’s a small plastic nub to prevent electrical contact if a battery is installed backwards. This nub allows the protruding positive end of AA battery to make contact, but keeps the flat negative end from making contact.

Nub Intact

Side note: When equipped with protective battery tray like this one, putting a battery in backwards is a valid way to stop battery power consumption, because it opens the circuit and no current will flow. However some people have gotten in the habit of reversing batteries to deactivate electronics with or without this nub. Without this nub, they risk cell voltage reversal and damaging the battery. It makes me wince to see it.

But back to the badge: since the correct battery orientation in this case is reverse of tray orientation, the expedient hack is to snip the nub away with some tools and insert the battery “backwards”.

It’s a hack and it works.

Nub Snipped

Hackaday Badge Nyan Cat Claws Back Final Bytes Before Wrapping Up

poptartcat320240There are just a few more touches before the finish line for getting my Nyan Cat project ready for consideration for the Hackaday Superconference 2018 badge. The final space savings came from realizing I only used two out of three voices in music playback, but my song structure carried three values so the unused voice takes up space holding zeroes. Maybe it’s only a few hundred bytes, but that’s still waste I could trim.

Once trimmed, I reviewed my code and realized I was still reading key-presses by reading the raw IO lines instead of using the existing stdio_get() API. This was a mistake made early on, when I thought it would block my animation/music until a key is pressed. Functionally speaking, neglecting to use the API not a terribly huge deal, but if I want the program to serve as example code it should do the right thing.

And finally, code comments. I want this to be something people can read through and understand how to write code for the badge in C using some techniques that are absent from other examples on the badge. This is an important part of the pitch for putting Nyan Cat on the badge – it should be educational in its construction in addition to being entertaining to launch.

After I committed the final code updates and comments, I realized I forgot to update the memory footprint listed by the flag to turn Nyan Cat on/off in a build. Final tally: 84 bytes of data memory, 8468 bytes of program memory. This is over the 8 kilobyte goal I was shooting for, but certainly a tremendous reduction from the original 30+ kilobytes.

I packaged my Nyan Cat into a pull request against the upstream depot, and it was accepted. Now my sample project will be a part of the default firmware on every Supercon badge.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat Sheds A Few More Bytes

poptartcat320240I built my Nyan Cat project on the Hackaday Belgrade 2018 badge. Now there’s a slim opening for it to be part of the Hackaday Superconference 2018 badge. The key is to get Nyan Cat skinny enough to fit through that door. Most of the 512 kilobytes of program storage on the badge’s PIC32MX370F512H chip have already been spoken for, leaving only about 16 kilobytes available. I set out to take up less than half of that space. I’m now just over 10 kilobytes, I need to trim another 2+ kilobytes.

The first task is to port the code from a fork of the Belgrade repo over to a fork of the Supercon repo. During this move, Nyan Cat code also migrated from being a customized user_program.c to its own nyancat.c source file in order to leave the default user program alone for badge hackers to play with. First I verified it still worked in the new repo – overweight and all – then I got to work trimming more data.

The key insight for more savings is realizing that we now store a quarter-scale image of 80×60 pixels and scale up at rendering time. Since they are encoded (and decoded) one scanline at a time, this means no single run length of pixels can be longer than 80. Previously, 12 bits were used to store length because a 320×240 image may have a run of 320 – longer than the maximum 8-bit value of 256. Now I only need 8 bits for run length. (The color palette always had only 14 colors, so it still needed only 4 bits.)

This trims every run in the image, color index + run length, from 16 bits down to 12. This did indeed trim data down to a little over 8.5 kilobytes. But code readability took a hit as a result: the smallest convenient unit in C is in multiple of 8 bits, so working with 12 bit values involve a lot of bit manipulation to pack and unpack that data.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat Needs A Diet

Now I’ve got Nyan Cat animation running while playing a simplified adaptation of the Nyan Cat music on my Hackaday Belgrade 2018 badge. I started writing run-length encoding on Friday, had a crash course in reading sheet music on Saturday, and by end of Sunday I had music and animation loop running together. This is roughly the same timespan that will be available to people putting their own projects on Hackaday Superconference 2018 badge, I just had the opportunity to do it a week ahead of time.

The original intent was twofold: One, to give myself some hands-on familiarity with the badge code base and two, have Nyan Cat project code available for other badge hackers as reference. I originally planned to have Nyan Cat up on Github for people to look at, but with this success my ambition grew: can this musical pop tart cat be part of the default badge firmware?

The greatest constraint on badge firmware is available space. Before I started this exploration, I hacked and slashed a bunch of features to make things lightweight, but if Nyan Cat is to be on the basic badge, it must coexist with all those features I had cut. And there isn’t enough free space for >30 kilobytes of Nyan Cat.

The majority of that space were consumed by run-length encoded animation frames, so that’s an obvious place to start. Code – both on encoding and decoding – most easily accommodates even power-of-two reductions. Nyan Cat is a blocky little kitty and should preserve well in downscaling from full resolution (320×240) to half (160×120), quarter (80×60), and eighth (40×30.) Here they are displayed in their pixel dimensions.

PoptartcatPixel

And here they are with pixels scaled up to fill a 320×240 screen, as it would on the badge.

PoptartcatScaled

There is visible degradation from full to half resolution, but not terrible. Nyan Cat starts getting pretty blocky at quarter resolution, but still recognizable. Eighth resolution is not usable.

So it looks like quarter scale is the sweet spot to target. This reduces the animation data from over 32 kilobytes to a little over 8 kilobytes. The music data and the program to bring it all together adds roughly another 2 kilobytes. It’s a good start but there is still room for improvement.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: Playing the Music And Animation

I found Nyan Cat song sheet music transcribed by a musescore.com contributer and translated it into scientific pitch notation used by the Hackaday Belgrade 2018 badge for use on its successor, the Hackaday Superconference 2018 badge. Now I have to figure out how to actually play it.

The first reference was the “play” button on musescore.com. When playing the song, the web page also highlights the current measure being played. This information may be obvious to experienced musicians, but super helpful to newcomers like myself trying to decipher sheet music. With this highlight tool, I could see which measures are played and the patterns in which they repeat to build the Nyan Cat song.

The second reference was the existing “mario” song on the badge, which showed one way to organize a song in code. Each measure is in its own array, and music playback consists of making calls to play measures in a particular sequence. I built on top of this idea and built another array nyancat_measures[] around them for convenient indexing. Then a separate array nyancat_sequence[] was created to track the order in which to play the measures. Playing the song would then be a matter of walking the sequence array in order and play each indexed measure as we go.

And finally – it’s time to put the sights and sounds together! The Nyan Cat badge app runs in a tight infinite loop checking the time via the millis() API. The video playback speed is controlled by one variable time_for_next_frame tracking the time for the next frame, and now music playback will be tracked with time_for_audio_update.

Is this perfect? No.

Unpacking and rendering a frame of animation takes a few tens of milliseconds. Occasionally this overlaps with a desired music start time, causing a note to end up playing a touch too long. The converse is also true – if music processing is underway at a desired animation frame time, there will be a brief animation glitch.

But it’s good enough for a badge hack.

NyanCatMusic-V

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: Reading the Music

The Hackaday Belgrade 2018 badge (and its successor, the Hackaday Superconference 2018 badge) has a simple audio system driving a speaker with up to three simultaneous tones. In order to give the Nyan Cat animation an appropriate soundtrack, I’d need to reduce its YouTube soundtrack to a few simple notes. Fortunately, people who are more knowledgeable about music have already done the work and shared them in sheet music format.

But there was a big problem: neither [amybaldwindev] or I knew how to read music.

We did what anyone would do in this day and age: search for “How to read sheet music” and read the first link. For the purpose of this specific project, I was not concerned with understanding the notes on the staff as I only needed to match them up against the reference chart on the badge music page. The duration of each note, however, proved more challenging. On several occasions we thought a note sounded wrong but it turned out just to be their duration

We started with a piano adaptation, but several attempts at translating it to badge music format failed to create something that sounded like Nyan Cat. Eventually we switched to this version – intended for violin – whose translated result running on the badge sounded like we were on the right track.

NyanCatMusic-V

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: Finding the Music

poptartcat320240I’m quite happy I got the Nyan Cat animation up and running on my Hackaday Belgrade 2018 badge, in preparation for putting it on my Hackaday Superconference 2018 badge. But the Nyan Cat experience is not complete without the catchy cutesy music. That music was an important reason for choosing Nyan Cat as the project.

Since Nyan Cat is an YouTube sensation, the obvious search for music information started with YouTube. Quite a few people have translated the music into piano and while a lot of notes go by very quickly, the simplified versions of Nyan Cat music seem to require no more than 2 keys at any given time.

This can be translated to fit on the badge, using two voices and one voice to spare. It leaves the door open to reuse the third audio timer for some other task.

It wouldn’t be hard to translate the piano keys from the YouTube video. Tedious, but not hard. Fortunately there are internet resources other than YouTube. A search turned up the web site musescore.com full of songs in sheet music format. Each of which was contributed by an user on the site and, given Nyan Cat’s internet fame, it was not a surprise that there were multiple takes on translating the catch tune into sheet music format.

This is an excellent place to start.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: Simplicity Pays Off

poptartcat320240I’m adapting the Nyan Cat animation to the Hackaday Belgrade 2018 badge (close predecessor to the Hackaday Superconference 2018 badge) and I chose to simplify the animated GIF data to a simple run-length encoding. RLE doesn’t compress as much as GIF, but it makes the decode algorithm simple. A simple algorithm takes up little program memory on the PIC32, and more importantly, it takes up less of my time coding and debugging. The latter is quite important when I’m trying to do something within the timeframe of a single weekend, as most Supercon badge hackers do.

The simplicity paid off when I wrote the code – just a few lines and only a few variables – and ran it on my Belgrade badge. The first test only decoded part of the first frame. I was actually quite surprised when the face of a cartoon cat looked back at me from the badge LCD! It is rare when a chunk of code works immediately on the first try.

After the first partial frame was proven to work, I extended the for() loop to the entire image, then I wrote an infinite loop to cycle through all 12 frames of the animation. I made the design decision for code simplicity and it paid off tremendously. Drastically reducing the time spent on implementation and (quite unexpectedly) completely eliminated the time spent on debugging.

If I had tried to port a GIF decode library I’m certain I would have needed to spend more time getting the code to compile and run on the badge, and it would not have been fun to debug if anything should go wrong.

This project’s progress is publicly visible on Github.

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: Run Length Encode Is Good Enough To Proceed

poptartcat320240At first glance, converting the Nyan Cat animated GIF to a run length encoded image doesn’t make a lot of sense: I’d need to decode the GIF at some point anyway, why go through the effort?

The key point is that the conversion process can be done on a desktop PC, with far more powerful and user-friendly tools. Yes, I could have done the work to port a GIF library to the PIC32 chip running the Hackaday Superconference 2018 badge, but on a desktop computer I could fire up Python, “from PIL import Image“, and be off and running manipulating a decoded GIF image sequence.

Once I got over the (small) hump of initial learning, it was easy to write a Python script to do everything I wanted to do to the image:

  1. Downscale from original 400×400 resolution to 320×320
  2. Crop off the top and bottom to obtain a 320×240 image
  3. Perform run-length encoding of resulting image.
  4. Output encoded bytes.

In step 4, the output comes in the form of text: specifically, C source code. Each encoded image is a static C array declaration that I could copy and paste into MPLAB X for storage into PIC32 program memory.

I had hoped the simple GIF would compress well with run length encoding, and the first results were quite promising: a little over 2 kilobytes for the first frame, and there are 12 frames in total implying the neighborhood of 24-28 kilobytes.

The original Nyan Cat GIF takes up 30 kilobytes. Granted, it is higher resolution and different aspect ratio, but this is going to make the PIC32 side programming far FAR easier. Which not only makes it easier for me to write, but also for others to read and understand in a little demo. I’m willing to trade a bit of space for those benefits.

(The Python script used for Nyan Cat encoding lives in this minimal Github repository.)

(Cross-posted to Hackaday.io)

Hackaday Badge Nyan Cat: GIF or Not?

With the decision to adapt Nyan Cat to the Hackaday Belgrade 2018 badge (as preparation for the Hackaday Superconference 2018 badge) it’s time to get down to some implementation details. Obviously we start with the cat – the original animated GIF is widely available. Can we use the file as-is?

poptartcat320240Looking at the GIF, it was drawn at 400×400 resolution. The badge LCD has a native resolution of 320×240, so the aspect ratio is wrong and the resolution is lower. In Photoshop I tried cropping the animation to see how that looked. I didn’t miss the cropped starry sky but I do miss the cropped rainbow trail. So let’s scale instead of crop.

The next question is: what file format? Do we stick with original GIF or something else? Raw bitmaps are out of the question. They would consume far too much valuable real estate on the badge. Rendering GIF would require porting a GIF decode library. When I was looking around for projects that decode GIF on a PIC32, I found the XORYA project which used libnsgif.

Looking over libnsgif dependencies, at first glance everything looks doable on the badge. This library was built to be part of the larger NetSurf project but it has abstraction layers that helps make badge adaptation easier. It looks like work, but a manageable amount of work.

But while it would be instructive to port an existing library for use, I lean towards doing something simpler to keep the demo approachable. So before I tackle the task of porting a GIF library, I wanted to evaluate run-length encoding. It is is the easiest compression algorithm available, making for code that is easy to read and understand. And this particular animation – with large horizontal streaks of the same color – seems ideally suited to the approach.

(Cross-posted to Hackaday.io)

Hackaday Badge Project: Nyan Cat

OK, enough probing and learning and experimenting with the Hackaday Belgrade 2018 badge, it’s about time I start writing something that I can put on its successor Hackaday Supercon 2018 badge. What to do?

For the purposes of a badge demo, it should explore areas of badge programming that aren’t already present in existing badge firmware. Because that’s what “demo” means – a demonstration.

I had been fascinated by the LCD module from the start, and the more I learn about it the more I feel it’s been under-utilized by existing badge code. In keeping with the retro computing theme, almost everything on the badge are text-based, leaving the graphics capabilities of the badge largely unused. The ideal project would flex those visual muscles.

Another point of novelty on the badge is the audio subsystem, consuming three of five timers, even more of the precious I/O pins on the chip, it’d be a shame to waste all those resources. I want to make it sing.

poptartcat320240So, what sights and sounds shall I present as a demonstration? A brainstorming session with [amybaldwindev] produced a list of candidates. The top candidate was Nyan Cat the famed YouTube star. Now, the badge won’t be able to play a YouTube video nor play its corresponding sound track. But the video’s source was a relatively simple animated GIF, and others have already done work to simplify the soundtrack.

Adapting an internet meme should make the result appealing to the Superconference audience. Making it an interesting technical demonstration project would almost end up being just a side bonus!

The only downside is that it doesn’t fit with the retro computing theme, but I can live with that.

(Cross-posted to Hackaday.io)

Hackaday Badge LCD Screen 4: Hunt for Speed Led To NES Project

Now that I have a better idea of programming against the LCD screen in the Hackaday Belgrade 2018 badge (similar to upcoming Hackaday Superconference 2018 badge) I went searching online for other people’s projects. The idea is that, with my newfound knowledge, I can better comprehend other projects.

Disappointingly, I wasn’t able to find many projects online, but the lack of quantity is made up by the quality of one extremely interesting project: someone tried to put a NES (Nintendo Entertainment System) emulator on the Belgrade badge. And a lot of the work went into increasing frame rate to be appropriate for Nintendo games.

My newfound knowledge turned out not to apply – the author has tore up major portions of the code base in order to fit in the arcade emulation layer. But reading the Github commits, I can tell that a major breakthrough was making use of a PIC32 feature called PMP (Parallel Master Port).

Microchip PIC32 PMP

Designed precisely to help interface with peripherals like a LCD screen, this peripheral can take over large data transfers (like sending data to a screen) without the CPU being directly involved as when running tft_fill_area() in disp.c. Looks like the performance advantage is twofold: first, PMP can update data and clock pins faster and more efficiently than doing it in CPU. And second, this frees up CPU to work on another task while PMP handles the transfer at the same time.

Further reading of work history indicated this person has also ran into screen tearing issues in the absence of VSYNC, and this problem was left to be solved later. And how did they create a buffer for PMP to transfer, when there isn’t enough for a full screen buffer? They didn’t use the full screen: the game only renders in a center rectangle subset of the screen.

I saw a burst of activity around Hackaday Belgrade in May, but activity stopped after June 4th. I’m inferring this has become an abandoned project.

Curious if I could take the project further, I cloned the repository, opened up the project in MPLAB X, and hit compile. And that’s when I found the final roadblock: as part of the hunt for performance, this person also changed code to require code optimization features of the paid version of PIC tools. I could not compile the project on my free tier.

Oh well, that was a fun detour, but I guess it’s time to get back to focusing on what I can actually use for Hackaday Superconference 2018.

Hackaday Badge LCD Screen 3: Establish Maximums

Examination of the LCD screen on the Hackaday Belgrade 2018 badge (predecessor to upcoming Hackaday Superconference 2018 badge) continues! Previous post highlighted some important tidbits from Reading The (Fine) Manual on components, now it’s time to get hands-on and get some experimental data. The default “user program” on the badge showcased a small bitmap operation that works one single pixel at a time. This is very inefficient and takes almost 2 seconds to fill the screen. I’m confident the badge can go faster, so let’s test how fast.

Maximum frame rate: ~80fps

Our tool for these tests is tft_fill_area() in disp.c. This function is used to fill a screen area with a single color, such as when clearing the screen. Looking at the code, we see it is sending 320 * 240 pixels of color data using a single fixed value. The fixed value means this is as fast as we’ll ever be able to fill the screen via existing interface configuration. Anything more complex will require computation that takes more time – and slower – than using a single fixed value.

A test program to cycle filling through all the RGB values shows that it takes about 3 seconds to traverse the 256 values of a single byte. 256 / 3 ~= 80 frames per second. Of course, frame rate for real tasks will be slower, but this isn’t bad at all and gives confidence it’ll be fine to stick with existing interface configuration. I’ve also confirmed visual artifacts from updating the screen so quickly without VSYNC. On a screen that’s supposed to be filled with a single color, we see diagonal rendering artifacts.

Hackaday Badge LCD Refresh Artifacts

Render-by-line frame rate: ~30fps

Since we don’t have enough memory for a full screen 32-bit buffer (and we don’t have VSYNC to make good use of it anyway) it’s time to scale down ambitions. Single pixel operations like the default demo program are too slow. So let’s go with a convenient middle ground between per-pixel and per-screen: operate at per-line level. A 32-bit buffer, for a single line of 320 pixels, would take only 1280 bytes (1.25 kilobyte). Well within our memory budget.

The test program will be doing a little bit of work, filling the line buffer with a pattern before sending the line to screen. It’ll also invoke the transmit overhead 240 times (once per line on screen) more than the single-screen operation, so I expected it to be slower. How much slower? It now takes about 8 seconds to run through 256 values of a single byte. 256 / 8 ~= 30 frames per second. This frame rate is more realistic, and still a decent speed for modest projects.

But some people will always push for faster. Has anyone applied that spirit of performance to the badge? Let’s look around the web…

 

 

Hackaday Badge LCD Screen 2: Documented Limitations

Now that I’ve completed my overview of the Hackaday Belgrade 2018 badge (which the upcoming Hackaday Superconference 2018 badge is very close to) it’s time to dig deeper. First topic for a deep dive: that LCD screen. In my earlier brief look, I only established that the screen is fully graphics capable and not restricted to text only. What kind of graphics can we do with this?

18-bit panel, accepts 24-bit color

First topic: color depth. The default badge firmware’s BASIC programming interface seems to allow only 16 colors which the documentation called “EGA colors”, see color_table[16] in disp.c. I was confident a modern LCD module has more than 4-bit color, and page 2 of the LCD module datasheet called itself a “262K color display.” That works out to 18 bits, so the panel native color depth is likely 6 bits red, 6 bits green, 6 bits blue. However, it is not limited to taking information in 18-bit color, the display can be configured to communicate at a wide range of bit depths. Looking in tft_fill_area() in disp.c, we can see the existing firmware is communicating in 24-bit color. 8 bits each for red, green, and blue.

Not enough memory for full 24-bit off-screen buffer

If we don’t want to change modes around on the fly, then, we’ll need to work with the panel in 24-bit color. Standard operating procedure is to draw using an off-screen buffer and, when the result is ready for display, send the buffer to screen in a single fast operation. A 24-bit off screen buffer is usually done with a 32-bit value representing each pixel with ARGB, even if we’re not using A(lpha) channel. 320 wide * 240 high * 32 bits = 300 kilobytes. Unfortunately, the datasheet for our PIC32 processor shows it only has a total of 128 kilobytes of memory, so the easy straightforward full screen buffer is out of the question. We’ll have to be more creative about this.

NHD-2.4-240320CF-CTXI LCD module wiring diagramNo VSYNC

But we wouldn’t have been able to make full use of an off screen buffer anyway. We need to send buffer data to screen at the right time. If we send while the screen is in the midst of drawing, there will be a visible tear as the old content is partially mixed with the new. The typical way to avoid this is to listen to a vertical synchronization signal (VSYNC) to know when to perform the update. And while the ST7789 controller on board the LCD module has provision to signal VSYNC, the LCD module does not expose VSYNC information. There may be some other way to avoid visual tearing, but it ain’t VSYNC.

These limitations, which are relatively typical of embedded electronics projects, are part of the fun of writing software for this class of hardware. Sure, it is a limitation, but it is also a challenge to be overcome, a puzzle to solve, and a change of pace from the luxury of desktop computers where such limitations are absent.

 

 

Hackaday Badge Firmware Diet

I now have a basic understanding of Hackaday Belgrade 2018 badge‘s internal subsystems and how they fit together. Now it’s time to start playing with the code. First to validate understanding before trying out some cool stuff.

When I’m in the early stages of experimentation and understanding, it’s good to make the try/learn/repeat loop as fast as possible. In the case of playing with badge firmware, flashing new builds of the firmware becomes the most time-consuming part of the loop. In order to speed up the fun I’m going to trim off parts of the project and make a lighter weight version of badge firmware.

My primary interest is in writing custom user programs in C. These programs utilize the same low-level infrastructure (font display, scan keyboard, etc) as the BASIC interpreter and Z80 emulator. Since I’m less interested in BASIC or Z80 at the moment, those are the biggest parts I can trim.

Begone, Z80

Begone, BASIC

I’m also trimming Tetris blocks-dropping game and the snake game. Not because they take up a great deal of room or time to compile, but just because they are well-defined chunks that I can easily remove.

Begone, snake

Begone, Tetris blocks.

Once the above parts have been trimmed, compile and build times dropped noticeably and flashing a new firmware now takes a fraction of the time.

I hadn’t set out to free up program space and memory, but they were happy side effects. Anyone working on user programs and feeling short on elbow room might consider doing what I did to free up space. Here’s what the MPLAB X dashboard shows for memory consumption after the trim:

Badge Firmware Trimmed

It is quite lean when compared against the default badge firmware:

Badge Firmware Full

If anyone else wants to look at my crude hack-and-slash job, it’s up on Github.

 

Hackaday Badge Expansion Header

The upper left corner of the Hackaday Belgrade 2018 badge is a series of standard 0.1″ pitch electric connection pins that serves as a portal to the world of hardware hacking projects. When the onboard peripherals aren’t enough, external accessories connect here.

Hackaday Badge Expansion Header

There’s also a less exotic use – the five pins on the left (RES / +V / GND / B0 / B1) serve as the firmware upgrade connection for the PIC32 processor. We connect a programmer (like the PICkit 3) to these five pins to reprogram the badge. But when the programmer is not connected, these pins can find secondary use in hardware hacks.

Hackaday Badge Expansion Header

The center pin RES(ET) goes to the hardware reset pin so that’s useful if we want to connect an external reset switch.

+V and GND is the voltage source and ground. With the pair of AAs present, these pins act as power sources for external components. If the AAs are absent, these pins can accept external power. Do note, though, that there’s no voltage regulation on the badge so +V/GND has to stay within the voltage range tolerated by badge components.

C13 and C14 are set up for serial communication. These are the most widely accessible of the expansion pins, usable from BASIC uin and uout, Z80 emulated CP/M machine via xmdem, and C user programs via rx_read and tx_write at the end of hw.c.

The remaining four pins are explicitly labeled as expansion pins 0 (G2), 1 (G3), 2 (B0), and 3 (B1). Accessible from BASIC with the edr / ein / eout commands and accessible from C user programs with exp_ddr / exp_get / exp_set functions in hw.c.

I see “I2C” written on top of G2 and G3, along with labels of SCL and SDA, but I have yet to find any actual I2C support infrastructure on the badge firmware. Maybe this is coming in later?

Also note that while G2 and G3 have minor protection in the form of a 220 ohm resistor, B0 and B1 are ‘naked’. Those expansion pins are connected directly to the corresponding PIC pins and officially must be free from external components when used for programming purposes. Typically this means they’re unused or disconnected from peripherals during programming, though there are ways to use them and still follow specifications. For example, they can be connected to a normally-open switch. As long as the switch doesn’t close during programming, everything should be fine.

Hackaday Badge Data Storage

The PIC32 chip at the heart of Hackaday Belgrade 2018 badge has a fixed program memory for storing machine code. There’s also a pool of random access memory for program data during execution. But what happens to user data? It wouldn’t belong in fixed code memory, and if it is kept in RAM it would be lost when the battery is removed.

The answer is a small block of nonvolatile memory that the user can read and write but would also maintain their data when the chip is shutdown or reset. It is a little chip with eight legs that sit to the right of the main PIC32 processor who has many more than eight legs.

Hackaday Badge Storage

A comment block in badge_settings.h outlines how this flash memory storage is allocated by the default badge firmware:

/*
* FLASH organization is as follows
* 0x000000-0x003FFF - first slot
* 0x004000-0x007FFF - second slot
* ...etc
* 0x03C000-0x03FFFF - 16-th slot
* 0x040000-0x07FFFF - empty space
* 0x080000-0x0FFFFF - D disk of CP/M machine
*/

The slots refer to BASIC program storage, where users can load from and save to up to sixteen BASIC programs, up to 16 kilobytes each. (BPROG_LEN) These 16 slots * 16 kilobytes takes up the first 256 kilobytes of flash memory. (0x00000-0x3FFFF) The second 256 kilobytes (0x040000-0x07FFFF) are unclaimed and available for custom user programs to use. The 512 kilobytes that follow (0x080000-0xFFFFF) is exposed as drive D: of the Z80 emulator running CP/M.

Custom user programs that wish to access that 256 kilobytes of unclaimed flash memory can access that space by referencing the code used to load and save BASIC programs. Flash memory can be read from, written to, and erased using the fl_* series of functions in hwz.c. See basic_save_program and basic_load_program in badge.c.

If a custom user program needs more than the available 256 kilobytes of flash memory, it’d have to take away from some one else… or does it? There’s one piece of mystery at hand. The memory allocation described above (256 kilobytes for BASIC, 256 kilobytes unclaimed, 512 kilobytes for CP/M drive D) add up to 1 megabyte. Is that all of flash storage?

Yes. No. Maybe.

Hackaday Badge StorageThe schematic and silkscreen on the Belgrade badge both name the flash chip as MX25V1635F. The datasheet for this chip indicates it has 2 megabyte capacity. However, the number actually printed on the chip is AT25DF081A, which is a 1 megabyte chip. The chip identity was confirmed by the badge Bill of Materials on Findchips.

But for the Hackaday Superconference badge, the flash chip is quoted to be a Microchip SST26VF016BT, which is a 2 megabyte chip. Maybe we’ll have a second megabyte of flash to play with at Supercon!

Hackaday Belgrade flash chip

Hackaday Badge Keyboard

The most visible physical feature of the Hackaday Belgrade 2018 badge, taking up most of the space on its circuit board, is an array of tiny little tactile clicky buttons making up a QWERTY keyboard. This is where badge hackers can type in BASIC programs and run them for an easy entry into this badge’s retrocomputing theme.

I’m no electronics expert, but I’ve seen enough circuit boards to recognize the convention for components to be lined up nicely in a grid. The keyboard buttons didn’t follow this pattern and sat at a slight angle. I had thought this was done just for aesthetics, standing apart from convention, but I was wrong. There was a functional goal at work: the slight angle allowed the button’s pins to be staggered and thus packed more closely together. Neat!

Hackaday Badge Keys

Electrically, most of the keys are laid out across a matrix of 10 columns and 5 rows. This allows the PIC32 chip to detect any single press of these 50 buttons using just 15 pins on the chip. The default firmware has a timer that fires regularly for household maintenance, and one of the tasks is to scan these pins for keyboard activity in function keyb_tasks in hw.c. Each timer slice checks one row on the keyboard, so it may take up to five time slices to scan the entire keyboard.

This is simple and efficient, but only works properly when one key at a time is pressed. When more than one key is pressed, the combination is ambiguous. For example, the following key combinations:

Hackaday Badge Keyboard Main

  • E + D
  • E + D + R
  • E + D + S
  • E + R + S
  • E + D + R + S

Would all light up the same four pins: B10, B11, B13, and B14 and there’s no way to tell them apart. This ambiguity will present a challenge for projects that require multiple simultaneous key presses. For example, some games require the user to press up and right simultaneously to command a movement to the upper right. Fortunately, this specific scenario is possible because the arrow keys are all on the same row, so a game that depends on arrow keys has to implement a custom variant of keyb_tasks that scan just pin F4’s row for one or more arrow keys. However, other typical sets of game directional keys (“WASD” and “IJKL”) could not be supported in the same way.

Hackaday Badge Keyboard Other

A few special keys on the keyboard have their own pins and read by other places in the firmware. The power button, break, and each of the two shift buttons have their own pin. The reset button is wired in series with the left shift key, so they both must be pressed to reset the badge. They do not share the D10 pin as the schematic might be interpreted to imply. A press of left shift + reset actually goes to MCLR pin, the PIC32 chip’s hardware reset guaranteeing that reset always works regardless of any potential firmware bugs.