验证RA8875的硬件绘图与使用MCU软件绘图的速度差异

RA8875是一块LCD驱动芯片,支持RGB接口的LCD液晶屏,提供8080时序的MCU接口; RA8875内置了2D硬件加速功能,可以实现硬件绘制矩形,直线等功能;

本次测试就是为了验证RA8875的硬件绘图与使用MCU软件绘图的速度差异。

硬件环境:

CPU:STM32F407VE@168MHz

LCD:480x272x16bpp

测试方法:

计算1秒内填充整个屏幕的次数(FPS)

测试结果:

填充方式 帧率(FPS) 速度(Pixel/s) 备注
软件逐点填充 6 783360
软件逐行填充 63 8225280
软件矩形填充 69 9008640
硬件逐行填充1 201 26242560 先绘图,等待空闲后退出函数
硬件逐行填充2 207 27025920 进入函数先等待空闲,再绘图
硬件矩形填充1 312 40734720 先绘图
硬件矩形填充2 315 41126400 先等待
emWin(5.30) 126 16441000 自带驱动,支持硬件加速
FastGUI 201 26242560 驱动为硬件逐行填充2
FlatGUI 324 42301440

说明:RA8875的硬件绘制功能,需要读取状态寄存器的BIT7,

如果该位为1说明硬件绘制没有完成,不能进行其它绘制,否则屏幕会显示不正常。

“先绘图”是指先发送硬件绘图指令,然后读取状态寄存器,等待BIT7清0后退出函数;

“先等待”是指先读取状态寄存器,等待BIT7清0后,再发送绘图指令;

测试结论:

由此可见使用RA8875的硬件绘图有着非常明显的速度优势,比使用软件绘图快了3-4倍。

附上RA8875的2D加速代码:

static void lcd_set_rect(int x1, int y1, int x2, int y2)
{
    //窗口起始位置
    lcd_command(0x30, x1);
    lcd_command(0x31, (x1 >> 8) & 0x3);
    lcd_command(0x32, y1);
    lcd_command(0x33, (y1 >> 8) & 0x01);

    //窗口结束位置
    lcd_command(0x34, x2);
    lcd_command(0x35, (x2 >> 8) & 0x03);
    lcd_command(0x36, y2);
    lcd_command(0x37, (y2 >> 8) & 0x01);
}

static void lcd_wseek(int x, int y)
{
    lcd_command(0x46, x);
    lcd_command(0x47, x >> 8);

    lcd_command(0x48, y);
    lcd_command(0x49, y >> 8);
}

static void lcd_rseek(int x, int y)
{
    lcd_command(0x4A, x);
    lcd_command(0x4B, x >> 8);

    lcd_command(0x4C, y);
    lcd_command(0x4D, y >> 8);
}

void lcd_set_pixel(int x, int y, int pixel)
{
    lcd_wait_ram();
    lcd_wseek(x, y);
    lcd_command(0x02, pixel);
}

int lcd_get_pixel(int x, int y)
{
    int data;
    lcd_rseek(x, y);
    LCD_CMD = 0x02;
    data = LCD_DATA;  //dummy read
    data = LCD_DATA;
    return data;
}

//BTE
static void bte_set_rect(int x, int y, int w, int h)
{
    lcd_command(0x58, x);
    lcd_command(0x59, (x >> 8) & 0x03);
    lcd_command(0x5A, y);
    lcd_command(0x5B, (y >> 8) & 0x01);

    lcd_command(0x5C, w);
    lcd_command(0x5D, (w >> 8) & 0x03);
    lcd_command(0x5E, h);
    lcd_command(0x5F, (h >> 8) & 0x03);
}

static void bte_set_bkcolor(int color)
{
    lcd_command(0x60, (color >> 11) & 0x1F);
    lcd_command(0x61, (color >> 5) & 0x3F);
    lcd_command(0x62, color & 0x1F);
}

static void bte_set_fgcolor(int color)
{
    lcd_command(0x63, (color >> 11) & 0x1F);
    lcd_command(0x64, (color >> 5) & 0x3F);
    lcd_command(0x65, color & 0x1F);
}

static void bte_set_colorkey(int color)
{
    lcd_command(0x67, (color >> 11) & 0x1F);
    lcd_command(0x68, (color >> 5) & 0x3F);
    lcd_command(0x69, color & 0x1F);
}

static void bte_open(int mode)
{
    lcd_command(0x51, lcd_rop_mask | mode);
    lcd_command(0x50, 0x80);
}

static void g2d_set_rect(int x, int y, int x2, int y2)
{
    lcd_command(0x91, x&0xFF);
    lcd_command(0x92, (x>>8)&0xFF);
    lcd_command(0x93, y&0xFF);
    lcd_command(0x94, (y>>8)&0xFF);
    
    lcd_command(0x95, x2&0xFF);
    lcd_command(0x96, (x2>>8)&0xFF);
    lcd_command(0x97, y2&0xFF);
    lcd_command(0x98, (y2>>8)&0xFF);
}

static void g2d_command(uint8_t cmd)
{
    lcd_command(0x90, cmd);
}

void lcd_set_rop(int mode)
{
    lcd_rop_mask = (mode & 0x0F) << 4;
}

void bte_fill_rect(int x, int y, int w, int h, int color)
{
    lcd_wait_bte();
    bte_set_rect(x, y, w, h);
    bte_set_fgcolor(color);
    bte_open(0x0C);
}

void g2d_fill_rect(int x, int y, int x2, int y2, int color)
{
    lcd_wait_ram();
    bte_set_fgcolor(color);
    g2d_set_rect(x, y, x2, y2);
    g2d_command(0xB0);
}