811 views|2 replies

501

Posts

4

Resources
The OP
 

[ST multiple development boards return to the field evaluation] STM32F767 Nucleo-144 UVC-based FRAMEBUFFER-artistic pictures [Copy link]

This post was last edited by qinyunti on 2023-11-1 22:03

Preface

Previously, we implemented UVC display in NV12 format. Based on this, we can implement the framebuffer mechanism, read and write the color of any point, and then transplant LVGL for GUI development. Since the use of YUV format requires format conversion and interpolation based on sampling, it is inconvenient to directly modify the color of a point, so we use RGB format, and use RGB565 format to reduce the cache size.

YUV-RGB565-FRAMEBUFFER

usbd_video.c modifies the descriptor GUID to

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*/

usbd_video_if_template.c modify size

extern uint8_t s_framebuffer[H_SIZE*V_SIZE*2];

const uint8_t *tImagesList[] = {s_framebuffer};

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

The framebuffer is implemented in framebuffer.c, where the framebuffer_update test uses RGB wheel display

#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++;

}

Art picture test

Based on arbitrary write point functions, interesting pictures are generated through some mathematical formulas.

code show as below

#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
}


Summarize

The above implementation of UVC-based FRAMEBUFFER allows arbitrary writing of points, and an interesting art picture generation test is performed.

This post is from stm32/stm8

Latest reply

Awesome!   Details Published on 2023-11-1 17:34
 

3

Posts

0

Resources
2
 
Interesting, come and have a look
This post is from stm32/stm8
 
 

623

Posts

0

Resources
3
 

Awesome!

This post is from stm32/stm8
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list