A GDI+ Based Character LCD Control
| This is a renew. |
A GDI+ Based Character LCD Control
by Conmajia
Character liquid crystal display (LCD) modules are widely used in electronic devices, instruments and handiworks. They are simple, flexible, clear to view, and low power. Fig.1 shows an example of character LCD used in an amateur project.

Fig.1 LCD in An Amateur Instrument
Very cool, isn't it? What if I told you that you could implement this hardware part as a software UI control and used it in your applications? To accomplish this, you have to get to know some of the hardware details.
Inside an LCD module, there are matrixed liquid crystal dots. Built-in controllers scan rows (COMn) and columns (SEGn) to activate dots to constitute characters and symbols. The process is shown in fig.2.

Fig.2 LCD Display Principle
One thing above all you should know is the register set that controls all display content of the control: display data RAM (DDRAM), character generator RAM/ROM (CGRAM/ROM).
The DDRAM is an 80-byte buffer which can hold up to 40×2 of display data. That is the largest size of a single LCD controller (HD44xxx series) supports. You change characters on the screen by changing bytes in the DDRAM. CGRAM/ROM are used to generate custom characters or symbols, or just simply load pre-defined character/symbols in the ROM. With the character generator, you can do lots tricks such as display animations, icons or Chinese characters.
With all the hardware knowledges you just learned, you can now have your "soft" LCDs. Fig.3 demonstrates one of my implementations.

