【电子量产工具】1.显示系统

简介: 【电子量产工具】1.显示系统

前言

最近看了 电子量产工具 这个项目,本专栏是对该项目的一个总结。


一、显示系统分析

可以看到上面的框图,我们可以分为三大部分:

  • 从最下面的  第 1 层开始。这是整个项目的最底层,主要负责处理数据和逻辑,与板子直接进行交互。
  • 中间的是第 2 层 管理层。负责处理应用的中间件功能,它位于底层程序和用户界面之间,主要向上层程序提供所需的底层代码。
  • 最上面的就是综合应用,用来实现用户所需的功能。

项目主要包含了 5 个方面,分别是 显示管理器,输入管理器,字体管理器,页面管理器,图片格式管理器。首先实现显示系统功能。

可以看到 显示管理器 下面有两种显示输出的方式:Framebufferweb输出。这里只着重讲解 Framebuffer 的显示实现。

在编写显示系统之前需要对 Framebuffer 有一定的了解,如何不了解的可以参考我之前的文章:Linux 应用基础 Framebuffer应用编程

二、封装显示结构体

对于显示方式有两种,可以将功能封装在结构体中,提高代码的扩展性和灵活性。

  1. DispOpr 显示设备结构体
typedef struct DispOpr {
  char *name;
  int (*DeviceInit)(void);                    //显示设备初始化
  int (*DeviceExit)(void);
  int (*GetBuffer)(PDispBuff ptDispBuff);             //获取LCD的framebuffer
  int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);   //将数据刷新到LCD
  struct DispOpr *ptNext;                     //指针,用于连接链表
}DispOpr, *PDispOpr;
  1. DispBuff 是一个结构体,用于封装LCD的相关信息,例如分辨率,像素等。
    buff: 用来后面 存放起始地址。
typedef struct DispBuff {
  int iXres;                        //x方向的分辨率
  int iYres;                        //y方向的分辨率
  int iBpp;                       //bits_per_pixel,每个像素占多少位
  char *buff;
}DispBuff, *PDispBuff;
  1. Region 也是一个结构体,用来表示一个区域的左上角坐标,宽度以及高度。
typedef struct Region {
  int iLeftUpX;
  int iLeftUpY;
  int iWidth;
  int iHeigh;
}Region, *PRegion;

三、底层 Framebuffer

  1. 在 framebuffer 里实现 DispOpr 结构体。

    这里要设置 name, 因为用于显示的设备不止 framebuffer ,还有 web 输入。
    中间管理层,会根据这里所设置的 name 来 按照需求 选择不同的显示设备。

  1. FbDeviceInit 中完成 framebuffer 的初始化。

  1. FbGetBuffer负责向上层 管理器返回初始化后的 LCD 的framebuffer 。将 var 中数值取出 放入函数参数的结构体里,传递给上层。

注意:FbFlushRegion 可以将绘制好buff 刷新到 LCD 上。

但是,在 FbDeviceInit 函数中,我们已经返回LCD的framebuffer, 以后上层APP可以直接操作LCD, 可以不用 FbFlushRegion


四、显示管理层

管理层 起着承上启下的作用。

首先,管理层 管理着不同的显示设备,我们可以将不同设备放入链表,然后根据 name来选择。

  1. 先将设备注册进入链表。

g_DispDevs 是头指针,在 RegisterDisplay 函数

  1. 中,采用头添加的方法将设备加入链表。
  2. 然后根据 要设备名来找到相应的显示设备。找到设备后对其初始化。
    底层的代码已经实现了相应功能,只需要调用即可。
int SelectDefaultDisplay(char *name)
{
  PDispOpr pTmp = g_DispDevs;         //临时指针指向头指针
  while (pTmp) 
  {
    if (strcmp(name, pTmp->name) == 0)      //判断名字是否相同
    {
      g_DispDefault = pTmp;         //找到目标设备
      return 0;
    }
    pTmp = pTmp->ptNext;          //遍历链表
  }
  return -1;
}
int InitDefaultDisplay(void)
{
  int ret;
  ret = g_DispDefault->DeviceInit();      //调用底层 DeviceInit初始化
  if (ret)
  {
    printf("DeviceInit err\n");
    return -1;
  }
  ret = g_DispDefault->GetBuffer(&g_tDispBuff);   //调用底层 GetBuffer获取LCD的framebuffer
  if (ret)
  {
    printf("GetBuffer err\n");
    return -1;
  }
  line_width  = g_tDispBuff.iXres * g_tDispBuff.iBpp/8;
  pixel_width = g_tDispBuff.iBpp/8;
  return 0;
}
  1. 为了方便上层 APP 使用 LCD 的 framebuffer,我们需要将 framebuffer 传递给上层。

