前面我们实现了NV12格式的UVC显示,基于此我们可以实现framebuffer机制,实现任意点的颜色的读写,然后移植LVGL进行GUI开发。由于使用YUV格式需要格式转换,且需要根据采样进行插值,直接修改某点的颜色不方便,所以我们使用RGB格式,为了减少缓存大小使用RGB565格式。
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*/
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++;
}
基于任意的写点函数,通过一些数学公式产生有意思的图片。
代码如下
#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 编辑牛逼!