基于FireBeetle 2 实现 VGA视频输出

之前有使用 FireBeetle(ESP32)实现过 VGA 输出,这次基于 FireBeetle 2 ESP32-S3 的板卡来实现 VGA 的输出。

首先进行电路的设计,其中的Hsync和Vsync分别使用 IO1 和 IO2,颜色则通过 R-2R 来实现:

PCB 设计如下:

3D预览如下:

图中的USB母头是预留给外部供电的,比如,VGA-HDMI转接器通常需要外部供电,这种情况下可以从这个端口取电。

焊接之后插入 FireBeetle 2 的板子(注意USB接口方向和 VGA接口方向相反):

接下来使用来自 https://github.com/spikepavel/ESP32-S3-VGA 的库

运行如下代码

#include "VGA.h"
#include <FONT_9x16.h>

VGA vga;

int scale = 2;

void setup()
{
//                   r,r,r,r,r,  g,g, g, g, g, g,   b, b, b, b, b,   h,v
const PinConfig pins(4,5,6,7,8,  9,10,11,12,13,14,  15,16,17,18,21,  1,2);
	Mode mode = Mode::MODE_640x480x60;
	
	if(!vga.init(pins, mode, 8, 3)) while(1) delay(1);
	
	vga.start();

	for(int y = 0; y < 480; y++)
		for(int x = 0; x < 640; x++)
			vga.dotdit(x, y, x, y, 255-x);

	vga.setFont(FONT_9x16);
	vga.start();
	
	delay(5000);
}

void loop() 
{
vga.clear(0);
delay(1000);
for(int count = 0; count < 100000; count++)
vga.dot(rand()%640, rand()%480, rand()%255);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 10000; count++)
vga.line(rand()%640, rand()%480, rand()%640, rand()%480, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 10000; count++)
vga.tri(rand()%640, rand()%480, rand()%640, rand()%480, rand()%640, rand()%480, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 1000; count++)
vga.fillTri(rand()%640, rand()%480, rand()%640, rand()%480, rand()%640, rand()%480, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 10000; count++)
vga.rect(rand()%640, rand()%480, rand()%640, rand()%480, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 1000; count++)
vga.fillRect(rand()%640, rand()%480, rand()%640, rand()%480, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 10000; count++)
vga.circle(rand()%640, rand()%480, rand()%100, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 5000; count++)
vga.fillCircle(rand()%640, rand()%480, rand()%50, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 10000; count++)
vga.ellipse(rand()%640, rand()%480, rand()%100, rand()%100, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 1000; count++)
vga.fillEllipse(rand()%640, rand()%480, rand()%100, rand()%100, rand()%255);
vga.clear(0);
delay(1000);

vga.clear(0);
delay(1000);
for(int count = 0; count < 100000; count++)
vga.mouse(rand()%640, rand()%480);
vga.clear(0);
delay(1000);

for(int count = 0; count < 1000; count++)
{
	static int c = 0;
	static int d = 1;
	c += d;
	if (c == 0 || c == 255)
		d = -d;

	char text[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 0, 0, 0, 0, 0
				  };
	
	for (int i = 0; i < 256; i++)
		text[i] = 33 + (i + (c >> 2));
	vga.setCursor(8, 48);
	vga.setTextColor(vga.rgb(c, 255 - c, 255), vga.rgb(0, c / 2, 127 - c / 2));
	vga.print(text);
	vga.setCursor(8, 148);
	vga.print(text);
	vga.setCursor(8, 248);
	vga.print(text);
	vga.setCursor(8, 348);
	vga.print(text);
}
 delay(4000);
}

实践测试发现,这个板卡在不同显示器上会有兼容性问题,可能和选择的分辨率及其参数有关系。

工作的测试视频【FireBeelte 2 ESP32-S3 VGA 输出测试】 https://www.bilibili.com/video/BV1yrzjY4EmG/?share_source=copy_web&vd_source=5ca375392c3dd819bfc37d4672cb6d54