Fig.3 Demo of My LCD Control
The LCD control is a standard WinForm control derived from the UserControl class.
public class DotMatrixLcd : UserControl
A 2-D array works as the DDRAM to store all characters to be displayed.
DotMatrixCharacter[][] characters;
The DotMatrixCharacter represents a single character in the DDRAM. I made it a Control derived class to easy my work. You are welcome to optimize this if you found it to heavy to use.
public class DotMatrixCharacter : Control
To generate raw character data, a CG class is defined as below.
public sealed class CharacterGenerator
{
/// Get character data from DDRAM by address.
public static byte[] GetDdram(byte address)
{
return charset[address];
}
/// Get character data from DDRAM to match the given character.
public static byte[] GetDdram(char character)
{
return charset[(byte)character];
}
// 8 cgram chars
static byte[][] cgram = new byte[8][];
// for dummy
static byte[] emptyChar ={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/// Store character data in CGRAM registers by index.
public static void SetCgram(byte[] data, int index)
{
if (data == null || data.Length != 8)
return;
if (index < 0 || index > 7)
return;
cgram[index] = data;
}
/// Get CGRAM character data by index.
public static byte[] GetCgram(int index)
{
if (index < 0 || index > 7)
return emptyChar;
return cgram[index];
}
// 256x8 bytes (1024 bytes) characters
static readonly byte[][] charset =
{
// 0000 0000
new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
// 0000 0001
new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
// ...
Now all the data is ready. Now the next todo is on the canvas. To paint a character, a renderer is built in the DotMatrixCharacter control.
void drawBlocks(Graphics g)
{
byte[] charData;
// check source of char to display for CGRAM support
switch (charSource)
{
case DisplaySource.CGRAM:
if (cgramData == null || cgramData.Length != DOT_ROWS)
// invalid data, draw empty
// all 0x00
charData = new byte[DOT_ROWS];
else
charData = cgramData;
break;
case DisplaySource.DDRAM:
default:
charData = CharacterGenerator.GetDdram(ddramAddress);
break;
}
// ready to draw
byte mask;
for (int i = 0; i < DOT_ROWS; i++)
{
// if use mask = 0x01 (right to left)
// the output will be vertical mirrored
mask = 0x01 << (DOT_COLS - 1);
for (int j = 0; j < DOT_COLS; j++)
{
if ((mask & charData[i]) == 0)
{
// 0 - empty
if (circleBlock)
g.FillEllipse(
inactiveBrush,
j * (blockSize.Width + spacing),
i * (blockSize.Height + spacing),
blockSize.Width,
blockSize.Height
);
else
g.FillRectangle(
inactiveBrush,
j * (blockSize.Width + spacing),
i * (blockSize.Height + spacing),
blockSize.Width,
blockSize.Height
);
}
else
{
// 1 - fill
if (circleBlock)
g.FillEllipse(
activeBrush,
j * (blockSize.Width + spacing),
i * (blockSize.Height + spacing),
blockSize.Width,
blockSize.Height
);
else
g.FillRectangle(
activeBrush,
j * (blockSize.Width + spacing),
i * (blockSize.Height + spacing),
blockSize.Width,
blockSize.Height
);
}
// next bit
//mask <<= 1;
// msb to lsb
mask >>= 1;
}
}
}
With the built-in renderer, the final LCD module control can obtain the extensibility to switch between different display contents like character displays, graphic dot matrix display, etc.
Source Code & Demo Executive
Download 'em here:
References
- How to Use Character LCD Module, chan@elm-chan.org
A GDI+ Based Character LCD Control的更多相关文章
- 阅读Deep Packet Inspection based Application-Aware Traffic Control for Software Defined Networks
Deep Packet Inspection based Application-Aware Traffic Control for Software Defined Networks Globlec ...
- 📟 Character Liquid Crystal Display Control (English)
A replica CLCD module control. Initiated on May 5, 2012 Updated on Feb 21, 2017 Copyright 2012-2017 ...
- Mecanim Control
http://www.ufe3d.com/doku.php/mecanimcontrol Mecanim Control Your ultimate solution for Mecanim base ...
- linux驱动之LCD
LCD程序步骤:1. 分配一个fb_info 2. 设置 3. 硬件相关的操作4. 注册 register_framebuffer 5.入口函数 6.出口函数 #include <linux/s ...
- 驱动05.lcd设备驱动程序
参考s3c2410fb.c总结出框架 1.代码分析 1.1 入口函数 int __devinit s3c2410fb_init(void) { return platform_driver_regis ...
- LCD 显示异常定位分析方法
第一种情况: 进入kernel或android 后,如果LCM图像示异常,可以通过如下步骤来判断问题出现在哪个层面. step1:通过DMMS截图,来判断上面刷到LCM的数据是否有问题. 若DMMS获 ...
- lcd驱动框架
目录 lcd驱动框架 框图 程序分析 入口 打开open 读read 初始化registered_fb 注册 小结 程序设计 测试 方式一操作fb0 方式二操作tty 方式三操作终端 完整程序 tit ...
- Linux学习: LCD驱动
一.LCD驱动框架: 1.分配一个fb_info结构体:s3c_lcd = framebuffer_alloc(0,NULL); 2.设置fb_info(s3c_lcd): ID.固定参数.可变参数. ...
- 关于Unity树形插件Tree View Control的相关搜集
博客http://blog.csdn.net/qq_15267341/article/details/51997926 的这个 Script Based Runtime Tree-Vie ...
随机推荐
- js实现浏览器添加收藏功能
今天搞项目的时候为了实现浏览者实现添加收藏的功能,特地了解了一下相关的API. 也看到了网上各种版本的代码.整理了一下,代码如下.简单易懂. <script> function _addF ...
- Nginx+IIS+Redis 处理Session共享问题 1
最近遇到一个棘手的问题,微信公众平台的前端站点session老是丢失,我们是走的微信网页授权,授权后获取用户openid,丢失后没有openid后续的操作全白搭了,因为没了openid只能判断为客户不 ...
- Java 数值类型以及计算
前段时候写了一个对外提供的接口,其中有一个数值校验的计算.在测试的过程中发现5.6-1.6 != 4,在反复的测试过程中发现double类型的数值为有精度丢失的现象,看来还是基础知识不牢固,所以就在网 ...
- wemall app商城源码机器人检测
wemall-mobile是基于WeMall的Android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之 ...
- 2818: Gcd
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2170 Solved: 979[Submit][Status][Discuss] ...
- 富文本NSAttributeString
例子:http://www.jianshu.com/p/9ffcdc0003e0 下面研究下AttributedString究竟可以设置哪些属性,具体来说,有以下21个: // NSFontAtt ...
- python + selenium <一>
python 安装 python 下载地址: http://python.org/getit/ ez_setup.py 下载地址: https://pypi.python.org/packages/s ...
- 纯Jquery前端分页
---恢复内容开始--- 由于之前自己做过jquery分页,就是调用jni接口时,只能用前台分页解决显示问题.最近看到有人提这样的问题:一个请求传过来上万个数据怎么办?于是萌生了写这篇博客的想法. 效 ...
- cuda编程学习2——add
cudaMalloc()分配的指针有使用限制,设备指针的使用限制总结如下: 1.可以将其传递给在设备上执行的函数 2.可以在设备代码中使用其进行内存的读写操作 3.可以将其传递给在主机上执行的函数 4 ...
- Android开发之获取xml文件的输入流对象
介绍两种Android开发中获取xml文件的输入流对象 第一种:通过assets目录获取 1.首先是在Project下app/src/main目录下创建一个assets文件夹,将需要获取的xml文件放 ...