【ST多款开发板返场测评】STM32F767 Nucleo-144 基于UVC的FRAMEBUFFER-艺术图片
<div class='showpostmsg'> 本帖最后由 qinyunti 于 2023-11-1 22:03 编辑<h1><b>前言</b></h1>
<p>前面我们实现了NV12格式的UVC显示,基于此我们可以实现framebuffer机制,实现任意点的颜色的读写,然后移植LVGL进行GUI开发。由于使用YUV格式需要格式转换,且需要根据采样进行插值,直接修改某点的颜色不方便,所以我们使用RGB格式,为了减少缓存大小使用RGB565格式。</p>
<p> </p>
<h1><b>YUV-RGB565-FRAMEBUFFER</b></h1>
<p>usbd_video.c修改描述符的GUID为</p>
<p>DBVAL(0xe436eb7b),</p>
<p>WBVAL(0x524f),</p>
<p>WBVAL(0x11ce),</p>
<p>0x9f,0x53,</p>
<p>0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70,</p>
<p> UVC_BITS_PER_PIXEL, /* bBitsPerPixel : Number of bits per pixel 16*/</p>
<p> </p>
<p> </p>
<p>usbd_video_if_template.c修改大小</p>
<p>extern uint8_t s_framebuffer;</p>
<p>const uint8_t *tImagesList[] = {s_framebuffer};</p>
<p>uint32_t tImagesSizes[] = {H_SIZE*V_SIZE*2};</p>
<p> </p>
<p>framebuffer.c中实现framebuffer,其中framebuffer_update测试用RGB轮显</p>
<pre>
<code class="language-cpp">#include <stdint.h>
#include "stm32f7xx_hal.h"
#include "encode_dma.h"
#include "framebuffer.h"
uint8_t s_framebuffer;
uint32_t color_table[] =
{
0xFF0000, /* */
0x00FF00, /* */
0x0000FF, /* */
};
void framebuffer_set(uint32_t xpos, uint32_t ypos, uint8_t r, uint8_t g, uint8_t b)
{
uint16_t color = (((uint16_t)r&0xF8)<<8) | (((uint16_t)g&0xFC)<<3) | (((uint16_t)b&0xF8)>>3);
uint8_t* p = s_framebuffer + (xpos*H_SIZE+ypos)*2;
*(uint16_t*)p = color;
}
void framebuffer_init(void)
{
}
void framebuffer_update(void)
{
static unsigned int index = 0;
uint8_t* p = (uint8_t*)s_framebuffer;
uint8_t r;
uint8_t g;
uint8_t b;
if(index >= sizeof(color_table)/sizeof(color_table))
{
index = 0;
}
r = (color_table >> 16) & 0xFF;
g = (color_table >> 8) & 0xFF;
b = (color_table >> 0) & 0xFF;
for(int x=0; x<H_SIZE; x++)
{
for(int y=0; y<V_SIZE; y++)
{
framebuffer_set(x, y, r, g, b);
}
}
index++;
}</code></pre>
<h1><b>艺术图片测试</b></h1>
<p>基于任意的写点函数,通过一些数学公式产生有意思的图片。</p>
<p> </p>
<p> </p>
<p>代码如下</p>
<pre>
<code class="language-cpp">#include <stdint.h>
#include "stm32f7xx_hal.h"
#include "encode_dma.h"
#include "framebuffer.h"
#include <math.h>
uint8_t s_framebuffer;
#define DIM H_SIZE
#define DM1 (DIM-1)
#define _sq(x) ((x)*(x))
#define _cb(x) abs((x)*(x)*(x))
#define _cr(x) (unsigned short)(pow((x),1.0/3.0))
unsigned char RD(int i,int j){
return (char)(_sq(cos(atan2(j-65,i-65)/2))*255);
}
unsigned char GR(int i,int j){
return (char)(_sq(cos(atan2(j-65,i-65)/2-2*acos(-1)/3))*255);
}
unsigned char BL(int i,int j){
return (char)(_sq(cos(atan2(j-65,i-65)/2+2*acos(-1)/3))*255);
}
unsigned char RD0(int i,int j)
{
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return ((int)((i+DIM)*s+y)%2+(int)((DIM*2-i)*s+y)%2)*127;
}
unsigned char GR0(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return ((int)(5*((i+DIM)*s+y))%2+(int)(5*((DIM*2-i)*s+y))%2)*127;
}
unsigned char BL0(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return ((int)(29*((i+DIM)*s+y))%2+(int)(29*((DIM*2-i)*s+y))%2)*127;
}
unsigned char RD1(int i, int j) {
#define r(n)(rand()%n)
static char c; return!c ? c = !r(999) ? r(256) : RD((i + r(2)) % 1024, (j + r(2)) % 1024) : c;
}
unsigned char GR1(int i, int j) {
static char c; return!c ? c = !r(999) ? r(256) : GR((i + r(2)) % 1024, (j + r(2)) % 1024) : c;
}
unsigned char BL1(int i, int j) {
static char c; return!c ? c = !r(999) ? r(256) : BL((i + r(2)) % 1024, (j + r(2)) % 1024) : c;
}
unsigned char RD2(int i, int j) {
static double k; k += rand() / 1. / 0x7FFF; int l = k; l %= 512; return l > 255 ? 511 - l : l;
}
unsigned char GR2(int i, int j) {
static double k; k += rand() / 1. / 0x7FFF; int l = k; l %= 512; return l > 255 ? 511 - l : l;
}
unsigned char BL2(int i, int j) {
static double k; k += rand() / 1. / 0x7FFF; int l = k; l %= 512; return l > 255 ? 511 - l : l;
}
unsigned char RD3(int i, int j) {
return (unsigned char)sqrt((double)(_sq(i - DIM / 2) * _sq(j - DIM / 2)) * 2.0);
}
unsigned char GR3(int i, int j) {
return (unsigned char)sqrt((double)(
(_sq(i - DIM / 2) | _sq(j - DIM / 2)) *
(_sq(i - DIM / 2) & _sq(j - DIM / 2))
));
}
unsigned char BL3(int i, int j) {
return (unsigned char)sqrt((double)(_sq(i - DIM / 2) & _sq(j - DIM / 2)) * 2.0);
}
unsigned char RD4(int i, int j) {
static int r; int p = rand() % 9 - 4; r = i & r ? (r + r) / 2 : i ? r : 512; r += r + p > 0 ? p : 0; return r ? r < DIM ? r : DM1 : 0;
}
unsigned char GR4(int i, int j) {
static int r; int p = rand() % 7 - 3; r = i & r ? (r + r) / 2 : i ? r : 512; r += r + p > 0 ? p : 0; return r ? r < DIM ? r : DM1 : 0;
}
unsigned char BL4(int i, int j) {
static int r; int p = rand() % 15 - 7; r = i & r ? (r + r) / 2 : i ? r : 512; r += r + p > 0 ? p : 0; return r ? r < DIM ? r : DM1 : 0;
}
void test0(void)
{
for(int i=0;i<H_SIZE;i++)
{
for(int j=0;j<V_SIZE;j++)
{
static unsigned short color;
color = RD(i,j)&255;
color = GR(i,j)&255;
color = BL(i,j)&255;
framebuffer_set(i, j, color, color, color);
}
}
}
void test1(void)
{
for(int i=0;i<H_SIZE;i++)
{
for(int j=0;j<V_SIZE;j++)
{
static unsigned short color;
color = RD1(i,j)&255;
color = GR1(i,j)&255;
color = BL1(i,j)&255;
framebuffer_set(i, j, color, color, color);
}
}
}
void test2(void)
{
for(int i=0;i<H_SIZE;i++)
{
for(int j=0;j<V_SIZE;j++)
{
static unsigned short color;
color = RD2(i,j)&255;
color = GR2(i,j)&255;
color = BL2(i,j)&255;
framebuffer_set(i, j, color, color, color);
}
}
}
void test3(void)
{
for(int i=0;i<H_SIZE;i++)
{
for(int j=0;j<V_SIZE;j++)
{
static unsigned short color;
color = RD3(i,j)&255;
color = GR3(i,j)&255;
color = BL3(i,j)&255;
framebuffer_set(i, j, color, color, color);
}
}
}
void test4(void)
{
for(int i=0;i<H_SIZE;i++)
{
for(int j=0;j<V_SIZE;j++)
{
static unsigned short color;
color = RD4(i,j)&255;
color = GR4(i,j)&255;
color = BL4(i,j)&255;
framebuffer_set(i, j, color, color, color);
}
}
}
uint32_t color_table[] =
{
0xFF0000,/**/
0x00FF00,/**/
0x0000FF,/**/
};
typedef void (*test_pf)(void);
test_pf pf_table[] =
{
test0,/**/
test1,/**/
test2,/**/
test3,/**/
test4,/**/
};
void framebuffer_set(uint32_t xpos, uint32_t ypos, uint8_t r, uint8_t g, uint8_t b)
{
uint16_t color = (((uint16_t)r&0xF8)<<8) | (((uint16_t)g&0xFC)<<3) | (((uint16_t)b&0xF8)>>3);
uint8_t* p = s_framebuffer + (xpos*H_SIZE+ypos)*2;
*(uint16_t*)p = color;
}
void framebuffer_init(void)
{
}
void framebuffer_update(void)
{
#if 0
static unsigned int index = 0;
uint8_t* p = (uint8_t*)s_framebuffer;
uint8_t r;
uint8_t g;
uint8_t b;
if(index >= sizeof(color_table)/sizeof(color_table))
{
index = 0;
}
r = (color_table >> 16) & 0xFF;
g = (color_table >> 8) & 0xFF;
b = (color_table >> 0) & 0xFF;
for(int x=0; x<H_SIZE; x++)
{
for(int y=0; y<V_SIZE; y++)
{
framebuffer_set(x, y, r, g, b);
}
}
index++;
#else
static unsigned int index = 0;
if(index >= sizeof(pf_table)/sizeof(pf_table))
{
index = 0;
}
pf_table();
//pf_table();
index++;
#endif
}
</code></pre>
<h1><b>总结</b></h1>
<p>以上实现了基于UVC的FRAMEBUFFER可以进行任意写点,并进行了有意思的艺术图片生成测试。</p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> 有意思,过来看看 <p>牛逼!</p>
<p><img height="59" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan061.gif" width="67" /></p>
页:
[1]