五、测试程序

测试层程序用于验证和检查应用的正确性和稳定性,例如 单元测试。

测试在 LCD 上显示一个英文字符。

在 main 函数里调用 管理层的代码,来实现相应功能。

  • 刷新LCD 的代码可以忽略不写,因为我们直接 返回 LCD 的 framebuffer , 以后上层APP可以直接操作 LCD , 可以不用 FbFlushRegion
  • 也可以 malloc 返回一块无关的 buffer , 要使用 FbFlushRegion

注意 :显示字符前,要实现描点函数。

pen_8 ,pen_16,pen_32 是起笔点,可以相互转化。

/* 描点函数 */
int PutPixel(int x, int y, unsigned int dwColor)
{
  unsigned char *pen_8 = (unsigned char *)(g_tDispBuff.buff+y*line_width+x*pixel_width);
  unsigned short *pen_16; 
  unsigned int *pen_32; 
  unsigned int red, green, blue;  
  pen_16 = (unsigned short *)pen_8;
  pen_32 = (unsigned int *)pen_8;
  switch (g_tDispBuff.iBpp)
  {
    case 8:
    {
      *pen_8 = dwColor;
      break;
    }
    case 16:
    {
      /* 565 */
      red   = (dwColor >> 16) & 0xff;
      green = (dwColor >> 8) & 0xff;
      blue  = (dwColor >> 0) & 0xff;
      dwColor = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
      *pen_16 = dwColor;
      break;
    }
    case 32:
    {
      *pen_32 = dwColor;
      break;
    }
    default:
    {
      printf("can't surport %dbpp\n", g_tDispBuff.iBpp);
      return -1;
      break;
    }
  }
  return 0;
}
/* 显示字符 */
void lcd_put_ascii(int x, int y, unsigned char c)
{
  unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
  int i, b;
  unsigned char byte;
  for (i = 0; i < 16; i++)
  {
    byte = dots[i];
    for (b = 7; b >= 0; b--)
    {
      if (byte & (1<<b))
      {
        /* show */
        PutPixel(x+7-b, y+i, 0xffffff);
      }
      else
      {
        /* hide */
        PutPixel(x+7-b, y+i, 0); 
      }
    }
  }
}

实验效果图:


总结

虽然 这种分层的写法看起来更复杂,但是对于代码的可以移植性会大大提高。

相关文章
【电子量产工具】6. 业务系统
【电子量产工具】6. 业务系统
92 0
|
中间件
【电子量产工具】大纲分析
【电子量产工具】大纲分析
96 0
|
5月前
|
数据采集 异构计算
实验室自用LabVIEW软件与商用软件价格差异分析
实验室自用LabVIEW软件与商用软件价格差异分析
72 2
|
7月前
|
监控 安全 物联网
智慧校园电子班牌系统源码,SaaS模式部署,支持PC端、移动客户端、电子班牌端
智慧班牌系统,支持PC端、移动客户端、电子班牌端,一方面将展示校园文化、班级文化的丰富多彩,另一方面也将成为学校和班级,教室和学生,教师和学生,以及家长和学生之间的互动媒介。通过班牌真正发挥智慧校园的优势,促进丰富的教学生活。
智慧校园电子班牌系统源码,SaaS模式部署,支持PC端、移动客户端、电子班牌端
|
监控 小程序 算法
原生小程序电子班牌系统 智慧校园云平台源码
智慧校园云平台电子班牌系统,集学生管理、班级管理、校园管理于一身,融合学校教务管理、教师管理、学籍管理、考勤、信息发布、班级文明建设、校园风采、家校互通等一系列应用,为校园管理现代化、信息化提供有效解决工具
141 3
【电子量产工具】5.页面系统
【电子量产工具】5.页面系统
66 0
|
存储 UED
【电子量产工具】2.输入系统
【电子量产工具】2.输入系统
79 0
|
编解码
【电子量产工具】3.文字系统
【电子量产工具】3.文字系统
77 0
|
vr&ar
【电子量产工具】4. UI系统
【电子量产工具】4. UI系统
92 0
|
小程序 数据管理 大数据
电子班牌系统 智慧班牌管理云平台源码
智慧电子班牌系统包括:SaaS云平台端、智慧校园管理平台端、家长小程序移动端、教师小程序移动端、智慧班牌学生端。一款全功能智慧管理平台系统,融合了多媒体信息发布、家校互通、物联控制、教务管理、日常办公等一系列应用,是校园管理的现代手段。
518 0
电子班牌系统 智慧班牌管理云平台源码