项目一:电子量产工具

软件总框架

1:设计构思-显示管理器

1.1 显示部分-数据结构抽象

对两个不同的设备(Frambuffer与WEB),抽象出同一个结构体类型,

总概括:先得到一个buffer,在这个buffer中你可以绘制图片,程序在buffer中绘制图片,然后刷到硬件上(lcd)去或者浏览器中(WEB网页)

如何获得buffer,以及buffer怎样绘制图片

1:先获得一个结构体,使用Framebufer中的函数,获得buffer来绘制界面。

2:在buffer中绘制按钮界面,根据ioctl获得LCD分辨率、BPP,最后刷新这个界面。

Framebuffer:在 Linux 系统中通过 Framebuffer 驱动程序来控制 LCD。Frame 是帧的意思,buffer 是缓冲的意思,这意味着 Framebuffer 就是一块内存,里面保存着一帧图像。Framebuffer 中保存着一帧图像的每一个像素颜色值,假设 LCD 的分辨率是 1024x768,每一个像素的颜色用 32 位来表示,那么 Framebuffer 的大小就是:1024x768x32/8=3145728 字节。

WEB

fd_fb = open("/dev/fb0", O_RDWR); //打开设备节点

ioctl: 获得LCD分辨率、BPP

mmap: 应用程序驱动程序之间传递数据时,可以通过 read、write 函数进行。这

涉及在用户态 buffer内核态 buffer 之间传数据,如下图所示:

应用程序不能直接读写驱动程序中的 buffer,需要在用户态 buffer 和内核buffer 之间进行一次数据拷贝。这种方式在数据量比较小时没什么问题;但是数据量比较大时效率就太低了。比如更新 LCD 显示时,如果每次都让 APP 传递一帧数据给内核,假设 LCD 采用 1024*600*32bpp 的格式,一帧数据就有

1024*600*32/8=2.3MB 左右,这无法忍受。

改进的方法就是让程序可以直接读写驱动程序中的 buffer,这可以通过mmap 实现(memory map),把内核的 buffer 映射到用户态,让 APP 在用户态直接读写。

cross_comepile 交叉编译工具链:交叉编译工具链用来在 Ubuntu 主机上编译应用程序,而这些应用程序是在ARM 等其他平台上运行。

makefile:

在一个正式的软件项目中,由很多个.c和.h文件构成,此时如果直接在命令行编译,就会像这样:gcc a.c b.c c.c d.c e.c f.c g.c -o exe每次编译都要输入一堆东西很麻烦,这时就需要Makefile来解决,这样就能实现只需要写一次即可实现每次都能同时编译多个文件。

————————————————

我参考 Linux 内核的 Makefile 编写了一个通用的 Makefile,它可以用来

编译应用程序:

1支持多个目录、多层目录、多个文件;

2 支持给所有文件设置编译选项;

3 支持给某个目录设置编译选项;

4 支持给某个文件单独设置编译选项;

5 简单、好用。

freetype:

一个外观对象通常使用FT_New_Face()来创建,这个函数接受如下参数:一个FT_Library句柄,一个表示字体文件的C文件路径名,一个决定从文件中装载外观的索引(一个文件中可能有不同的外观),和FT_Face句柄的地址,它返回一个错误码。

FT_Error FT_New_Face( FT_Library library,
                        const char* filepathname,
                        FT_Long face_index,
                        FT_Face* face);
1.1.1 程序
disp_manager.h
#ifndef __DISP_MANAGER_H
#define __DISP_MANAGER_H

typedef struct Region{          //一个区域
    int iLeftUpX;  //左上角
    int iLeftUpY;
    int iWidth;
    int iHeigh;
}Region,*PRegion;        //结构体(Region)指针.

//绘制图片
typedef struct DispOpr{
    char *name;    //来分辨取得的不同的结构体
    char *GetBuffer(int *pXres, int *pYres, int *pBpp);  //绘制图片需要buffer,获得一个buffer
                                            //(分辨率,像素占据多少位)
    int FlushRegion(PRegion ptRegion, char *buffer);     
                        // 绘制好按钮,刷新区域,刷到设备上去(Framebuffer)
    struct DispOpr *ptNext;         //为了让这些结构体都能够链接起来,我们加一个指针struct。。。
};

#endif
1.1.2 总结

1.上层APP在这个buffer中绘制图片

typedef struct DispOpr{
    char *name;
    char *GetBuffer(int *pXres, int *pYres, int *pBpp);
    int FlushRegion(PRegion ptRegion, char *buffer);
    struct DispOpr *ptNext;
};

2.可以更新某个区域,比如“按钮2”然后把该区域Flush到LCD或者WEB上

typedef struct Region{
    int iLeftUpX;
    int iLeftUpY;
    int iWidth;
    int iHeigh;
}Region,*PRegion;

1.2 显示部分-Framebuffer编码

抽象出两个结构体:一个显示结构体 ,一个更新结构体

1.2.1 Framebuffer程序
framebuffer.c
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>

#include "disp_manager.h"

static int fd_fb;
static struct fb_var_screeninfo var;    /* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;

static int FbDeviceInit(void)
{
    fd_fb = open("/dev/fb0", O_RDWR);
    if (fd_fb < 0)
    {
        printf("can't open /dev/fb0\n");
        return -1;
    }
    if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
    {
        printf("can't get var\n");
        return -1;
    }

    line_width  = var.xres * var.bits_per_pixel / 8;
    pixel_width = var.bits_per_pixel / 8;
    screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
    fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
    if (fb_base == (unsigned char *)-1)
    {
        printf("can't mmap\n");
        return -1;
    }

    return 0;
}

static int FbDeviceExit(void)
{
    munmap(fb_base, screen_size);
    close(fb_base);
    return 0;
}

/* 可以返回LCD的framebuffer, 以后上层APP可以直接操作LCD, 可以不用 FbFlushRegion
 * 也可以malloc返回一块无关的buffer, 要使用 FbFlushRegion
 *
 */
static char *FbGetBuffer(int *pXres, int *pYres, int *pBpp)
{
    *pXres = var.xres;
    *pYres = var.yres;
    *pBpp  = var.bits_per_pixel;

    return fb_base; 
}
static int FbFlushRegion(PRegion ptRegion, char *buffer)
{

    return 0;
}

static DispOpr g_tFramebufferOpr = {
    .name           = "fb",
    .DeviceInit   = FbDeviceInit,
    .DeviceExit   = FbDeviceExit,
    .GetBuffer    = FbGetBuffer,
    .FlushRegion  = FbFlushRegion,
};
1.2.2 总结

int FbDeviceInit(void); //设备初始化

int FbDeviceExit(void); //exit清除 munmap close

char *FbGetBuffer(int *pXres, int *pYres, int *pBpp);

1.上层APP在这个buffer中绘制图片

int FbFlushRegion(PRegion ptRegion, char *buffer);

2.可以更新某个区域,比如“按钮2”然后把该区域Flush到LCD或者WEB上

1.3 显示系统-显示管理

1.3.1 显示管理

disp_manager.c的作用

1.承上启下

2.下面各个模块把DispOpr注册进来

3.上面选择某个模块

4.还提供一些函数,比如PutPixel

1.3.2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值