Screen Rotation Support for ESP_8_BIT_Composite Arduino Library
I've had my head buried in modern LED-illuminated digital panels, so it was a good change of pace to switch gears to old school CRTs for a bit. Several months have passed since I added animated GIF support to my ESP_8_BIT_Composite video out Arduino library for ESP32 microcontrollers. I opened up the discussion forum option for my GitHub repository and a few items have been raised, sadly I haven't been able to fulfill the requests ranging from NTSC-J support (I don't have a corresponding TV) to higher resolutions (I don't know how). But one has just dropped in my lap, and it was something I can do.
Issue #21 was a request for the library to implement Adafruit GFX capability to rotate display orientation. When I first looked at rotation, I had naively thought Adafruit GFX would handle that above drawPixel()
level and I won't need to write any logic for it. This turned out to be wrong: my code was expected to check rotation and alter coordinate space accordingly. I looked at the big CRT TV I had sitting on my workbench and decided I wasn't going to sit that beast on its side, and then promptly forgot about it until now. Whoops.
Looking into Adafruit's generic implementation of drawPixel()
, I saw a code fragment that I could copy:
int16_t t;
switch (rotation) {
case 1:
t = x;
x = WIDTH - 1 - y;
y = t;
break;
case 2:
x = WIDTH - 1 - x;
y = HEIGHT - 1 - y;
break;
case 3:
t = x;
x = y;
y = HEIGHT - 1 - t;
break;
}
Putting this into my own drawPixel()
was a pretty straightforward way to handle rotated orientations. But I had overridden several other methods for the sake of performance, and they needed to be adapted as well. I had drawFastVLine
, drawFastHLine
, and fillRect
, each optimized for their specific scenario with minimal overhead. But now the meaning of a vertical or horizontal line has become ambiguous.
Looking over at what it would take to generalize the vertical or horizontal line drawing code, I realized they have become much like fillRect()
. So instead of three different functions, I only need to make fillRect()
rotation aware. Then my "fast vertical line" routine can call into fillRect()
with a width of one, and similarly my "fast horizontal line" routine calls into fillRect()
with a height of one. This invokes some extra computing overhead relative to before, but now the library is rotation aware and I have less code to maintain. A tradeoff I'm willing to make.
While testing behavior of this new code, I found that Adafruit GFX library uses different calls when rendering text. Text size of one uses drawPixel()
for single-pixel manipulation. For text sizes larger than one, they switch to using fillRect()
to draw more of the screen at a time. I wrote a program to print text at all four orientations, each at three different sizes, to exercise both code paths. It has been added to the collection of code examples as GFX_RotatedText
.
Satisfied that my library now supports screen rotation, I published it as version 1.3.0. But that turned out to be incomplete, as I neglected to update the file library.properties
.