737 FMC CDU – Snappier Display Updates
I spent the last long weekend rewriting the FMC CDU display code in C++ and SDL2 … redrawing time is much more snappy than before (https://www.youtube.com/watch?v=i1mQiPr0KUI). For someone coming from an age where PCs had 40×25 screens, you would think that placing characters at fixed positions on the screen is trivial … but these days almost all user interface libraries are design the handle fonts of different heights, and variable widths and kerning, so simple things become harder.
My first attempt was in Java and I created a label at every character position, so I could update them easily by just writing a single character into each label. That was too much for the Pi to handle and gave that “matrix” effect whenever the screen changed a lot.
The SDL2 library supposedly can make use of hardware acceleration on the Pi, but you have to work by its terms, i.e. working with “textures” and “rendering” them to the screen. I pre-generated each character of the font in tall and short sizes as a “texture”, and whenever a line of the display changed, I would just render the character textures at the appropriate positions.
It worked on the PC but not on the Pi. Turns out once you’ve rendered stuff to the screen, there’s no guarantee that what was drawn before will remain on the screen the next time you render stuff. On the PC the stuff remained, but on the Pi only the new stuff I rendered appeared but with everything else disappearing. Not an issue for most games as most objects on the screen have moved around anyway, so they regenerate the entire screen.
To fix this, I created a larger texture as a “buffer” for the entire screen. Now when a line changes, I render the character textures into the buffer texture, and then render the entire buffer to the screen.
Strangely the Pi still struggled with this. It turns out that because I was receiving updates from the server in terms of “lines”, whenever the whole screen changed, I was repainting the entire screen 14 times, and you could see changing of one line at a time as a flicker.
Finally settled on this solution: when a new line change comes in, render those characters to the buffer texture, but don’t update the screen immediately. Instead, wait until there have been no more changes for 10 milliseconds, and then render the buffer texture to the screen once. This way whenever the entire screen changed, it would just redraw the new screen once.
The results turned out well … and I now have a lot of repect for game developers.
Next up is to write code to scan the keypad for presses and transmit those to the flight simulator.
Originally created with EverNote at 20170505T035601Z