[原创] 【ST多款开发板返场测评】STM32F767 Nucleo-144 基于UVC的FRAMEBUFFER-艺术图片

qinyunti   2023-11-1 15:56 楼主

前言

前面我们实现了NV12格式的UVC显示,基于此我们可以实现framebuffer机制,实现任意点的颜色的读写,然后移植LVGL进行GUI开发。由于使用YUV格式需要格式转换,且需要根据采样进行插值,直接修改某点的颜色不方便,所以我们使用RGB格式,为了减少缓存大小使用RGB565格式。

 

YUV-RGB565-FRAMEBUFFER

usbd_video.c修改描述符的GUID为

DBVAL(0xe436eb7b),

WBVAL(0x524f),

WBVAL(0x11ce),

0x9f,0x53,

0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70,

  UVC_BITS_PER_PIXEL,                            /* bBitsPerPixel : Number of bits per pixel  16*/

image-20231101155414-1.png  

 

usbd_video_if_template.c修改大小

extern uint8_t s_framebuffer[H_SIZE*V_SIZE*2];

const  uint8_t *tImagesList[] = {s_framebuffer};

uint32_t tImagesSizes[] = {H_SIZE*V_SIZE*2};

 

framebuffer.c中实现framebuffer,其中framebuffer_update测试用RGB轮显

#include <stdint.h>

#include "stm32f7xx_hal.h"

#include "encode_dma.h"

#include "framebuffer.h"



uint8_t s_framebuffer[H_SIZE*V_SIZE*2];



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[0]))

    {

        index = 0;

    }

    r = (color_table[index] >> 16) & 0xFF;

    g = (color_table[index] >> 8) & 0xFF;

    b = (color_table[index] >> 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++;

}

艺术图片测试

基于任意的写点函数,通过一些数学公式产生有意思的图片。

cef7b98c9913ef215c895182fa17527.jpg  

ec3524505ad27d0bf1c4cfc9f6bbd18.jpg  

代码如下

#include <stdint.h>
#include "stm32f7xx_hal.h"
#include "encode_dma.h"
#include "framebuffer.h"
#include <math.h>

uint8_t s_framebuffer[H_SIZE*V_SIZE*2];


#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[DIM][DIM]; return!c[i][j] ? c[i][j] = !r(999) ? r(256) : RD((i + r(2)) % 1024, (j + r(2)) % 1024) : c[i][j];
}

unsigned char GR1(int i, int j) {
    static char c[DIM][DIM]; return!c[i][j] ? c[i][j] = !r(999) ? r(256) : GR((i + r(2)) % 1024, (j + r(2)) % 1024) : c[i][j];
}

unsigned char BL1(int i, int j) {
    static char c[DIM][DIM]; return!c[i][j] ? c[i][j] = !r(999) ? r(256) : BL((i + r(2)) % 1024, (j + r(2)) % 1024) : c[i][j];
}

 
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[DIM]; int p = rand() % 9 - 4; r[i] = i & r[i] ? (r[i] + r[i - 1]) / 2 : i ? r[i - 1] : 512; r[i] += r[i] + p > 0 ? p : 0; return r[i] ? r[i] < DIM ? r[i] : DM1 : 0;
}

unsigned char GR4(int i, int j) {
    static int r[DIM]; int p = rand() % 7 - 3; r[i] = i & r[i] ? (r[i] + r[i - 1]) / 2 : i ? r[i - 1] : 512; r[i] += r[i] + p > 0 ? p : 0; return r[i] ? r[i] < DIM ? r[i] : DM1 : 0;
}

unsigned char BL4(int i, int j) {
    static int r[DIM]; int p = rand() % 15 - 7; r[i] = i & r[i] ? (r[i] + r[i - 1]) / 2 : i ? r[i - 1] : 512; r[i] += r[i] + p > 0 ? p : 0; return r[i] ? r[i] < DIM ? r[i] : 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[3];
			color[0] = RD(i,j)&255;
			color[1] = GR(i,j)&255;
			color[2] = BL(i,j)&255;
			framebuffer_set(i, j, color[0], color[1], color[2]);
		}
	}
}

void test1(void)
{
	for(int i=0;i<H_SIZE;i++)
	{
		for(int j=0;j<V_SIZE;j++)
		{
			static unsigned short color[3];
			color[0] = RD1(i,j)&255;
			color[1] = GR1(i,j)&255;
			color[2] = BL1(i,j)&255;
			framebuffer_set(i, j, color[0], color[1], color[2]);
		}
	}
}

void test2(void)
{
	for(int i=0;i<H_SIZE;i++)
	{
		for(int j=0;j<V_SIZE;j++)
		{
			static unsigned short color[3];
			color[0] = RD2(i,j)&255;
			color[1] = GR2(i,j)&255;
			color[2] = BL2(i,j)&255;
			framebuffer_set(i, j, color[0], color[1], color[2]);
		}
	}
}

void test3(void)
{
	for(int i=0;i<H_SIZE;i++)
	{
		for(int j=0;j<V_SIZE;j++)
		{
			static unsigned short color[3];
			color[0] = RD3(i,j)&255;
			color[1] = GR3(i,j)&255;
			color[2] = BL3(i,j)&255;
			framebuffer_set(i, j, color[0], color[1], color[2]);
		}
	}
}

void test4(void)
{
	for(int i=0;i<H_SIZE;i++)
	{
		for(int j=0;j<V_SIZE;j++)
		{
			static unsigned short color[3];
			color[0] = RD4(i,j)&255;
			color[1] = GR4(i,j)&255;
			color[2] = BL4(i,j)&255;
			framebuffer_set(i, j, color[0], color[1], color[2]);
		}
	}
}


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[0]))
    {
        index = 0;
    }
    r = (color_table[index] >> 16) & 0xFF;
    g = (color_table[index] >> 8) & 0xFF;
    b = (color_table[index] >> 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[0]))
    {
        index = 0;
    }
		pf_table[2]();
		//pf_table[index]();
		index++;
#endif
}


总结

以上实现了基于UVC的FRAMEBUFFER可以进行任意写点,并进行了有意思的艺术图片生成测试。

本帖最后由 qinyunti 于 2023-11-1 22:03 编辑

回复评论 (2)

有意思,过来看看
点赞  2023-11-1 16:49

牛逼!

点赞  2023-11-1 17:34
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复