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 ...
随机推荐
- 深入理解java虚拟机之——JVM垃圾回收策略总结
如何判断一个对象是否存活 引用计数算法:给对象中添加一个引用计数器,每当有引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用. Java虚拟机里面没有 ...
- okhttp +fastJson 在UI层的回调封装
一直使用OkHttp 经常烦人的地方是回调方法 数据解析后必须通过handler 在主线程做操作 网上找了很多资料 发现有些都是基于Gson做的解析 fastJson 在封装时 泛型传入会有很多不方 ...
- 使用JSON.parse(),JSON.stringify()实现对对象的深拷贝
根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系. 测试例子: var test={ a:"ss", ...
- MySQL入门(上)
1 课程回顾 自定义标签&编码实战 1)自定义标签步骤: 1.1 编写标签处理器类,继承SimpleTagSupport类,覆盖doTag方法 1.2 在WEB-INF目录下建立tld文件,在 ...
- 【CNMP系列】VIM编辑器详解
缘起 大学的时候做过Linux内核驱动程序研发,之前写C语言就是用的Vim编辑器,当年的Vim还不如今天之强大,当时的插件也没有现在这么多,只是觉得这个编辑器能满足我想要的所有,查看Linux内核代码 ...
- Tomcat+Eclipse乱码问题解决方法
概述 乱码问题是大家在日常开发过程中经常会遇到的问题,由于各自环境的不同,解决起来也费时费力,本文主要介绍一般性乱码问题的解决方法与步骤,开发工具采用Eclipse+Tomcat,统一设置项目编码UT ...
- iOS开发之判断系统版本
if([[UIDevice currentDevice].systemVersion doubleValue]>=7.0) { //是IOS7至以上版本 }else{ //IOS7以下版本 }
- jqzoom插件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title> ...
- Swift应用案例 2.闭包入门到精通
本文主要介绍Swift的闭包的使用并与OC的Block做比较.学习Swift是绕不过闭包的,因为无论是全局函数还是嵌套函数都是闭包的一种,本文主要介绍闭包表达式. 1.闭包表达式的使用 // 1. ...
- suse安装svn服务端和客户端的使用
suse安装svn服务端 一. 安装服务端 配置网络安装源(suse11sp1为例) 新建11.1.repo11.1为软件源名称,可自定义文件并添加如下内容后保存 linux-e0xg:/etc/zy ...