Espressif made breaking changes to ESP32 Arduino Core between v2.x and v3.x which cause compilation errors in this library. The first compiler error (but not the most serious one) is:
ESP_8_BIT_composite.cpp:45:55: error: invalid conversion from 'const volatile void*' to 'volatile void*' [-fpermissive]
I am tracking the problem as issue #56 in this repository. Current workaround is to downgrade Espressif ESP32 Arduino core to v2, this library was last verified to work with v2.0.14.
The composite video generation code from SEGA emulator of ESP_8_BIT extracted and packaged into a standalone Arduino library so everyone can write Arduino sketches that output a color composite video signal. NTSC and PAL are both supported.
Huge thanks to Peter Barrett / rossumur for ESP_8_BIT, without which this library would not have been possible.
For more behind-the-scenes information on how this library came to be, see the development diary which has all the details anyone would ever want plus even more that nobody ever asked for.
- 'Newer' ESP32 (see below)
- Composite video connector to ESP32 GPIO25 video signal pin.
- Display device with composite video input port. (Usually an old-school tube TV.)
ESP32 Details
This composite video generation code is an extremely clever hack that used several ESP32 peripherals in ways they were not originally designed for. See the original author's blog documentation for details. It also means older versions of ESP32 could not run this code. I don't know exactly which Espressif errata is relevant. [UPDATE: sysytwl believes it is 3.7 Audio PLL frequency range is limited.]
Here are some data points:
- Known to work
ESP32-D0WD (revision 1)
(mine)ESP32-D0WDQ6 (revision 1)
(thanks todbot)ESP32-PICO-D4 (revision 1)
(thanks alex1115alex)
- Known to NOT work
ESP32-D0WDQ6 (revision 0)
(thanks todbot)
Chip identification obtained from ESPTool
with the command esptool chip_id
Pushing hardware limits in this manner may restrict this library to a subset of the ESP32 family. This library was developed and tested against the original suffix-free ESP32. Compatiblity with variants (ESP32-S2, ESP32-S3, etc.) are untested and unknown.
- Adafruit GFX Library available from Arduino IDE Library Manager. (Last verified to work with v1.11.9)
- Espressif Arduino Core for ESP32, follow installation directions at that link. (Last verified to work with v2.0.14)
- (Optional) AnimatedGIF, for displaying animated GIF files. (Last verified to work with v1.4.7)
- Arduino IDE of course. (Last verified to work with v2.2.1)
Here's an Arduino IDE screenshot of my ESP32 configuration:
This library is NOT compatible with the "Arduino ESP32 Boards by Arduino" board library. (thanks JLBCS for #44) Compilation will fail with the following error:
ESP_8_BIT_composite.h:48:10: fatal error: driver/dac.h: No such file or directory
#include "driver/dac.h"
^~~~~~~~~~~~~~
This library can now be installed from within the Arduino desktop IDE via the Library Manager. Listed as "ESP_8_BIT Color Composite Video Library"
It can also be installed from this GitHub repository if desired:
- Download into a folder named "ESP_8_BIT_composite" under your Arduino IDE's
libraries
folder. - Restart Arduino IDE.
ESP_8_BIT_GFX
offers high-level drawing commands via the Adafruit GFX API. Easy to use, but not the highest performance.ESP_8_BIT_composite
exposes low-level frame buffer for those who prefer to manipulate bytes directly. Maximum performance, but not very easy to use.
GFX_HelloWorld
draws animated rectangles and text, both in changing colors, using the Adafruit GFX API exposed byESP_8_BIT_GFX
.RGB332_Colors
draws all 256 available colors directly to frame buffer allocated byESP_8_BIT_composite
. Draws once, no updates.RGB332_PulseB
draws 64 blocks of colors (8x8) representing different combinations of red (vertical axis) and green (horizontal axis). Uses the frame buffer ofESP_8_BIT_composite
directly. Every second, the entire screen is redrawn with one of four possible values of blue in a pulsing cycle.GFX_Screen_Fillers
demonstrates several of the common ways to put graphics on screen. Includes the following APIS:fillRect
,fillCircle
,drawFastVLine
, anddrawFastHLine
.AnimatedGIF
demonstrates how to use this video out library with the AnimatedGIF decoder library by Larry Bank. Art used in this example is Cat and Galactic Squid by Emily Velasco (CC BY-SA 4.0)GFX_RotatedText
demonstrates support for Adafruit_GFX::setRotation() by rendering text in one of four orientations and one of three text sizes.GFX_RotatedRect
demonstrates support for Adafruit_GFX::setRotation() by drawing four rectangles - one in each supported orientation - on every frame. Cycles through one of four animated pameters (X/Y/Width/Height) every second.
- Inherited from SEGA emulator of ESP_8_BIT, the addressible screen size is 256 pixels wide
and 240 pixels tall. This means valid X values of 0 to 255 inclusive, and
valid Y values of 0 to 239 inclusive.
- When displayed on a standard analog TV with 4:3 aspect ratio, these pixels
are not square. So
drawCircle()
will look like a squat wide oval on screen and not a perfect circle. This is inherent to the system and not considered a bug. - When displayed on a standard analog TV, the visible image will be slightly cropped due to overscan. This is inherent to analog televisions and not considered a bug.
- When displayed on a standard analog TV with 4:3 aspect ratio, these pixels
are not square. So
- The developer-friendly
ESP_8_BIT_GFX
class checks for valid coordinates and will only draw within the valid range. So if X is too large (say, 300)drawPixel()
will ignore the command and silently do nothing. - The raw
ESP_8_BIT_composite
class gives max performance power, but with great power comes great responsibility. Caller is responsible for making sure X and Y stay within bounds when manipulating frame buffer bytes viagetFrameBufferLines()[Y][X]
. Any bugs that use out of range array index may garble the image, or trigger a memory access violation and cause your ESP32 to reset, or other general memory corruption nastiness including the potential for security vulnerabilities.
Inherited from ESP_8_BIT is a fixed 8-bit color palette in RGB332 format. The underlying composite video out code always works with this set of colors. (See Examples.)
- The developer-friendly
ESP_8_BIT_GFX
class constructor can be initialized in either 8-bit (native) or 16-bit (compatibility) color mode.- Adafruit GFX was written for 16-bit color in
RGB565 format.
ESP_8_BIT_GFX
in 16-bit mode is compatible with existing Adafruit GFX code by automatically downconverting color while drawing. The resulting colors will be approximate, but they should closely resemble the original. Using RGB332 color values while in this mode will result in wrong colors on screen due to interpretation as RGB565 colors. - In 8-bit mode, color values given to GFX APIs will be treated as native 8-bit RGB332 values. This is faster because it skips the color conversion process. Using RGB565 color values while in this mode will result in wrong colors on screen due to the higher 8 bits being ignored.
- Adafruit GFX was written for 16-bit color in
RGB565 format.
- The raw
ESP_8_BIT_composite
class always works in 8-bit RGB332 color.
Sample colors in 8-bit RGB332 format:
Name | RGB332 (binary) | RGB332 (hexadecimal) |
---|---|---|
Black | 0b00000000 | 0x00 |
Blue | 0b00000011 | 0x03 |
Green | 0b00011100 | 0x1C |
Cyan | 0b00011111 | 0x1F |
Red | 0b11100000 | 0xE0 |
Magenta | 0b11100011 | 0xE3 |
Yellow | 0b11111100 | 0xFC |
White | 0b11111111 | 0xFF |
CLICK HERE for an interactive color picker web app. It shows all 256 possible 8-bit RGB332 colors in either a HSV (hue/saturation/value) color cylinder or a RGB (red/green/blue) color cube.
The intent of this library is to be easy to use, with minimum complexity for beginners. Advanced users are expected to fork this repository to add their desired features, or go to the source and fork ESP_8_BIT directly.
If this library is not a good fit for your project, please consider another library for ESP32 composite video:
- Bitluni's Lab: one of the earliest ESP32 composite video generators that informed development of many that followed.
- FabGL: This powerful graphics library didn't have composite video output when I started my project, but it has since been added. See the author's show-and-tell thread for details. The author has a Tektronix VM700 to ensure PAL video output signal is accurate.
- LovyanGFX: Another very nice graphics library that has preliminary composite video support in a development branch. I believe this library is unique in support for NTSC-J, and documentation is in both Japanese and English. (Code comments are in Japanese.)
Please post to discussions and see if anyone knows the answer. Note there's no guarantee of an answer.
Please open an issue to see if it can be fixed. Note there's no guarantee of support.
Just like its predecessor ESP_8_BIT, this project is shared freely with the world. Under the MIT license, you don't owe me anything.
But if you want to toss a few coins my way, you can do so by using my Amazon Associates link to buy your ESP32 development boards or composite video cables. You'll pay the same price, but I get a small percentage. As an Amazon Associate I earn from qualifying purchases.