搜索
bottom↓
回复: 219

[交流][2008-6-09 Update]手把手教你编写GUI——第一阶段:Fool GUI

  [复制链接]

出0入296汤圆

发表于 2008-5-22 22:29:36 | 显示全部楼层 |阅读模式
>>说在前面的话
    傻孩子的成名作也许就是那个充满抽象概念的“水贴”——《[交流]如何在12864上绘图》。
以我现在的观点看来,挨骂是必然的。其中原因,如果你没有真的去实现一个GUI是很难说得清楚
的。
    不管大家承不承认,mkII的开源工作实际上已经完成了,一个指令解析引擎,已经能让Studio
认出我们的系统,您只需要根据格式依次添加指令即可;一个Mega系列的下载函数库,已经能够
实现Mega系列的ISP功能,是否能把解析引擎和下载库连结在一起,实际上正是您DIY mkII的最后
乐趣了——什么?你要实现完整功能的源代码?已经有人开源了阿,帖子里面就有啊,你参考下
不就可以了?一边要鱼一边喊“渔”,拜托,心口如一好不好?
    后来,我终于想清楚这个问题了,大家需要的也许只是一个自制mkII的材料,而不是如何自己
编写mkII的乐趣……而我开源的乐趣却恰恰和大家不同,我希望找到与我一起讨论代码的人……为
了找到这样的人,我苦苦的开源……可惜应者寥寥……不知道是不是不屑与我交流……
   
    ——于是,我决定,继续开源,不管你骂也好,赞也好……我开故我在……多批评也许和赞
扬一样让我开心。感谢大家的支持。


>>手把手教你编写GUI开源规划

    1、这是一个研究性的开源贴。所谓研究性,就是边开源,边讨论,边修改,边发布。
    2、整个开源计划,要完成一个Snail GUI系统。该系统是开源的,跨平台的,可以实现类似
       windows GDI 的功能。为了让大家一步一步明白我的思路,现在只是第一阶段,完成一个
       容易理解的,用来打开大家思路的简易系统——对很多人来说也许更实用的系统 Fool GUI。
    3、Fool GUI,顾名思义,就是傻瓜GUI,是一个概念GUI,只追求实现功能,无视优化。它要
       实现的功能是:首先,必须与硬件无关——12864也好、320240也好……只要按照规范编写
       硬件驱动库,就可以使用;其次,实现菜单编写技术,图形绘制、滚屏等基本技术。支持
       大SRAM的系统,比如M128或者M64,也支持小SRAM的系统,比如M8。
    4、编写Fool GUI的目的是让大家对很多GUI的概念有思考有萌芽,而不是直接告诉大家“有XX
       概念你必须这样做云云”
    5、如果您从某些书上看到更好的做法,请务必自己告诉大家是哪本书,但是最好给我留一丝
       面子,我并不是想故弄玄虚,我写故我在。您不爱看,可以不用点开。浪费您的眼球,实
       在不敢。
    6、关于Fool GUI系统的优化,将在第二阶段着重进行。第二阶段实际上会发现,很多问题以
       现有构架是无法实现的,于是我们将重新规划,进入第三阶段 Snail GUI的编写。这就是
       系列专题的规划。
    7、我并不准备讲解如何编写某一个液晶屏幕的底层驱动,但是我会着重于讲解如何让这些驱
       动更符合Fool GUI的规范,以至于GUI的上层代码可以不经过修改直接使用。
    8、这个帖子可能会很长……希望大家理解……傻孩子还要考研……


>>硬件平台

    处理器:        ATMega128L                       
    系统时钟:      外部16M
    LCD:           SED1335 驱动的 320240
    原理图:        <有待添加下载>
   

>>相关资料和链接

    SED1335 芯片手册(文件大小:388K)
    LCD320240 用户手册(文件大小:100K)
    点击此处下载Fool GUI的最小系统(包含了SED1335驱动)ourdev_304894.rar(文件大小:311K)

>>章节索引


    ------------------------------------------------------------------------------------
       章节      标题                            楼层            状态
    ------------------------------------------------------------------------------------

       第一章    物质基础决定上层建筑            2楼             基本完成

       实例1.1   SED1335驱动                     24楼            上传工程

       第二章    GUI逻辑骨架的规划               --              规划中

       第三章    随心所欲的位图显示              25楼            正在编写

       实例3.1   英文字符的任意位置显示          --              规划中

       第四章    深入文本模式                    --              规划中

       实例4.1   在矩形区域内连续输出文本        --              规划中
      
       实例4.2   TextBox的实现                   --              规划中

       ……

       最终章    将Fool GUI移植到12864上         --              计划中

       最终实例一 贪食蛇                         65、66楼        上传工程、GUI最小系统

    -----------------------------------------------------------------------------------

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2008-5-22 22:36:21 | 显示全部楼层
沙发

傻孩子:又被抢了沙发…… - -b

出0入296汤圆

 楼主| 发表于 2008-5-22 22:36:33 | 显示全部楼层

>>第一章:物质基础决定上层建筑

[本章目的]
          为大家分析GUI系统可移植性的一个致命问题,存储器。明确LCD其实
      只是一个存储器的本质。然后完成对嵌入式系统存储器系统的抽象。并尝
      试规定统一的接口。编写对应的函数库(甚至包含一个类视图)。

[原理解析]
          最近,研究AVR32,突发灵感,把嵌入式系统硬件系统的构成划分为
      三类:存储器、总线、运算单元(DSP/协处理器/FPGA等)。比如LCD就是
      一个存储器。FLASH、EEPROM、SRAM就更不用说了。可以说,但凡映射到
      存储器空间中的设备都可以被视作一个存储器。对他们的操作都具有统一
      的特性,因而可以使用统一的抽象和接口。
          多说无益,学过C++的可以直接看下面的类声明,你应该就知道我的意
      图了。对,这就是一个存储器基类,将所有存储器的操作抽象出来,提供
      统一的接口,利用这些接口,我们可以很方便的实现诸如存储器间拷贝的
      移植。
          举一个例子,我们的LCD自己有一个显示存储器,我们为它建立了一个
      专门的对象,拥有自己的接口实现方法。当我们使用M128这样有较大SRAM
      的单片机时,我们可以在SRAM中开辟一个缓冲区,用于实现双缓冲技术。
      我们针对SRAM的操作也会建立一个专门的对象,实现专门的接口实现方法。
      这个时候,刷新操作对应的就是SRAM->LCD显存的拷贝。当我们使用M8这样
      SRAM较小的单片机时,我们没有能力在SRAM中开辟缓冲区,此时,要想使
      用和M128环境下相同的代码(且不修改这部分代码),就必须要找一个地
      方来作为缓冲区。我们当然可以选择LCD显存的某一个空闲部分来充当这个
      缓冲区,那么又如何实现直接使用M128环境下的代码而不经过修改呢?其
      时我们的MEM类已经解决了这个问题,因为我们都是通过统一的接口来实现
      存储器拷贝的,存储器的改变并不影响代码的结构。是不是很神奇?
          这就是这种抽象的威力之一,后面我们还可以看到,利用这种技术,我
      们甚至可以实现虚拟存储技术——这当然是后话。
         

class MEM
{
    private:
        UINT16          m_wType;
        UINT16          m_wAccess;
        UINT32          m_dwAddress;
        UINT32          m_dwSize;
        UINT16          m_wBlockSize;
    public:
        virtual BOOL Read(UINT32 dwAddress,UINT32 dwLength,void *pData);
        virtual BOOL Write(UINT32 dwAddress,UINT32 dwLength,void *pData);
        virtual BOOL ReadBlock(UINT32 dwAddress,UINT16 wBlockSize,void *pData);
        virtual BOOL WriteBlock(UINT32 dwAddress,UINT16 wBlockSize,void *pData);
        virtual BOOL EraseBlock(UINT16 wBlock,BYTE chSymble);
        virtual BOOL EraseChip(BYTE chSymble);
        virtual BOOL LockBlock(UINT16 wBlock);
        virtual BOOL LockChip(void);
        virtual BOOL UnlockBlock(UINT16 wBlock);
        virtual BOOL UnlockChip(void);
        virtual BOOL ProtectBlock(UINT16 wBlock);
        virtual BOOL ProtectChip(void);
        virtual BOOL Copy(UINT32 dwAddressFrom,UINT32 dwLength,UINT32 dwAddressTo);
        virtual BOOL Initial(void);
};

          对照上面的代码,我们来看看,它是如何对针对存储器的操作进行抽
      象的。首先,我们来看m_wType。这显然是一个描述存储器类型的变量。
      我们不能简单的认为,给SRAM一个类型,给FLASH一个类型等等。因为,在
      实际的应用中,对于存储器间拷贝,我们的一般做法是,首先从源存储器
      中读取一小段数据到一个很小的临时缓冲区中;再将该缓冲区中的数据写
      入到目标存储器中。这些操作分别牵涉到,Read和Write两个接口。显然,
      这里存在优化的可能——对于同一个存储器,我们并不需要一个缓冲区作
      为中转,直接复制即可,典型的就是SRAM。但是简单的人为m_wType值相同
      就是同一个存储器是不妥的。比如,我有多个LCD,都是同一种型号的。显
      然,如果m_wType的值只是简单的表示存储器类型,此时,不同LCD就会拥
      有相同的类型值,而导致系统对拷贝进行优化——这种优化显然是非法的。
      因此,我们必须利用m_wType来表征存储器类型同时还要能区别该对象是该
      存储器类型的第几个实例。显然,同一个存储器中的对象拥有相同的存储器
      类型和相同的实例编号,而不同存储器虽然可能拥有相同的存储器类型号,
      却拥有不同的实例编号。
          基于上面的考虑,我们将m_wType作为两个字节来考虑,高字节表征存
      储器类型,低字节表征存储器实例编号。当我们执行拷贝优化时,只要简
      单判断m_wType是否相同就可以了。(参照后面的代码)
          从m_wType中,我们还可以知道,实际上这里说的MEM对象,并不一定是
      一个完整的存储器,而可以是一个存储器中的某一段区域——也就是存储器
      块的概念——有了这一概念,就有条件进行段、页式存储管理,虚拟存储技
      术就成为可能。每一个存储块在同一个存储器内肯定有自己起始地址,也有
      自己的块大小。这就是m_dwAddress和m_dwSize的由来。需要补充说明的是
      在一个存储块中,我们所使用的地址实际上是相对m_dwAddress的一个偏移
      量。
           
          对存储器有哪些操作,实际上就决定了我们需要添加哪些函数接口。
      有些存储器是可以随机读写的,有些则仅仅允许随机读,比如某些FLASH。
      同样,典型的存储器往往被按照块进行了划分,读写要按照块为单位。这
      就牵涉到块读写。当然,还有块擦除,片擦除。块保护,块锁定等等。为了
      表征我们的对象支持哪些操作,我们需要一个专门的标志变量,这就是
      m_wAccess的由来。通常,针对存储器存在以下的操作,我们为之定义了宏,
      这些宏可以通过或操作来连接,以描述该存储器允许的操作:
   
# define MEM_ACCESS_RANDOM_READ         0x0001
# define MEM_ACCESS_RANDOM_WRITE        0x0002
# define MEM_ACCESS_BLOCK_READ          0x0004
# define MEM_ACCESS_BLOCK_WRITE         0x0008
# define MEM_ACCESS_BLOCK_ERASE         0x0010
# define MEM_ACCESS_CHIP_ERASE          0x0020
# define MEM_ACCESS_BLOCK_LOCK          0x0040
# define MEM_ACCESS_CHIP_LOCK           0x0080  
# define MEM_ACCESS_UNLOCK_BLOCK        0x0100
# define MEM_ACCESS_UNLOCK_CHIP         0x0200
# define MEM_ACCESS_BLOCK_PROTECT       0x0400
# define MEM_ACCESS_CHIP_PROTECT        0x0800

         很容易想到,对于SRAM,我们可以自己抽象出所谓的块读写和擦除,当
     然也可以干脆不加入这一操作属性。后面的实际应用中,我们就以LCD240320
     SED1335为例说明如何建立这样一个存储器对象。
         
         这里,我们补充一个问题。这就是存储器的访问模式。也许对SRAM这样的
     存储器,每次读写时包含于或非之类的操作模式并没有意义,而针对LCD这样
     的现实缓冲区,读写数据时加入于或非操作就有相当的意义了。为了保证接口
     的通用性,我们在所有的接口中都加入了读写模式 chModel这一参数。你也别
     觉得浪费,如果你的存储器操作不关心这些,你编写接口实例时,无视它就可
     以了。下面是对应的宏:

# define MEM_ACCESS_MODEL_NORMAL        0x00
# define MEM_ACCESS_MODEL_AND           0x01
# define MEM_ACCESS_MODEL_OR            0x02
# define MEM_ACCESS_MODEL_NOT           0x03
# define MEM_ACCESS_MODEL_XOR           0x04

         根据上面的讲解,再看下面的代码还会觉得头晕么?如果稍微有一点,那
     么你无视它们就好了。后面使用的时候,直接使用接口函数和宏即可,领会精
     神即可。一切为代码的可读性服务。

[实际应用]
     有待添加文字



[相关库函数]

    RD_Memory.h
    RD_Memory.c
    RD_DeviceID_LIB.h

RD_Memory.h


#ifndef _USE_ADT_MEMORY_STRUCTURE_H_
#define _USE_ADT_MEMORY_STRUCTURE_H_
/***********************************************************
*   声明库说明:存储器操作结构声明库                       *
*   版本:      v0.10                                      *
*   作者:      王卓然                                     *
*   创建日期:  2008年5月18日                              *
* -------------------------------------------------------- *
*  [支 持 库]                                              *
*   支持库名称:                                           *
*   需要版本:                                             *
*   支持库说明:                                           *
* -------------------------------------------------------- *
*  [版本更新]                                              *
*   修改:                                                 *
*   修改日期:                                             *
*   版本:                                                 *
* -------------------------------------------------------- *
*  [版本历史]                                              *
* -------------------------------------------------------- *
*  [使用说明]                                              *
***********************************************************/

/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_DeviceID_LIB.h"

/********************
*   系 统 宏 定 义  *
********************/

/*------------------*
*   常 数 宏 定 义  *
*------------------*/

/* 存储器操作权限 */
# define MEM_ACCESS_RANDOM_READ         0x0001
# define MEM_ACCESS_RANDOM_WRITE        0x0002
# define MEM_ACCESS_BLOCK_READ          0x0004
# define MEM_ACCESS_BLOCK_WRITE         0x0008
# define MEM_ACCESS_BLOCK_ERASE         0x0010
# define MEM_ACCESS_CHIP_ERASE          0x0020
# define MEM_ACCESS_BLOCK_LOCK          0x0040
# define MEM_ACCESS_CHIP_LOCK           0x0080  
# define MEM_ACCESS_UNLOCK_BLOCK        0x0100
# define MEM_ACCESS_UNLOCK_CHIP         0x0200
# define MEM_ACCESS_BLOCK_PROTECT       0x0400
# define MEM_ACCESS_CHIP_PROTECT        0x0800

/* 存储器操作模式 */
# define MEM_ACCESS_MODEL_NORMAL        0x00
# define MEM_ACCESS_MODEL_AND           0x01
# define MEM_ACCESS_MODEL_OR            0x02
# define MEM_ACCESS_MODEL_NOT           0x03
# define MEM_ACCESS_MODEL_XOR           0x04

/*------------------*
*   动 作 宏 定 义  *
*------------------*/

/********************
*  用户变量类型定义 *
********************/
typedef struct Embedded_Memory_Structure    MEM;
typedef struct Memory_Function_Table        MEM_FUN_TAB;

/*---------------------------------------------------------*
*   接口说明:  从指定的地址读取指定长度的数据             *
*   输入:      起始地址,读取长度,数据缓冲区指针         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_READ)
                (
                    UINT32 dwAddress,
                    UINT32 dwLength,
                    void *pData,
                    UINT8  chModel
                );
               
/*---------------------------------------------------------*
*   接口说明:  从指定的地址写入指定长度的数据             *
*   输入:      起始地址,写入长度,数据缓冲区指针         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (* _MEM_WRITE)
                (
                    UINT32 dwAddress,
                    UINT32 dwLength,
                    void *pData,
                    UINT8  chModel
                );
                              
/*---------------------------------------------------------*
*   接口说明:  从指定的地址读取整块的数据                 *
*   输入:      起始地址,块大小,数据缓冲区指针           *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (* _MEM_BLOCK_READ)
                (
                    UINT32 dwAddress,
                    UINT16 wBlockSize,
                    void *pData,
                    UINT8  chModel
                );
               
/*---------------------------------------------------------*
*   接口说明:  从指定的地址写入整块的数据                 *
*   输入:      起始地址,块大小,数据缓冲区指针           *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_BLOCK_WRITE)
                (
                    UINT32 dwAddress,
                    UINT16 wBlockSize,
                    void *pData,
                    UINT8  chModel
                );     
               
/*---------------------------------------------------------*
*   接口说明:  擦除指定的块                               *
*   输入:      块地址,填充的字符                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_BLOCK_ERASE)(UINT16 wBlock,BYTE chSymble);
              
/*---------------------------------------------------------*
*   接口说明:  整片擦除                                   *
*   输入:      填充的字符                                 *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_CHIP_ERASE)(BYTE chSymble);

/*---------------------------------------------------------*
*   接口说明:  整块锁定                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_BLOCK_LOCK)(UINT16 wBlock);

/*---------------------------------------------------------*
*   接口说明:  整片锁定                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_CHIP_LOCK)(void);

/*---------------------------------------------------------*
*   接口说明:  整块解锁                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_BLOCK_UNLOCK)(UINT16 wBlock);

/*---------------------------------------------------------*
*   接口说明:  整片解锁                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_CHIP_UNLOCK)(void);

/*---------------------------------------------------------*
*   接口说明:  整块保护                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_BLOCK_PROTECT)(UINT16 wBlock);

/*---------------------------------------------------------*
*   接口说明:  整片保护                                   *
*   输入:      无                                         *
*   输出:      操作是否成功                               *
*   调用函数:  --                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_CHIP_PROTECT)(void);

/*---------------------------------------------------------*
*   接口说明:  同一存储器内部拷贝                         *
*   输入:      源地址,长度,数据区地址,目标地址         *
*   输出:      操作是否成功                               *
*   调用函数:  无                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_COPY)
                (
                    UINT32 dwAddressFrom,
                    UINT32 dwLength,
                    UINT32 dwAddressTo,
                    UINT8  chModel
                );

/*---------------------------------------------------------*
*   接口说明:  存储器初始化                               *
*   输入:      无                                         *
*   输出:      无                                         *
*   调用函数:  无                                         *
*---------------------------------------------------------*/
typedef BOOL (*_MEM_INIT)(void);
               
/********************
*    结构体定义区   *
********************/

/*---------------------------------------------------------*
*   存储器结构体说明                                       *
* -------------------------------------------------------- *
*   名称            类型        说明                       *
* -------------------------------------------------------- *
*   ID           DEVICE_ID_TYPE 存储器类型定义,具体内容参 *
*                               见存储器类型定义宏。       *
*   wAccess      UINT16          操作属性                  *
*   dwAddress    UINT32         存储器起始地址             *
*   dwSize       UINT32         存储器大小                 *
*   wBlockSize   UINT16         在支持块写入的存储器中,用 *
*                               于指定存储块的大小。当操作 *
*                               属性支持块操作时,该值为0  *
*                               表示大小不限制。           *
*   pmftAccess   MEM_FUN_TAB    存储器操作虚函数表         *
*---------------------------------------------------------*/
struct Embedded_Memory_Structure
{
    DEVICE_ID       ID;
    UINT16          wAccess;   
    UINT32          dwAddress;
    UINT32          dwSize;
    UINT16          wBlockSize;
    MEM_FUN_TAB     *pmftAccess;
};

struct Memory_Function_Table
{
    _MEM_READ           fnRead;
    _MEM_WRITE          fnWrite;
    _MEM_BLOCK_READ     fnReadBlock;
    _MEM_BLOCK_WRITE    fnWriteBlock;
    _MEM_BLOCK_ERASE    fnEraseBlock;
    _MEM_CHIP_ERASE     fnEraseChip;
   
    _MEM_BLOCK_LOCK     fnLockBlock;
    _MEM_CHIP_LOCK      fnLockChip;
    _MEM_BLOCK_UNLOCK   fnUnlockBlock;
    _MEM_CHIP_UNLOCK    fnUnlockChip;
    _MEM_BLOCK_PROTECT  fnProtectBlock;
    _MEM_CHIP_PROTECT   fnProtectChip;
   
    _MEM_COPY           fnCopy;
    _MEM_INIT           fnInitial;
};


/********************
*   函 数 引 用 区  *
********************/
extern BOOL MEM_Read_Byte
            (
                MEM *pmType,
                UINT32 dwAddress,
                BYTE *pchData,
                UINT8 chModel
            );
extern BOOL MEM_Write_Byte
            (
                MEM *pmType,
                UINT32 dwAddress,
                BYTE *pchData,
                UINT8 chModel
            );
extern BOOL MEM_Read
            (
                MEM *pmType,
                UINT32 dwAddress,
                UINT32 dwLength,
                void *pData,
                UINT8 chModel
            );
extern BOOL MEM_Write
            (
                MEM *pmType,
                UINT32 dwAddress,
                UINT32 dwLength,
                void *pData,
                UINT8 chModel
            );
extern BOOL MEM_Copy
        (
            MEM *pmTypeFrom,
            UINT32 dwAddressFrom,
            UINT32 dwLength,
            MEM *pmTypeTo,
            UINT32 dwAddressTo,
            void *pBuffer,
            UINT16 wBufferSize,
            UINT8  chModel
        );
        
/********************
*   全局变量引用区  *
********************/

#endif




RD_Memory.c


/***********************************************************
*   函数库说明:存储器操作结构函数库                       *
*   版本:      v0.10                                      *
*   作者:      王卓然                                     *
*   创建日期:  2008年5月18日                              *
* -------------------------------------------------------- *
*  [支 持 库]                                              *
*   支持库名称:                                           *
*   需要版本:                                             *
*   支持库说明:                                           *
* -------------------------------------------------------- *
*  [版本更新]                                              *
*   修改:                                                 *
*   修改日期:                                             *
*   版本:                                                 *
* -------------------------------------------------------- *
*  [版本历史]                                              *
* -------------------------------------------------------- *
*  [使用说明]                                              *
***********************************************************/

/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"
# include "RD_ADT_Memory.h"

/********************
*   系 统 宏 定 义  *
********************/

/*------------------*
*   常 数 宏 定 义  *
*------------------*/
#ifndef MEM_COPY_DEFAULT_BUFFER_SIZE
    # define MEM_COPY_DEFAULT_BUFFER_SIZE       8
#endif
/*------------------*
*   动 作 宏 定 义  *
*------------------*/

/********************
*  模块结构体定义区 *
********************/

/********************
*   函 数 声 明 区  *
********************/

/********************
*   模块函数声明区  *
********************/
BOOL MEM_Read_Byte
            (
                MEM *pmType,
                UINT32 dwAddress,
                BYTE *pchData,
                UINT8 chModel
            );
BOOL MEM_Write_Byte
            (
                MEM *pmType,
                UINT32 dwAddress,
                BYTE *pchData,
                UINT8 chModel
            );
BOOL MEM_Read
            (
                MEM *pmType,
                UINT32 dwAddress,
                UINT32 dwLength,
                void *pData,
                UINT8 chModel
            );
BOOL MEM_Write
            (
                MEM *pmType,
                UINT32 dwAddress,
                UINT32 dwLength,
                void *pData,
                UINT8 chModel
            );
BOOL MEM_Copy
        (
            MEM *pmTypeFrom,
            UINT32 dwAddressFrom,
            UINT32 dwLength,
            MEM *pmTypeTo,
            UINT32 dwAddressTo,
            void *pBuffer,
            UINT16 wBufferSize,
            UINT8  chModel
        );
/********************
*   模块变量声明区  *
********************/

/********************
*   全局变量声明区  *
********************/


/***********************************************************
*   函数说明:  存储器间数据拷贝指令                       *
*   输入:      源类型,地址,数据长度,                   *
*               目标类型,目标地址,缓冲区地址             *
*   输出:      操作是否成功                               *
*   调用函数:  fnCopy()                                   *
***********************************************************/
BOOL MEM_Copy
        (
            MEM *pmTypeFrom,
            UINT32 dwAddressFrom,
            UINT32 dwLength,
            MEM *pmTypeTo,
            UINT32 dwAddressTo,
            void *pBuffer,
            UINT16 wBufferSize,
            UINT8  chModel
        )
{
    if  (
                (pmTypeFrom == NULL)
            ||  (pmTypeTo == NULL)
            ||  (pmTypeFrom->dwAddress + dwAddressFrom == NULL)
            ||  (pmTypeTo->dwAddress + dwAddressTo == NULL)
            ||  (dwAddressFrom + dwLength >= pmTypeTo->dwSize)
        )
    {
        /* 强壮性检测 */
        return FALSE;
    }
   
    //_PE3 = LOW;
    if (pmTypeFrom->ID.ID == pmTypeTo->ID.ID)
    {
        /* 同一存储块内部数据的拷贝 */
        
        //代码优化部分
        if (pmTypeFrom->ID._.Type == DID_MEM_DIRECT_ACCESS_SRAM)
        {
            BYTE *pchFrom = (BYTE *)(pmTypeFrom->dwAddress + dwAddressFrom);
            BYTE *pchTo = (BYTE *)(pmTypeTo->dwAddress + dwAddressTo);
            
            switch (chModel)
            {
                case MEM_ACCESS_MODEL_AND:
                    while(dwLength--)
                    {
                        *pchFrom++ &= *pchTo++;
                    }
                    break;
                case MEM_ACCESS_MODEL_OR:
                    while(dwLength--)
                    {
                        *pchFrom++ |= *pchTo++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NOT:
                    while(dwLength--)
                    {
                        UINT8 chTempData = *pchTo++;
                        *pchFrom++ = ~chTempData;
                    }
                    break;
                case MEM_ACCESS_MODEL_XOR:
                    while(dwLength--)
                    {
                        *pchFrom++ ^= *pchTo++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NORMAL:
                default:
                    while(dwLength--)
                    {
                        *pchFrom++ = *pchTo++;
                    }
            }

            return TRUE;
        }
        
        if (pmTypeFrom->pmftAccess != NULL)
        {
            _MEM_COPY fnFunction = pmTypeFrom->pmftAccess->fnCopy;
            
            if (fnFunction != NULL)
            {
                if (
                        fnFunction
                            (
                                pmTypeFrom->dwAddress + dwAddressFrom,
                                dwLength,
                                pmTypeFrom->dwAddress + dwAddressTo,
                                chModel
                            )
                   )
                {
                    return TRUE;
                }
                //如果返回FALSE,则尝试使用普通的拷贝方式
                           
            }
        }
        else
        {
            return FALSE;
        }
    }
   
   
   
    {
        /* 不同存储块内部数据的拷贝         */
        /* 或者同一存储块内没有优化拷贝函数 */
        BYTE chBuffer[MEM_COPY_DEFAULT_BUFFER_SIZE] = {0};
        BYTE *pchBuffer = NULL;
        UINT16 wSize = 0;
        UINT32 dwOffSet = 0;
        
        if (pBuffer == NULL)
        {
            /* 没有额外的缓冲区 */
            pchBuffer = chBuffer;
            wSize = sizeof(chBuffer);
        }
        else
        {
            /* 有额外的缓冲区 */
            pchBuffer = pBuffer;
            wSize = wBufferSize;
        }
        
        do
        {
            UINT16 wTempSize = dwLength >= wSize ?
                                wSize : dwLength;
            
            /* 把数据读取到缓冲区 */
            if (
                !MEM_Read
                    (
                        pmTypeFrom,
                        dwAddressFrom + dwOffSet,
                        wTempSize,
                        pchBuffer,
                        chModel
                    )
               )
            {
                //操作失败
                return FALSE;
            }
            
            /* 把缓冲区里面的数据写到目标存储器里 */
            if (
                !MEM_Write
                    (
                        pmTypeTo,
                        dwAddressTo + dwOffSet,
                        wTempSize,
                        pchBuffer,
                        chModel
                    )
               )
            {
                //操作失败
                return FALSE;
            }
            
            dwOffSet += wTempSize;
            dwLength -= wTempSize;
        }
        while(dwLength != 0);
    }
   
    return TRUE;
}

/***********************************************************
*   函数说明:  函数选择器存储器读取                       *
*   输入:      类型,保存数据的地址                       *
*   输出:      操作是否成功                               *
*   调用函数:  fnRead()                                   *
***********************************************************/
BOOL MEM_Read_Byte(MEM *pmType,UINT32 dwAddress,BYTE *pchData,UINT8 chModel)
{
    if (
            (pmType == NULL)
        ||  (pchData == NULL)
        ||  (dwAddress >= pmType->dwSize)
       )
    {
        return FALSE;
    }
   
    //代码优化部分
    if (pmType->ID._.Type == DID_MEM_DIRECT_ACCESS_SRAM)
    {
        switch (chModel)
            {
                case MEM_ACCESS_MODEL_AND:
                    (*pchData) &= (*((BYTE *)((pmType->dwAddress) + dwAddress)));
                    break;
                case MEM_ACCESS_MODEL_OR:
                    (*pchData) |= (*((BYTE *)((pmType->dwAddress) + dwAddress)));
                    break;
                case MEM_ACCESS_MODEL_NOT:
                    (*pchData) = ~(*((BYTE *)((pmType->dwAddress) + dwAddress)));
                    break;
                case MEM_ACCESS_MODEL_XOR:
                    (*pchData) ^= (*((BYTE *)((pmType->dwAddress) + dwAddress)));
                    break;
                case MEM_ACCESS_MODEL_NORMAL:
                default:
                    (*pchData) = (*((BYTE *)((pmType->dwAddress) + dwAddress)));
                    break;
            }
        
        
        return TRUE;
    }
   
    if (pmType->pmftAccess != NULL)
    {
        _MEM_READ fnFunction = pmType->pmftAccess->fnRead;
        
        if (fnFunction != NULL)
        {
            return fnFunction
                        (
                            (pmType->dwAddress) + dwAddress,
                            1,
                            pchData,
                            chModel
                        );
        }
    }
   
    return FALSE;
}


/***********************************************************
*   函数说明:  函数选择器存储器写入                       *
*   输入:      类型,保存数据的地址                       *
*   输出:      操作是否成功                               *
*   调用函数:  fnRead()                                   *
***********************************************************/
BOOL MEM_Write_Byte(MEM *pmType,UINT32 dwAddress,BYTE *pchData,UINT8 chModel)
{
    if (
            (pmType == NULL)
        ||  (pchData == NULL)
        ||  (dwAddress >= pmType->dwSize)
       )
    {
        return FALSE;
    }
   
    //代码优化部分
    if (pmType->ID._.Type == DID_MEM_DIRECT_ACCESS_SRAM)
    {
        switch (chModel)
            {
                case MEM_ACCESS_MODEL_AND:
                    (*((BYTE *)((pmType->dwAddress) + dwAddress))) &= (*pchData);
                    break;
                case MEM_ACCESS_MODEL_OR:
                    (*((BYTE *)((pmType->dwAddress) + dwAddress))) |= (*pchData);
                    break;
                case MEM_ACCESS_MODEL_NOT:
                    (*((BYTE *)((pmType->dwAddress) + dwAddress))) = ~(*pchData);
                    break;
                case MEM_ACCESS_MODEL_XOR:
                    (*((BYTE *)((pmType->dwAddress) + dwAddress))) ^= (*pchData);
                    break;
                case MEM_ACCESS_MODEL_NORMAL:
                default:
                    (*((BYTE *)((pmType->dwAddress) + dwAddress))) = (*pchData);
                    break;
            }
        
        return TRUE;
    }
   
    if (pmType->pmftAccess != NULL)
    {
        _MEM_READ fnFunction = pmType->pmftAccess->fnWrite;
        
        if (fnFunction != NULL)
        {
            return fnFunction
                        (
                            (pmType->dwAddress) + dwAddress,
                            1,
                            pchData,
                            chModel
                        );
        }
    }
   
    return FALSE;
}


/***********************************************************
*   函数说明:  函数选择器存储器字节流读取                 *
*   输入:      类型,保存数据的地址                       *
*   输出:      操作是否成功                               *
*   调用函数:  fnRead()                                   *
***********************************************************/
BOOL MEM_Read(MEM *pmType,UINT32 dwAddress,UINT32 dwLength,
                void *pData,UINT8 chModel)
{
    if (
            (pmType == NULL)
        ||  (pData == NULL)
        ||  ((dwAddress + dwLength) >= pmType->dwSize)
       )
    {
        return FALSE;
    }
   
    //代码优化部分
    if (pmType->ID._.Type == DID_MEM_DIRECT_ACCESS_SRAM)
    {
        BYTE *pchData = pData;
        BYTE *pchSCR = ((BYTE *)((pmType->dwAddress) + dwAddress));
        
            switch (chModel)
            {
                case MEM_ACCESS_MODEL_AND:
                    while(dwLength--)
                    {
                        *pchData++ &= *pchSCR++;
                    }
                    break;
                case MEM_ACCESS_MODEL_OR:
                    while(dwLength--)
                    {
                        *pchData++ |= *pchSCR++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NOT:
                    while(dwLength--)
                    {
                        UINT8 chTempData = *pchSCR++;
                        *pchData++ = ~chTempData;
                    }
                    break;
                case MEM_ACCESS_MODEL_XOR:
                    while(dwLength--)
                    {
                        *pchData++ ^= *pchSCR++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NORMAL:
                default:
                    while(dwLength--)
                    {
                        *pchData++ = *pchSCR++;
                    }
                    break;
            }
        
        
        return TRUE;
    }
   
    if (pmType->pmftAccess != NULL)
    {
        _MEM_READ fnFunction = pmType->pmftAccess->fnRead;
        
        if (fnFunction != NULL)
        {
            return fnFunction
                        (
                            (pmType->dwAddress) + dwAddress,
                            dwLength,
                            pData,
                            chModel
                        );
        }
    }
   
    return FALSE;
}


/***********************************************************
*   函数说明:  函数选择器存储器写入                       *
*   输入:      类型,保存数据的地址                       *
*   输出:      操作是否成功                               *
*   调用函数:  fnRead()                                   *
***********************************************************/
BOOL MEM_Write(MEM *pmType,UINT32 dwAddress,UINT32 dwLength,
                void *pData,UINT8 chModel)
{
    if (
            (pmType == NULL)
        ||  (pData == NULL)
        ||  ((dwAddress + dwLength) >= pmType->dwSize)
       )
    {
        return FALSE;
    }
   
    //代码优化部分
    if (pmType->ID._.Type == DID_MEM_DIRECT_ACCESS_SRAM)
    {
        BYTE *pchData = pData;
        BYTE *pchSCR = ((BYTE *)((pmType->dwAddress) + dwAddress));
        
        switch (chModel)
            {
                case MEM_ACCESS_MODEL_AND:
                    while(dwLength--)
                    {
                        *pchSCR++ &= *pchData++;
                    }
                    break;
                case MEM_ACCESS_MODEL_OR:
                    while(dwLength--)
                    {
                        *pchSCR++ |= *pchData++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NOT:
                    while(dwLength--)
                    {
                        UINT8 chTempData = *pchData++;
                        *pchSCR++ = ~chTempData;
                    }
                    break;
                case MEM_ACCESS_MODEL_XOR:
                    while(dwLength--)
                    {
                        *pchSCR++ ^= *pchData++;
                    }
                    break;
                case MEM_ACCESS_MODEL_NORMAL:
                default:
                    while(dwLength--)
                    {
                        *pchSCR++ = *pchData++;
                    }
                    break;
            }
        
        
        return TRUE;
    }
   
    if (pmType->pmftAccess != NULL)
    {
        _MEM_READ fnFunction = pmType->pmftAccess->fnWrite;
        
        if (fnFunction != NULL)
        {
            return fnFunction
                        (
                            (pmType->dwAddress) + dwAddress,
                            dwLength,
                            pData,
                            chModel
                        );
        }
    }
   
    return FALSE;
}


RD_DeviceID_LIB.h

#ifndef _USE_DEIVCE_ID_LIB_H_
#define _USE_DEIVCE_ID_LIB_H_
/***********************************************************
*   声明库说明:设备ID分配说明库                           *
*   版本:      v0.20                                      *
*   作者:      王卓然                                     *
*   创建日期:  2008年2月19日                              *
* -------------------------------------------------------- *
*  [支 持 库]                                              *
*   支持库名称:                                           *
*   需要版本:                                             *
*   支持库说明:                                           *
* -------------------------------------------------------- *
*  [版本更新]                                              *
*   修改:      王卓然                                     *
*   修改日期:  2008年5月20日                              *
*   版本:      v0.20                                      *
* -------------------------------------------------------- *
*  [版本历史]                                              *
*       v0.10   规定了基本的设备ID原则:                   *
*               a、ID的类型由 typdef 定义的DEVICE_ID_TYPE  *
*                 来统一定义。第一个版本DEVICE_ID_TYPE为   *
*                 UINT16型变量。                           *
*               b、ID的最高位用来区分设备是否为实际硬件的  *
*                 虚拟设备。                               *
*       v0.20   重新分配了ID的功能域,其中,高字节表征设备 *
*               类型,低字节表征该类型下的不同设备实例。   *
* -------------------------------------------------------- *
*  [使用说明]                                              *
*           1、 该库用于统一给已有的和未来的设备分配ID。   *
*           2、 以后所有的设备都根据该头文件提供的ID宏来处 *
*               理设备ID的问题。这样便于在以后更新的版本出 *
*               现时或应用新的ID分配原则时不会产生代码级别 *
*               的ID兼容问题。                             *
*           3、 由于ID本身在设计时是允许日后变动的,所以程 *
*               序中不应该使用具体的数值作为设备的具体区别 *
*               程序在代码级别,应该使用ID宏作为设备区分依 *
*               据,编译后的系统应该根据ID库版本来区别具体 *
*               数字所代表的设备ID。                       *
*           4、 对于兼容的ID库版本,不需要保留备份版本;对 *
*               于改变了编码规则的版本,应该保留之前的版本 *
*               作为对从前产品的ID索引和查询之用。         *
*           5、 这是基础头文件。                           *
***********************************************************/

/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"

/********************
*   系 统 宏 定 义  *
********************/

/*------------------*
*   常 数 宏 定 义  *
*------------------*/
# define DEVICE_ID_HIGH_BIT     ((sizeof(DEVICE_ID_TYPE) << 3)-1)

# define DID_MEM_DEFAULT                        0x0000
# define DID_MEM_DIRECT_ACCESS_SRAM             0x0000
# define DID_MEM_INDIRECT_ACCESS_SRAM           0x0100
# define DID_MEM_INTERNAL_EEPROM                0x0200
# define DID_LCD_SED1335_FRONT                  0x0300
# define DID_LCD_SED1335_MIDDLE                 0x0400
# define DID_LCD_SED1335_BACKGROUND             0x0500

/*------------------*
*   动 作 宏 定 义  *
*------------------*/

/********************
*  用户变量类型定义 *
********************/
typedef UINT16 DEVICE_ID_TYPE;

typedef union DeviceID
{
    UINT16 ID;
    struct
    {
        UINT8 Device;
        UINT8 Type;
    }_;
}DEVICE_ID;

/********************
*    结构体定义区   *
********************/

/********************
*   函 数 引 用 区  *
********************/

/********************
*   全局变量引用区  *
********************/
# define DEVICE_ID_LIB_VERSION      0x00020000

#endif

出0入0汤圆

发表于 2008-5-22 23:26:35 | 显示全部楼层
我正在研究你的《[交流]如何在12864上绘图》,写得很不错, 英雄出少年啊,
      傻孩子是个人才啊.

出0入0汤圆

发表于 2008-5-22 23:30:29 | 显示全部楼层
傻孩子的又一伟大创举,一直会跟踪下去的,另外很佩服傻孩子的代码结构,很清晰

出0入0汤圆

发表于 2008-5-22 23:52:35 | 显示全部楼层
支持一下,跟班学习:-)

出0入0汤圆

发表于 2008-5-23 00:08:16 | 显示全部楼层
我喜欢Linux的一个原因是开源,另一个原因是在Linux眼里一切都是file(网络设备除外)。

傻孩子这里提出的这个“存储器”的抽象,个人感觉和Linux下的file很像。最近我也有一些想法,能不能把单片机中的各种外设资源设计一个统一接口的抽象呢?你的这个“存储器”抽象给我一些启发。

另,傻孩子的代码又是典型的C语言实现面向对象啊,赞!

出0入0汤圆

发表于 2008-5-23 00:14:46 | 显示全部楼层
---------------------------------------
因此,我们必须利用m_wType来表征存储器类型同时还要能区别该对象是该
      存储器类型的第几个实例。显然,同一个存储器中的对象拥有相同的存储器
      类型和相同的实例编号,而不同存储器虽然可能拥有相同的存储器类型号,
      却拥有不同的实例编号。
---------------------------------------
太像了,这就是Linux中的主设备号,次设备号。傻孩子是仿照着Linux进行这个抽象设计的吗?
如果是,干嘛不直接引进“设备文件”这个抽象某种简化版本呢?我以为设备文件(分为:block类型,char类型)这个概念能抽象更多的设备。
而你的“存储器”抽象,个人感觉只能抽象block类型的设备。比如串口,按键这类设备能否用你的方法抽象呢?

出0入296汤圆

 楼主| 发表于 2008-5-23 00:20:17 | 显示全部楼层
实际上……这也许就是Linux下的设备文件的一个最原始的形式的模拟吧……我不很确定,因为我没有学过Linux。
慢慢来,不必要刚开始就提高到那种程度。大家慢慢研究,最后自然会达到那种程度,一开始就弄成那样,反而让很多人张二和尚摸不着头脑。不然何来“一步一步”的说法呢?

出0入0汤圆

发表于 2008-5-23 00:28:26 | 显示全部楼层
哈哈,果然是。对这个设计极为感兴趣,可惜太忙了,不过一定抽空参与这个东东。

出0入296汤圆

 楼主| 发表于 2008-5-23 00:28:49 | 显示全部楼层
不,我没有学过Linux……一直想读它们的源代码,但是一直没有机会……
这次应该是碰巧吧……反正思考已经写出来了……很自然得出这样的结论。
不过有Linux在前面,至少坚定我这样划分是正确的。

出0入296汤圆

 楼主| 发表于 2008-5-23 00:35:23 | 显示全部楼层
串口和按键仍然可以抽象。
方法就是对应缓冲区。按键有两种方法,一种是按键缓冲区,这种方法和串口的方法一样
后面说明。对于按键地图,则直接可以使用Block来抽象了。

对于缓冲区,我们在接口处做文章即可。例如,Read,无视地址,只从依次从队列中取数
据,Write,无视地址,依次向队列中写数据即可。

实际上,我并不希望进行这种形式的抽象。串口我是列入总线这一大类的……总线有自己
的处理方法……

但是从名称上来看char类型应该是所谓的“流文件”吧……我推断处理方法应该也是类似的。

出0入0汤圆

发表于 2008-5-23 00:54:03 | 显示全部楼层
暂时来说只是对串口如何抽象比较感兴趣,不过一直也没看到类似的例子,先顶一下……

出0入0汤圆

发表于 2008-5-23 01:07:29 | 显示全部楼层
你说的read、write无视地址依次读入,依次写入,这就是我认为你不能抽象为“MEM”的原因。
因为在我头脑中把你的这个“MEM”看成了block文件,而你说的依次(顺序)读取/写入,正是
char类型文件的特点,不支持随机访问。

对于Linux我也是心向往之,有一本内核的书看了好几遍,还是一只半解,只是进来看了点Linux
设备驱动编写,对设备文件这个东西有丁点了解。

让我猜测下你说的“总线”,这个应该是你对I2C,SPI,Uart等的又一种抽象,你会给出一个类似的
统一的接口,比如读,写,方式控制等。当然,如果是这样的抽象,Uart归入这一类抽象应该更好。
我的想法是在这类总线抽象基础上,把连接于这些总线的设备再抽象为一个“文件”。因为我们使用这些
总线归根结底为使用连于这些总线上的设备,这样上层代码就根本不用考虑“总线”的概念了。

你的想法里,可能还有个运算单元抽象?这个会是什么呢?
run( A, cmd)  让A运行cmd指令吗?

出0入0汤圆

发表于 2008-5-23 01:27:06 | 显示全部楼层
掂啊,又出精品了.
很晚了,别太累了

出0入50汤圆

发表于 2008-5-23 08:00:34 | 显示全部楼层
楼主要细水常流,^_^,注意身体,年轻的时候不要太过透支。

支持!别的就不多说了。

友情提醒楼主:这个帖子穿裤子是早晚的事情,目前天气气温开始偏高,楼主务必做好防暑降温工作!

出0入0汤圆

发表于 2008-5-23 08:40:52 | 显示全部楼层
不顶对不起你啊

出0入0汤圆

发表于 2008-5-23 08:48:08 | 显示全部楼层
老实说,开源的精神是一回事儿,但我宁愿楼主事先把《现代操作系统》以及《Linux驱动程序设计》这两本书通读三遍、并有适当的实践经验后再重新考虑怎么设计有自己风格的系统程序

东一榔头西一棒,想到哪儿算哪儿的开发年代,十多年前就已经该结束了

或者说得更直接一些,个人认为,楼主若是认真考虑一下【怎么用AVR作出X的最小化实现方案】,可能会远比从零开始的琢磨什么仿WindowsGDI,效果要好得多……
毕竟,我们是生活在一个充满了标准的年代,而不符合标准的东西,哪怕是M$出品,也要先碰碰壁才有机会……

出0入0汤圆

发表于 2008-5-23 08:50:57 | 显示全部楼层
跟着学习

出0入93汤圆

发表于 2008-5-23 08:58:27 | 显示全部楼层
标记,拜读

出0入0汤圆

发表于 2008-5-23 08:58:29 | 显示全部楼层
狂顶!!!傻孩子真是个无私的“志愿者”
     
     强烈关注..............

出0入0汤圆

发表于 2008-5-23 09:12:57 | 显示全部楼层
傻孩子 好样的!注意身体!

出0入296汤圆

 楼主| 发表于 2008-5-23 09:58:34 | 显示全部楼层
.to 【17楼】 watercat
    这就是所谓的DIY。你们可以DIY航模,DIY四轴飞行器,热衷于DIY下载器,就不
允许我DIY自己喜欢的代码结构?你说的书,我都有计划要阅读,问题在于,你说过
适当的经验,我这种做法也是积累适当经验的一种方法啊。
    永远只想把别人的东西简化,做外包,永远没有自己的核心技术。永远只会想遵
守别人的协议。当然,一开始,我们需要去遵守,这是顺应时代的,一旦等我们羽翼
丰满的时候,就要有中国开发人员能力和中国实力的证明——让别人遵守我们自己的
协议。现在做一点兴趣爱好,算是聊以自_慰,未尝不可?
    你也许不可以当飞行员,但是你绝对有机会做一把航模的操作手。DIY并不
代表我排斥这些已有的标准,你们也许用工作的眼光在看待我所做的事情,而我恰恰
好并不工作,立场不同,自然观点不同。我可以游戏代码,而对你们很多人来说,这
就是不可容忍的——因为不符合一些工业标准。

    现实中,我碰壁的次数也许对大部分人来说,已经是难以想象的程度。然而,因
为坚持,我才有今天。坚持一天两天甚至三天,叫做虎头蛇尾。坚持一年两年三年,
叫做固执,如果一直坚持不算超级固执也可以说成是执著了吧?

    简而言之,您回复中的一个关键字就是“开发”,而我帖子的关键字是“研究”,
不是一个目的,自然走的路不同哈。

    谢谢【17楼】 watercat 的关注。很希望和您这样的人多交流。

出0入296汤圆

 楼主| 发表于 2008-5-23 10:08:42 | 显示全部楼层
to 【13楼】 ifree64  
    对于总线,我之前有过抽象的尝试,较为成功。
    我把这种总线称之为管道(Pipe)。管道实际上在外界看来就是
一个简单地输入和输出双缓冲,事实上,管道屏蔽了底层所有的硬件
操作细节,你可以理解为我的管道实现了Intel网络中链路层以上的
内容,也就是网络层。我们建立的管道实例就是建立了链路层。
    可以把管道抽象为你所说的流文件,实际上仍然可以用Mem来抽象
不过这种抽象是否合适,还有待时间来检验。

出0入296汤圆

 楼主| 发表于 2008-5-23 10:16:38 | 显示全部楼层

>>实例一 SED1335驱动


有待添加文字



测试实例

1、在SED1335屏幕上滚动显示和擦除ASCII码字符。并添加下划虚线。
2、通过MEM通用接口操作存储器,实现存储器操作与硬件无关。


点击此处下载 ourdev_292912.rar(文件大小:435K) (原文件名:Fool_GUI_Demo.rar)


适用LCD SED1335自身的现存实现的双缓冲技术,由于未进行任何优化,单字节写屏,一秒钟
只有8帧左右的速度。后面可以优化。
点击此处下载 ourdev_293334.rar(文件大小:435K) (原文件名:Fool_GUI_Demo双缓冲演示.rar)

至此,第一章,物质基础决定上层建筑到此结束。我们已经成功的将LCD抽象成一个
内存储器。并实现使用硬件无关的内存储器操作接口向屏幕缓冲区写入数据。从第
二章开始,我们将开始讨论字符(位图)的任意位置显示技术。建立在第一章提供
的平台之上,我们的GUI已经是一个硬件无关的跨平台GUI了。




……

/********************
*  用户变量类型定义 *
********************/
typedef struct DisplayDeviceInterface DDI;

/********************
*  模块结构体定义区 *
********************/
struct DisplayDeviceInterface
{
    MEM *pmemWindow;
    UINT16 wWidth;
    UINT16 wHeight;
};

/********************
*   函 数 引 用 区  *
********************/
MEM *DDI_Updata(DDI *pddiTarget,MEM *pmemBuffer);

……


/* 存储器操作模式 */
# define MEM_ACCESS_MODEL_NORMAL        0x00
# define MEM_ACCESS_MODEL_AND           0x01
# define MEM_ACCESS_MODEL_OR            0x02
# define MEM_ACCESS_MODEL_NOT           0x03
# define MEM_ACCESS_MODEL_XOR           0x04
# define MEM_ACCESS_MODEL_INSTEAD       0x80                /*所谓INSTEAD模式意思就是取代 */
                                                            /*如果两个存储块无法直接取代,*/
                                                            /*则直接用覆盖拷贝来替代,否则*/
                                                            /*根据具体的存储器特性执行取代*/
                                                            /*操作,比如LCD中,用一个缓冲 */
                                                            /*取代原有的显示区域,则只需要*/
                                                            /*修改LCD显示区域的起始地址。 */




/***********************************************************
*   函数说明:  设备刷新程序                               *
*   输入:      设备接口,缓冲区                           *
*   输出:      缓冲区,如果刷新失败,则返回NULL           *
*   调用函数:  无                                         *
***********************************************************/
MEM *DDI_Updata(DDI *pddiTarget,MEM *pmemBuffer)
{
    if (
            (pddiTarget == NULL)
        ||  (pddiTarget->pmemWindow == NULL)
       )
    {
        /* 如果输入的设备为空,则不作任何处理 */
        return pmemBuffer;
    }
   
    if (
            (pmemBuffer == NULL)
        ||  (pmemBuffer == pddiTarget->pmemWindow)
       )
    {
        /* 无缓冲区的情况,直接向显存写数据 */
        return pddiTarget->pmemWindow;         
    }
   
    /* 存储器块拷贝 */
    if (!MEM_Copy
        (
            pmemBuffer,
            0,
            pmemBuffer->dwSize,
            pddiTarget->pmemWindow,
            0,
            NULL,
            0,
            /*这里是一个特殊的方式,对应可能的优化操作*/
            MEM_ACCESS_MODEL_INSTEAD                                      
        )
       )
    {
        /* 拷贝失败 */
        return NULL;
    }
   
    if (pddiTarget->pmemWindow->ID.ID == pmemBuffer->ID.ID)
    {
        /* 同一存储器中的操作,拷贝通过修改显示地址,实现*/
        /* 了优化,此时,就必须交换缓冲区和显示区的地址  */
        UINT32 dwAddress =pddiTarget->pmemWindow->dwAddress;
        
        /* 交换存储区域 */
        pddiTarget->pmemWindow->dwAddress = pmemBuffer->dwAddress;
        pmemBuffer->dwAddress = dwAddress;
    }
   
    return pmemBuffer;
}


static MEM_FUN_TAB s_mftLCDInterfaceFront =
                    {
                        LCD_SED1335_Read_Display_Data_Stream,
                        LCD_SED1335_Write_Display_Data_Stream,
                        NULL,                               //ReadBlock
                        NULL,                               //WriteBlock
                        NULL,                               //EraseBlock
                        LCD_SED1335_CLS_Front,              //EraseChip
                        NULL,                               //LockBlock
                        NULL,                               //LockChip
                        NULL,                               //UnlockBlock
                        NULL,                               //UnlockChip
                        NULL,                               //ProtectBlock
                        NULL,                               //ProtectChip
                        LCD_SED1335_Copy_Front,             //Copy
                        LCD_SED1335_INIT
                    };
static MEM_FUN_TAB s_mftLCDInterfaceMiddle =
                    {
                        LCD_SED1335_Read_Display_Data_Stream,
                        LCD_SED1335_Write_Display_Data_Stream,
                        NULL,                               //ReadBlock
                        NULL,                               //WriteBlock
                        NULL,                               //EraseBlock
                        LCD_SED1335_CLS_Middle,             //EraseChip
                        NULL,                               //LockBlock
                        NULL,                               //LockChip
                        NULL,                               //UnlockBlock
                        NULL,                               //UnlockChip
                        NULL,                               //ProtectBlock
                        NULL,                               //ProtectChip
                        LCD_SED1335_Copy_Middle,            //Copy
                        LCD_SED1335_INIT
                    };
static MEM_FUN_TAB s_mftLCDInterfaceBackground =
                    {
                        LCD_SED1335_Read_Display_Data_Stream,
                        LCD_SED1335_Write_Display_Data_Stream,
                        NULL,                               //ReadBlock
                        NULL,                               //WriteBlock
                        NULL,                               //EraseBlock
                        LCD_SED1335_CLS_Background,         //EraseChip
                        NULL,                               //LockBlock
                        NULL,                               //LockChip
                        NULL,                               //UnlockBlock
                        NULL,                               //UnlockChip
                        NULL,                               //ProtectBlock
                        NULL,                               //ProtectChip
                        LCD_SED1335_Copy_Background,        //Copy
                        LCD_SED1335_INIT
                    };
static MEM_FUN_TAB s_mftLCDInterface =
                    {
                        LCD_SED1335_Read_Display_Data_Stream,
                        LCD_SED1335_Write_Display_Data_Stream,
                        NULL,                               //ReadBlock
                        NULL,                               //WriteBlock
                        NULL,                               //EraseBlock
                        NULL,                               //EraseChip
                        NULL,                               //LockBlock
                        NULL,                               //LockChip
                        NULL,                               //UnlockBlock
                        NULL,                               //UnlockChip
                        NULL,                               //ProtectBlock
                        NULL,                               //ProtectChip
                        LCD_SED1335_Copy_Background,        //Copy
                        LCD_SED1335_INIT
                    };
/********************
*   全局变量声明区  *
********************/

MEM g_memLCDSED1335Front =
            {
                DID_LCD_SED1335,
                MEM_ACCESS_RANDOM_READ |
                MEM_ACCESS_RANDOM_WRITE |
                MEM_ACCESS_CHIP_ERASE,
                0,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                &s_mftLCDInterfaceFront
            };
MEM g_memLCDSED1335Middle =
            {
                DID_LCD_SED1335,
                MEM_ACCESS_RANDOM_READ |
                MEM_ACCESS_RANDOM_WRITE |
                MEM_ACCESS_CHIP_ERASE,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                &s_mftLCDInterfaceMiddle
            };
MEM g_memLCDSED1335Background =
            {
                DID_LCD_SED1335,
                MEM_ACCESS_RANDOM_READ |
                MEM_ACCESS_RANDOM_WRITE |
                MEM_ACCESS_CHIP_ERASE,
                LCD_SCREEN_GRAPHIC_DATA_COUNT<<1,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                &s_mftLCDInterfaceBackground
            };
MEM g_memLCDSED1335 =
            {
                DID_LCD_SED1335,
                MEM_ACCESS_RANDOM_READ |
                MEM_ACCESS_RANDOM_WRITE,
                LCD_SCREEN_GRAPHIC_DATA_COUNT * 3,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                LCD_SCREEN_GRAPHIC_DATA_COUNT,
                &s_mftLCDInterface
            };



/***********************************************************
*   函数说明:设置读写地址(光标地址)函数                 *
*   输入:    地址                                         *
*   输出:    无                                           *
*   调用函数:SEND_CMD()    SEND_DATA()                    *
***********************************************************/
void LCD_SED1335_CSRW(uint16 wAddress)
{
    SEND_CMD(LCD_CMD_CSRW);
    SEND_DATA(wAddress);
    SEND_DATA(wAddress>>8);
}


/***********************************************************
*   函数说明:LCD_SED1335数据流读取函数                    *
*   输入:    保存数据的指针,读取数据的大小               *
*   输出:    保存数据的指针                               *
*   调用函数:SEND_CMD()                                   *
***********************************************************/
BOOL LCD_SED1335_Read_Display_Data_Stream
                (
                    UINT32 dwAddress,
                    UINT32 dwLength,
                    void *pData,
                    UINT8  chModel
                )
{
    uint16 n = 0;
    uint16 wLength = dwLength;
    BYTE *pchData = pData;
    if (pchData == NULL)
    {
        //指针为空,无法读取任何数据
        return FALSE;
    }
    LCD_SED1335_CSRW(dwAddress);
   
    SEND_CMD(LCD_CMD_MREAD);
   
    //释放数据总线
    LCD_DATA_DDR = 0x00;
    LCD_DATA_OUT = 0xFF;
    #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
        REFRESH_VIRTUAL_PORT
    #endif
    LCD_WR = HIGH;
    LCD_CS = LOW;
    LCD_A0 = HIGH;
   
    switch (chModel)
    {
        case MEM_ACCESS_MODEL_XOR:
            for (n = 0;n < wLength;n++)
            {
                LCD_RD = LOW;                                          
                WDR();
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
                pchData[n] ^= LCD_DATA_IN;
                LCD_RD = HIGH;
            }
            break;
        case MEM_ACCESS_MODEL_NOT:
            for (n = 0;n < wLength;n++)
            {
                LCD_RD = LOW;                                          
                WDR();
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
                pchData[n] = ~LCD_DATA_IN;
                LCD_RD = HIGH;
            }
            break;
        case MEM_ACCESS_MODEL_OR:
            for (n = 0;n < wLength;n++)
            {
                LCD_RD = LOW;                                          
                WDR();
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
                pchData[n] |= LCD_DATA_IN;
                LCD_RD = HIGH;
            }
            break;
        case MEM_ACCESS_MODEL_AND:
            for (n = 0;n < wLength;n++)
            {
                LCD_RD = LOW;                                          
                WDR();
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
                pchData[n] &= LCD_DATA_IN;
                LCD_RD = HIGH;
            }
            break;
        case MEM_ACCESS_MODEL_NORMAL:
        default:
            for (n = 0;n < wLength;n++)
            {
                LCD_RD = LOW;                                          
                WDR();
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
                pchData[n] = LCD_DATA_IN;
                LCD_RD = HIGH;
            }
            break;
    }
    LCD_CS = HIGH;
   
    return TRUE;
}

/***********************************************************
*   函数说明:前图层清屏函数                               *
*   输入:    填充字符                                     *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
BOOL LCD_SED1335_CLS_Front(UINT8 chSymble)
{
    uint16 n = 0;
    uint8 Temp = 0;
   
   
    LCD_SED1335_CSRDIR(LCD_CURSOR_DIRECTION_RIGHT);
    LCD_SED1335_CSRW(0);
    SEND_CMD(LCD_CMD_MWRITE);
    LCD_CS = LOW;
   
    LCD_A0 = LOW;
    LCD_DATA_DDR = 0xff;
    LCD_DATA_OUT = chSymble;
    #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
        REFRESH_VIRTUAL_PORT
    #endif
    for (n = 0;n < LCD_SCREEN_GRAPHIC_DATA_COUNT;n++)
    {
        LCD_WR = LOW;
        WDR();
        LCD_WR = HIGH;
    }

    LCD_CS = HIGH;
   
    return TRUE;
}

/***********************************************************
*   函数说明:中图层清屏函数                               *
*   输入:    填充字符                                     *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
BOOL LCD_SED1335_CLS_Middle(UINT8 chSymble)
{
    uint16 n = 0;
    uint8 Temp = 0;
    LCD_SED1335_CSRDIR(LCD_CURSOR_DIRECTION_RIGHT);
    LCD_SED1335_CSRW(LCD_SCREEN_GRAPHIC_DATA_COUNT);
   
    SEND_CMD(LCD_CMD_MWRITE);
    LCD_CS = LOW;
   
    LCD_A0 = LOW;
    LCD_DATA_DDR = 0xff;
    LCD_DATA_OUT = chSymble;
    #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
        REFRESH_VIRTUAL_PORT
    #endif
    for (n = 0;n < LCD_SCREEN_GRAPHIC_DATA_COUNT;n++)
    {
        LCD_WR = LOW;
        WDR();
        LCD_WR = HIGH;
    }

    LCD_CS = HIGH;
   
    return TRUE;
}

/***********************************************************
*   函数说明:底图层清屏函数                               *
*   输入:    填充字符                                     *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
BOOL LCD_SED1335_CLS_Background(UINT8 chSymble)
{
    uint16 n = 0;
    uint8 Temp = 0;
   
    LCD_SED1335_CSRDIR(LCD_CURSOR_DIRECTION_RIGHT);
    LCD_SED1335_CSRW(LCD_SCREEN_GRAPHIC_DATA_COUNT << 1);
   
    SEND_CMD(LCD_CMD_MWRITE);
    LCD_CS = LOW;
   
    LCD_A0 = LOW;
    LCD_DATA_DDR = 0xff;
    LCD_DATA_OUT = chSymble;
    #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
        REFRESH_VIRTUAL_PORT
    #endif
    for (n = 0;n < LCD_SCREEN_GRAPHIC_DATA_COUNT;n++)
    {
        LCD_WR = LOW;
        WDR();
        LCD_WR = HIGH;
    }

    LCD_CS = HIGH;
   
    return TRUE;
}

/***********************************************************
*   函数说明:LCD_SED1335数据流发送函数                    *
*   输入:    要发送的数据指针,数据的长度                 *
*   输出:    无                                           *
*   调用函数:SEND_CMD()                                   *
***********************************************************/
BOOL LCD_SED1335_Write_Display_Data_Stream
            (
                UINT32 dwAddress,
                UINT32 dwLength,
                void *pData,
                UINT8  chModel
            )
{
    uint16 n = 0;
    uint8 Temp = 0;
    uint16 wLength = dwLength;
    BYTE *pchData = pData;
   
    if (pData == NULL)
    {
        return FALSE;
    }
    LCD_SED1335_CSRDIR(LCD_CURSOR_DIRECTION_RIGHT);

    switch (chModel)
    {
        case MEM_ACCESS_MODEL_XOR:
            
            for (n = 0;n < wLength;n++)
            {
                BYTE chData = 0;
                LCD_SED1335_CSRW(dwAddress + n);
                SEND_CMD(LCD_CMD_MREAD);
                chData = READ_DATA;
                LCD_SED1335_CSRW(dwAddress + n);
                SEND_CMD(LCD_CMD_MWRITE);
                SEND_DATA(chData ^ pchData[n])
            }
            break;
        case MEM_ACCESS_MODEL_NOT:
            LCD_SED1335_CSRW(dwAddress);
            for (n = 0;n < wLength;n++)
            {
                BYTE chData = 0;
                SEND_CMD(LCD_CMD_MWRITE);
                SEND_DATA(~pchData[n])
            }
            break;
        case MEM_ACCESS_MODEL_OR:
            LCD_SED1335_CSRW(dwAddress);
            for (n = 0;n < wLength;n++)
            {
                BYTE chData = 0;
                SEND_CMD(LCD_CMD_MREAD);
                chData = READ_DATA;
                SEND_CMD(LCD_CMD_MWRITE);
                SEND_DATA(chData | pchData[n])
            }
            break;
        case MEM_ACCESS_MODEL_AND:
            LCD_SED1335_CSRW(dwAddress);
            for (n = 0;n < wLength;n++)
            {
                BYTE chData = 0;
                SEND_CMD(LCD_CMD_MREAD);
                chData = READ_DATA;
                SEND_CMD(LCD_CMD_MWRITE);
                SEND_DATA(chData & pchData[n])
            }
            break;
        case MEM_ACCESS_MODEL_NORMAL:
        default:
            LCD_SED1335_CSRW(dwAddress);
            SEND_CMD(LCD_CMD_MWRITE);
            LCD_CS = LOW;
            LCD_A0 = LOW;
            LCD_DATA_DDR = 0xff;
            #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                REFRESH_VIRTUAL_PORT
            #endif
            for (n = 0;n < wLength;n++)
            {
                LCD_WR = LOW;
                LCD_DATA_OUT = pchData[n];
                #ifdef GUI_LCD_SED1335_USE_VIRTUAL_DATA_PORT
                    REFRESH_VIRTUAL_PORT
                #endif
            
                WDR();
                LCD_WR = HIGH;
            }
            LCD_CS = HIGH;
            break;
    }

    return TRUE;
}

/***********************************************************
*   函数说明:系统显示缓冲区设置函数                       *
*   输入:    缓冲区设置指针  修改参数的ID                 *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
void LCD_SED1335_Scroll(LCD_SED1335_SCROLL *pScroll,uint8 chParameterID)
{
    uint8 n = 0;
   
    SEND_CMD(LCD_CMD_SCROLL);
   
    while(chParameterID--)
    {
        SEND_DATA(((uint8 *)pScroll)[n++]);
    }
}


/***********************************************************
*   函数说明:  SED1335拷贝优化函数                        *
*   输入:      源地址,数据长度,目标地址,拷贝模式       *
*   输出:      操作是否成功                               *
*   调用函数:  LCD_SED1335_Scroll()                       *
***********************************************************/
BOOL LCD_SED1335_Copy_Front
                (
                    UINT32 dwAddressFrom,
                    UINT32 dwLength,
                    UINT32 dwAddressTo,
                    UINT8  chModel
                )
{
    if (chModel != MEM_ACCESS_MODEL_INSTEAD)
    {
        /* 无法优化 */
        return FALSE;
    }
   
    g_ScreenScroll.SAD1 = (UINT16)dwAddressFrom;      
   
    LCD_SED1335_Scroll(&g_ScreenScroll,8);
   
    return TRUE;
}

/***********************************************************
*   函数说明:  SED1335拷贝优化函数                        *
*   输入:      源地址,数据长度,目标地址,拷贝模式       *
*   输出:      操作是否成功                               *
*   调用函数:  LCD_SED1335_Scroll()                       *
***********************************************************/
BOOL LCD_SED1335_Copy_Middle
                (
                    UINT32 dwAddressFrom,
                    UINT32 dwLength,
                    UINT32 dwAddressTo,
                    UINT8  chModel
                )
{
    if (chModel != MEM_ACCESS_MODEL_INSTEAD)
    {
        /* 无法优化 */
        return FALSE;
    }
   
    g_ScreenScroll.SAD2 = (UINT16)dwAddressFrom;      
   
    LCD_SED1335_Scroll(&g_ScreenScroll,8);
   
    return TRUE;
}

/***********************************************************
*   函数说明:  SED1335拷贝优化函数                        *
*   输入:      源地址,数据长度,目标地址,拷贝模式       *
*   输出:      操作是否成功                               *
*   调用函数:  LCD_SED1335_Scroll()                       *
***********************************************************/
BOOL LCD_SED1335_Copy_Background
                (
                    UINT32 dwAddressFrom,
                    UINT32 dwLength,
                    UINT32 dwAddressTo,
                    UINT8  chModel
                )
{
    if (chModel != MEM_ACCESS_MODEL_INSTEAD)
    {
        /* 无法优化 */
        return FALSE;
    }
   
    g_ScreenScroll.SAD3 = (UINT16)dwAddressFrom;      
   
    LCD_SED1335_Scroll(&g_ScreenScroll,8);
   
    return TRUE;
}

出0入296汤圆

 楼主| 发表于 2008-5-23 10:29:08 | 显示全部楼层
有待添加文字

出0入0汤圆

发表于 2008-5-23 13:07:55 | 显示全部楼层
谢谢傻孩子的无私奉献!

出0入0汤圆

发表于 2008-5-23 13:11:35 | 显示全部楼层
强烈支持!
 该GUI可以显示真彩色BMP图片吗?支持画园等操作码?

出0入0汤圆

发表于 2008-5-23 13:30:20 | 显示全部楼层
编译器用得哪种?

出0入0汤圆

发表于 2008-5-23 14:21:08 | 显示全部楼层
【22楼】 Gorgon Meducer 傻孩子
    这就是所谓的DIY。你们可以DIY航模,DIY四轴飞行器,热衷于DIY下载器,就不
允许我DIY自己喜欢的代码结构?你说的书,我都有计划要阅读,问题在于,你说过
适当的经验,我这种做法也是积累适当经验的一种方法啊。
    永远只想把别人的东西简化,做外包,永远没有自己的核心技术。永远只会想遵
守别人的协议。当然,一开始,我们需要去遵守,这是顺应时代的,一旦等我们羽翼
丰满的时候,就要有中国开发人员能力和中国实力的证明——让别人遵守我们自己的
协议。现在做一点兴趣爱好,算是聊以自_慰,未尝不可?
    你也许不可以当飞行员,但是你绝对有机会做一把航模的操作手。DIY并不
代表我排斥这些已有的标准,你们也许用工作的眼光在看待我所做的事情,而我恰恰
好并不工作,立场不同,自然观点不同。我可以游戏代码,而对你们很多人来说,这
就是不可容忍的——因为不符合一些工业标准。

    现实中,我碰壁的次数也许对大部分人来说,已经是难以想象的程度。然而,因
为坚持,我才有今天。坚持一天两天甚至三天,叫做虎头蛇尾。坚持一年两年三年,
叫做固执,如果一直坚持不算超级固执也可以说成是执著了吧?

    简而言之,您回复中的一个关键字就是“开发”,而我帖子的关键字是“研究”,
不是一个目的,自然走的路不同哈。

    谢谢【17楼】 watercat 的关注。很希望和您这样的人多交流。

==================================

在我看来,所谓的DIY,无非是出于两个目的

1、原装货色价格高,于是用DIY制作廉价版本(举例:DIY下载器)

2、原装货色性能差,于是用DIY制作高性能版本(举例:DIY航模)

或者两个目的的不等比例综合

但是,DIY一个GUI的意义在于什么呢?

举例来说,X协议是完全开放的、功能完备的协议,其实现方案有几千行代码的最小功能版本,也有上百万行代码的巨无霸版本,而这些大多数是完全开源的(遵循LGPL或BSD协议)

研读这些代码,并且深刻理解它们的构思,并不比你重新设计一套来得更复杂,尤其当你这个设计还需要连操作系统的许多部件一并设计时……

这样,你到底是为什么坚持于一定要自己从零开始把一个GUI从操作系统底层到协议到实现代码完全定制化呢?

出0入296汤圆

 楼主| 发表于 2008-5-23 14:24:42 | 显示全部楼层
to 【29楼】 watercat
    这个麻……纯属个人爱好……^_^这个理由如何?
    你推荐的东西我一定好好阅读。不过,我还是喜欢自己做一个^_^。
    另外我的函数库一向是工作在裸机状态下的,所以必不可少要牵涉到一些操作系统里面的
东西。好在我是软件工程专业的学生,所以,全当作操作系统和编译原理之类的课程设计了……

    别说我任性哈,我学工程的知道自己这种做法是违背工程原则的,我也常常在团队中让大家
作工程的时候避免这种屋上架屋的做法。但是,我现在并不在作工程阿……趁着年轻,趁着没有
工作,多玩两年吧……程序员的玩具……其实就是DIY一些别人不屑的东西……

    另外,你说的X系统,能提供一个连接么?

to 【27楼】 ba_wang_mao  
    Fool GUI并不支持。在Snail GUI中将支持这一系统。画圆和填充都要支持的。

to 【28楼】 spy2008 水底石
    我用的是ICC,不过我力争编写的函数库可以在各个平台上很容易就实现移植。因为我坚持
使用ANSI-C的特性。

出0入0汤圆

发表于 2008-5-23 14:31:59 | 显示全部楼层
watercat说的X系统是指Unix/Linux下的X window。
几百万行的巨无霸我等可不敢看。几千行的可能是指TinyX

出0入0汤圆

发表于 2008-5-23 14:32:52 | 显示全部楼层
即使是纯粹的个人爱好,有些时候,或者说绝大多数时候,能够借鉴参考先行者的经验也是非常有益的,这也是我建议你先去阅读那两本书的原因,毕竟,磨刀不误砍柴工

至于X协议……满网络都有……那个……你到底要哪种内容的连接?- -

出0入296汤圆

 楼主| 发表于 2008-5-23 14:40:23 | 显示全部楼层
to 【32楼】 watercat
    源代码的连接……借鉴的问题,其实你不了解我,我最擅长借鉴……这一点有
点类似微软的做法……好的东西就先抄袭,然后消化,最后在改进……上次看了MFC
和OOC的一些东西,直接导致我现在编码风格的突变……因为我还没有工作在Linux
环境下,所以还没有接触这些。不过对GUI的尝试,我从高中就开始了,用QB写了一
Windows风格的工具。现在想来真是怀念……但是,当时就觉得,如果有一个东西能
作为参考就好了……
    另外,我写这个帖子,就是希望抛砖引玉,写一点自己的想法和成果,自然会
得到类似您这样的高人,给与指点,然后我就知道后面要看什么书,要怎么做了。
从这点来说,非常感谢您!谢谢

    我写Fool GUI只是想试验一下我所学到的原理和方法_论,但凡我做过的东西,再
看别人的源代码就容易的很多,比如MFC的内核代码(部分牛人仿真的版本)。但是
如果反过来,现看代码,估计效率就要低得多……但是原理往往大家都知道,自己亲
手有选择的做一部分,往往对我们阅读别人先进的系统,有很大的帮助,很容易对
书中作者的说法产生共鸣。^_^如果你读书的时候,觉得不只所云,其实是因为,你和
作者没有经历过类似的东西罢了……

出0入0汤圆

发表于 2008-5-23 14:55:08 | 显示全部楼层
跟着学习

出0入0汤圆

发表于 2008-5-23 15:33:56 | 显示全部楼层
太强了,又是重磅炸_弹。

出0入0汤圆

发表于 2008-5-23 16:36:47 | 显示全部楼层
本人水平太低,没法参与讨论,搬个板凳坐在边上旁听。我看Gorgon Meducer 傻孩子很有希望成为中国的比尔盖茨。

出0入296汤圆

 楼主| 发表于 2008-5-23 16:38:43 | 显示全部楼层
to 【36楼】 sunke9 小可歌

    那我开玩笑哈……^_^

出0入0汤圆

发表于 2008-5-23 17:29:40 | 显示全部楼层
支持这个贴子..有空多研究下....哈,不要成为太监贴哦

出0入0汤圆

发表于 2008-5-23 18:18:10 | 显示全部楼层
我自已的水平还不高,很难发表什么好的意见,在学习中。

出0入0汤圆

发表于 2008-5-23 18:23:02 | 显示全部楼层
努力向楼主学习中

出0入0汤圆

发表于 2008-5-23 19:26:24 | 显示全部楼层
  没看完全贴,先泼点“冷水”:与其在AVR上做GUI,不如自己搞个软GPU
AVR内存小,扩展不便,屏幕各种各样,小屏多自带控制器,大屏多无控制器,话说回来,各爱好者手中的屏也是大不一样,小屏做GUI没什么实际意义,(除了傻孩子说的设计并验证这个GUI Framework),大屏带宽来不了(不带控制器的屏滚屏时所需的带宽极大,AVR要忙死了)……
  建议傻孩子把平台换一下,比如ARM,或是其它什么的。听说Power处理器比较便宜,有没有人用?要不看上去除学习研究外真的没什么意义。
  附上PC上流行的GUI列表,算是比较全了,至今还没找到比这张表更全的,国人写的MiniGUI也有收录,至于ZlgGUI...呵呵,也是研究性的GUI。
The GUI Toolkit, Framework Pageourdev_291114.zip(文件大小:57K) (原文件名:The GUI Toolkit, Framework Page.zip)

  傻孩子应该对GUI还不是太了解吧?我也不了解,对于二楼的说法,思想个人认为是对的也是很好的,但是作为实现来说,太过天真。WinNT是把GUI做为一个组件在内核中实现的,足见GUI的重要,可以借鉴Windows GDI的接口及做法。
  我说嘛,无论是爱好还是什么也好,一定得有点现实意义(包括应用与指导意义),同时也得衡量投入产出,GUI是个力气活,楼主想清楚啊……要不这样也好,找个好的GUI给大家解析一番如何?如果要好玩,就移植到AVR下(貌似不可能,对内存等的要求都挺高的,而且多依赖于操作系统,要不连操作系统一块移???。。。改写比较划算,呵呵)。至于更多的,还没想好,上段时间用M16+SD+3100LCD做了个显示图片的东东(仅能显示一张图片,没用FS,纯属自娱,哈哈),7M主频下128*128的16位色bmp图像要近1秒才能刷完。但8位色的就比较快,如果AVR其它事不做就刷屏的话可以到8fps,(从这就可以看到带宽的重要性了吧,我用硬件SPI,同时挂屏和SD卡)。搞完了之后发现除了能显示图片啥都做不了,感觉没什么意义,扔掉了……所以。。楼主现在的意见?

出0入0汤圆

发表于 2008-5-23 19:53:52 | 显示全部楼层
这也是技术提高和学习的过程--》这就是意义,哈哈

我用硬件SPI,同时挂屏和SD卡,而且3100LCD是串行9位SPI接口的屏,要软硬结合才行,所以速度就比你的慢的多,楼上应该是并口的吧,哈哈

有空把资料打包发一下,包括3100的电路图,驱动程序(两个型号的都有),测试代码,还有控制器的Datasheet,两个型号的哦

出0入296汤圆

 楼主| 发表于 2008-5-23 20:14:28 | 显示全部楼层
to 【41楼】 Totry  
    谢谢你的建议,我对GUI的确不是特别了解。不过如果了解了,也不会
做这些没有意义的事情了。至于定位,大家可能定的太高了。目前我做的,
GUI只要接口上支持真彩色扩展就可以了,主体还是以黑白屏为主流。
    我的目标就是要写小型操作系统,所以我的GUI目前都是在裸机中跑,
你也可以认为就是以内核形态在运行哈。速度永远是值得推敲的事情,即便
是Windows的GUI在原理上也不是随时刷新的,实际上,他使用脏矩阵技术,
每次只刷新被改变的部分。而且,我一般都是跑16M的时钟,以我目前测试
的结果,320240的黑白屏幕,一秒钟可以刷50帧朝上……毕竟数据少嘛。
AVR充其量只能做小屏幕的GUI,但是我写的GUI是跨平台的,做到和底层硬
件无关,因此,可以在ARM7、AVR32这样的系统上跑……AVR可以看作一个
极限情况——小内存,对速度又要求等等。极限情况都能获得不错的效果
那么宽松的情况下自然占用系统资源就不会很多了。
    眼光不可以只停留在试验所使用的平台上,跨平台,用什么平台其实
都无所谓,关键在于逻辑结构和思想。

    太高兴了,有这么多热心人参与讨论!

出0入0汤圆

发表于 2008-5-23 20:20:49 | 显示全部楼层
MARK,等忙完手上的再回来慢慢的看

出0入0汤圆

发表于 2008-5-23 21:08:27 | 显示全部楼层
既然楼主都这么说了,那还等什么,大家有什么好主意就赶快动起来吧!

我先从另一个角度做个Outline..,即从用户用概念角度来说
·Graphics:是提供Windows中的多视窗服务还是简单的点线形状等函数的封装?
·User:不用说了,以单用户为基础
·Interface:当然是键盘了,鼠标做为可选的扩展
……

傻孩子还是先给个大体的方向描述吧,最好写成文档形式,用各种图来表达思想,
这样可以节省时间增进理解啊。另外建议不要把那么长的代码直接贴进来哦,眼
都看花啦。

对于操作系统,我也很感兴趣,有空了慢慢研究,也想自己写个,但同样被自己
给否定了,呵呵,满足傻孩子读Linux源码的部分愿望,上传本Linux0.11版的内
核完全注释,赵炯博士写的,绝好的Linux深入学习资料。说来惭愧,早就下好了
却一直都没看,哈哈:ourdev_291172.pdf(文件大小:5.15M) (原文件名:Linux内核完全注释.pdf)

出0入0汤圆

发表于 2008-5-23 21:24:01 | 显示全部楼层
很多Linux大侠都说,0.11版内核不要再看了,因为看了发现和现在的内核差别实在是太太大了。

出0入0汤圆

发表于 2008-5-23 21:39:43 | 显示全部楼层
话是这么说,但引用一个人曾经说过的话,就是看现在的Linux0.11版内核完全注释“性价比”相对好点,现在的Linux真的是太大了,以个人为单位进行学习,太太难了。个人认为,这仍然是一个操作系统原理入门的好蓝本,除非哪个Linux大侠给点好的学习资料?

说点不负责任的,仅供个人发牢骚:Linux现在是疲于奔命,她是开源世界中的一棵大树不错,但也不需要面面俱到,为了变得更加“完美”而不惜一切代价去做修补(改)……早就偏离了Linux诞生的初衷……祝愿Linux一路走好……

出0入0汤圆

发表于 2008-5-23 21:57:57 | 显示全部楼层
只是GUI?结合后面的讨论怎么越来越像带GUI的OS?!把控件对象和绘图之外的所有东西都该扔掉先。
GUI分两部分,现在讨论的应该是物理部分吧,跟GDI或是SDL以及X的绘图部分是一类的,这部分要做到跨平台可移植还是有点小挑战的,SDL算做得不错,缺陷就是速度上不去。傻孩子加油,弄个更快更猛的,PK掉SDL。
感觉逻辑部分可能是大头,MFC框架、GTK、QT都属于这类的,要做好GUI对象的逻辑处理现成的好例子很多,GTK的应用程序写起来很爽快,QT也很不错,都比MFC舒服不是一点点。MFC的唯一优势在于M$给他做了个所见即所得的IDE。咱自己写GUI要解决的最大困惑可能就是如何响应GUI对象的事件,别的问题在这种轻量级的GUI里都好说。
另外,绘制接口是个困难,GUI的这两个部分的耦合需要做到尽量低,这样才可能有比较好的移植性和通用性。

出0入296汤圆

 楼主| 发表于 2008-5-23 22:26:19 | 显示全部楼层
to 【47楼】 Totry  
    Fool GUI 以实现跨平台为主,无视优化,只做简单的点线封装。
    Snail GUI 提供完整的窗体解决方案(构架已经完成,正在改进),有兴趣可
以和我直接交流哈。加我QQ即可。
    键盘、鼠标、触摸屏都将在Fool GUI中登场。

    公布Snail GUI已有的特性:
    1、支持虚拟显示,天然的双缓冲。
    2、真正的窗体结构,窗体覆盖,底层窗体和顶层窗体显示互不干扰。
    3、为窗体封装键盘和鼠标事件。
    4、跨平台,仍然是裸机系统^_^
    5、多LCD支持,LCD间窗口无缝拖放(和Windows的多显示是一样的)
    6、支持大SRAM和小SRAM两种状态。
    7、编程接口模仿MFC。
    8、支持RPG游戏中的那种滚屏(无需用户软件模拟)。
   
    Snail GUI目前正在公关的问题——脏矩阵技术实现屏幕显示速度的优化。

to 【50楼】 wei1985_5
    Fool GUI 只是一个很简单的玩具,专门针对裸机AVR跑得GUI系统。很简单
和Snail GUI不是一个数量级的。切忌不可以根据Fool GUI来推断Snail GUI系统。
只能说,Fool GUI在DDI部分是Snail GUI的一个修正子集。
   
DisplayDeviceContext   DDC      显示设备上下文
DisplayDeviceInterface DDI      显示设备接口

在Fool GUI中,只有DDI,而在DDC中DDI只是DDC的一个部分。DDC中还要包含刷子
画笔等对象。DDC部分本身支持一些基本的绘图操作接口函数,例如,画线,画
点,画圆,画多边形等……
DDC不同于Windows,拥有一个特殊的缓冲区域,允许将B缓冲区向A缓冲区进行位图
影射。其中A缓冲区是显示设备的缓冲区——也就是用于双缓冲的缓冲区。而B缓冲
区是源缓冲区。A在矩形尺寸上可以大于B也可以小于B。B影射在A中时,可以指定
Left和Top。我们利用这样多个DDC就可以实现窗体构架。

比如,在一个屏幕上实现一个PRG游戏窗口,这个RPG是可以滚屏的。那么肯定需要
一个该屏幕的DDC,在该DDC中,我们指定其B缓冲区就似乎RPG窗口。此时,我们再
建立一个DDC,这个DDC的A缓冲区就是上一个DDC的B缓冲区。而此时该DDC的B缓冲
区则可以是RPG的完整地图。我们只需要修改该DDC中B缓冲区Left和Top值就能实现
在屏幕上RPG游戏窗口中的地图滚屏,而游戏窗口位置的改变,只需要修改第一个
DDC中B缓冲区的Left和Top值。

我们将这样一串DDC根据覆盖顺序串联起来,就构成了窗口的覆盖关系。按照一定
顺序向屏幕DDC的A缓冲区刷新,就可以实现最终显示效果的无闪烁多窗口独立混合
显示技术。

这一构架的瓶颈在于,每次都要整屏刷新,实际上,利用脏矩阵技术,就可以实现
部分被改变的小矩形区域来刷新。这是我努力要解决的问题。欢迎大家拍砖。

呵呵,说着说着就跑题了,本贴不讨论Snail GUI的技术。千里之行,始于足下。
先带领大家搞定Fool GUI这个“低端”的看似简单的东西吧。

出0入46汤圆

发表于 2008-5-23 22:29:21 | 显示全部楼层
多学习!

出0入0汤圆

发表于 2008-5-24 00:35:14 | 显示全部楼层
学习!

出0入296汤圆

 楼主| 发表于 2008-5-26 00:30:18 | 显示全部楼层
GUI的跨平台工作已经完成,大家可以从24楼下载实例代码。
基于2楼中提到的技术,我们成功的将LCD抽象成了一个存储器,
并使用通用的接口函数实现了对其的读写操作。通过这个通用
的接口标准,我们以后所有的操作都是跨平台,或者说与硬件
无关的。

欢迎大家拍砖。24后面张贴了实现这一技术的典型示例代码。

出0入296汤圆

 楼主| 发表于 2008-5-26 15:04:11 | 显示全部楼层
这是一个利用LCD自身的缓冲区实现双缓冲技术的例子。
适用于小SRAM的处理器。由于未进行任何形式的优化,所以速度稍微有点慢。
单字节写屏,一秒钟8帧左右。


点击此处下载 ourdev_293334.rar(文件大小:435K) (原文件名:Fool_GUI_Demo双缓冲演示.rar)

出0入0汤圆

发表于 2008-5-26 16:18:49 | 显示全部楼层

(原文件名:未命名.JPG)


编译没通过么......想先编译了再仔细研究的,不知道是不是我的设置问题。

出0入296汤圆

 楼主| 发表于 2008-5-26 18:58:26 | 显示全部楼层
我编译没有问题啊……你是不是头文件包含有问题?
要7.16A版本才可以……否则你就需要替换PF_Config.h中
的包含宏
# include <iccioavr.h> 替换为 # include <iom128v.h>。
一定要用工程编译
方法 Shift + F9

出0入0汤圆

发表于 2008-5-26 20:10:22 | 显示全部楼层
在傻孩子身上学了N多东西
谢谢哈。
记号

出0入0汤圆

发表于 2008-5-26 20:20:46 | 显示全部楼层
是不是类似于minigui的东东?

出0入296汤圆

 楼主| 发表于 2008-5-26 21:44:18 | 显示全部楼层
也许?我没有读过minigui的代码。谢谢大家的提醒,看来我不应该闭门造车。

出0入0汤圆

发表于 2008-5-27 07:45:29 | 显示全部楼层
接 【56楼】

头文件一开始就换了,先把所有头文件看了下才动手编译的,也是shift+F9。看来得去下个7.16A试试了么:)


****************************************************************************************************

下了个7.16A了,编译通过,应该就是版本问题了:)

出0入296汤圆

 楼主| 发表于 2008-5-27 14:27:09 | 显示全部楼层
to 【61楼】 andyjuly 77
    解决了就好哈。^_^

出0入0汤圆

发表于 2008-5-27 17:05:18 | 显示全部楼层
学习学习~~~~~~~

出0入0汤圆

发表于 2008-5-27 18:43:36 | 显示全部楼层
支持一下

出0入296汤圆

 楼主| 发表于 2008-6-9 16:30:43 | 显示全部楼层
这里发大水,房屋未冲毁……
帐篷等警报,至今还未归……

定场诗一首^_^



最近因为上网不容易,还有忙着做Robocon。只是把Fool GUI v1.00完成了。
作为纪念,写了一个探视蛇来玩玩。未来几天将加入触摸屏。因为没有时间
更新帖子的课程内容,所以只好暂时放一点成果上来。


Fool GUI v1.00的接口描述

//绘制一个纯窗体,可以单独设置边框的颜色和绘制模式,填充的颜色和绘制模式
# define LCD_BOX(__X,__Y,__WIDTH,__HEIGHT,__FRAME_MODEL,__FRAME_COLOR,__FILL_MODEL,__FILL_COLOR)    \
            GUI_BOX(g_bmLCDPanel,__X,__Y,__WIDTH,__HEIGHT,__FRAME_MODEL,__FRAME_COLOR,__FILL_MODEL,__FILL_COLOR)

//文字显示,可以指定x,y坐标,目前,为了简化代码,x坐标会被自动对其到8为单位的坐标上,可以指定颜色和模式
# define LCD_TEXT_OUT(__X,__Y,__STR,__COLOR,__MODEL)    \
            GUI_TEXT_OUT(g_bmLCDPanel,__X,__Y,__STR,__COLOR,__MODEL)

//显示二进制数字,其余同上            
# define LCD_BIN_OUT(__X,__Y,__NUMBER,__COLOR,__MODEL)  \
            {\
                BYTE chTextBuffer[32] = {0};\
                GUI_TEXT_OUT(g_bmLCDPanel,(__X),(__Y),"0b",(__COLOR),(__MODEL));\
                GUI_TEXT_OUT(g_bmLCDPanel,(__X)+16,(__Y),ltoa(chTextBuffer,(__NUMBER),2),(__COLOR),(__MODEL));\
            }

//显示十六进制数字,其余同上
# define LCD_HEX_OUT(__X,__Y,__NUMBER,__COLOR,__MODEL)  \
            {\
                BYTE chTextBuffer[32] = {0};\
                GUI_TEXT_OUT(g_bmLCDPanel,(__X),(__Y),"0x",(__COLOR),(__MODEL));\
                GUI_TEXT_OUT(g_bmLCDPanel,(__X)+16,(__Y),ltoa(chTextBuffer,(__NUMBER),16),(__COLOR),(__MODEL));\
            }            

//显示十进制数字,其余同上
# define LCD_DEC_OUT(__X,__Y,__NUMBER,__COLOR,__MODEL)  \
            {\
                BYTE chTextBuffer[32] = {0};\
                GUI_TEXT_OUT(g_bmLCDPanel,(__X),(__Y),ltoa(chTextBuffer,(__NUMBER),10),(__COLOR),(__MODEL));\
            }         

//显示一个具有3D效果的窗口(无标题栏)            
# define LCD_WINDOW_3D(__X,__Y,__WIDTH,__HEIGHT) \
            {\
                LCD_BOX((__X) + 5,(__Y) + 5,(__WIDTH),(__HEIGHT),0xFF,0,0,0);\
                LCD_BOX((__X),(__Y),(__WIDTH),(__HEIGHT),0,0,0,0xFF);\
            }            

//显示一个平板风格的窗口(无标题栏)
# define LCD_WINDOW(__X,__Y,__WIDTH,__HEIGHT) \
                LCD_BOX((__X),(__Y),(__WIDTH),(__HEIGHT),0,0,0,0xFF);

//显示一个3D效果的窗口(有标题栏)            
# define LCD_FORM_3D(__X,__Y,__WIDTH,__HEIGHT,__STR)   \
            {\
                LCD_WINDOW((__X),(__Y),__WIDTH,__HEIGHT);\
                LCD_TEXT_OUT(((__X)+8),(__Y)+2,(__STR),0,MEM_ACCESS_MODEL_NORMAL);\
                LCD_BOX((__X)+1,(__Y)+1,(__WIDTH) - 2,16,0xFF,0,MEM_ACCESS_MODEL_XOR,0);\
            }

//显示一个平板风格的窗口(有标题栏)            
# define LCD_FORM(__X,__Y,__WIDTH,__HEIGHT,__STR)    \
            {\
                LCD_WINDOW((__X),(__Y),__WIDTH,__HEIGHT);\
                LCD_TEXT_OUT(((__X)+8),(__Y)+2,(__STR),0,MEM_ACCESS_MODEL_NORMAL);\
                LCD_BOX((__X)+1,(__Y)+1,(__WIDTH) - 2,16,0xFF,0,MEM_ACCESS_MODEL_XOR,0);\
            }

//类似标签的窗口
# define LCD_LABEL_FORM(__X,__Y,__WIDTH,__HEIGHT,__STR) \
            {\
                LCD_TEXT_OUT(((__X)),(__Y),(__STR),0,MEM_ACCESS_MODEL_NOT);\
                LCD_WINDOW((__X),(__Y)+16,__WIDTH,__HEIGHT);\
            }
         
//在双缓冲模式下,会自动将缓冲区的内容刷新到前台,在直接写屏模式下,不作任何操作
# define LCD_REFRESH        \
            {\
                if (!g_bIfDirectlyAccess)\
                {\
                    UPDATA_DDC(g_ddcLCD320240Middle);\
                    DDC_SYN_Buffer(&g_ddcLCD320240Middle);\
                }\
            }

//进入直接写屏模式
# define LCD_SET_FAST_ACCESS    {\
                                    g_bmLCDPanel.pmemBitMap = DDC_Get_Device(&g_ddcLCD320240Middle);\
                                    g_bIfDirectlyAccess = TRUE;\
                                }

//在显示设备上下文DDC中存在缓冲区时,进入后台作图模式,只有通过LCD_REFRESH才可以将绘制好的内容一次性更新到前台
# define LCD_SET_BACKGROUND_ACCESS  \
            {\
                g_bmLCDPanel.pmemBitMap = DDC_Get_Buffer(&g_ddcLCD320240Middle);\
                g_bIfDirectlyAccess = FALSE;\
            }

//在直接写屏模式下将清除屏幕的内容,在双缓冲区模式下,将清除缓冲区的内容
# define LCD_CLS    \
            {\
                if (g_bIfDirectlyAccess)\
                {\
                    DDC_CLS_DEVICE(g_ddcLCD320240Middle,NULL);\
                }\
                else\
                {\
                    DDC_CLS_BUFFER(g_ddcLCD320240Middle,NULL);\
                }\
            }

出0入296汤圆

 楼主| 发表于 2008-6-9 16:38:13 | 显示全部楼层
这里,结合《深入浅出AVR单片机——从ATMega48/88/168》最后一个实例,利用Fool GUI
实现了这个探视蛇的游戏,希望对大家有所帮助。游戏代码全部在System.c中,完全是使
用与硬件无关的伪代码写成,工程中提供了原理图。我使用的屏幕是320240,一屏数据要
9600个字节,不可能用AVR的SRAM开缓冲,所以,我使用了LCD自己的存储区作为缓冲。也
就是说,大家可以使用M8这样小SRAM的程序来驱动我们的这个Fool GUI。

欢迎大家交流。在贴最后的最后,我们会通过一个大章节——将GUI移植到基于12864的系
上完成整个Fool GUI的研究和讲解工作,并形成一个完善的函数库,甚至编写必要的辅助
工具,方便大家在各种条件下,使用这个开源和跨平台的GUI。

点击此处下载 探视蛇.rar(文件大小:617K)


提供一个Fool GUI的最小系统(包含了SED1335驱动)
点击此处下载 ourdev_304894.rar(文件大小:311K)

出0入0汤圆

发表于 2008-6-9 17:49:55 | 显示全部楼层
傻孩子是我的偶像!

出0入0汤圆

发表于 2008-6-9 18:38:04 | 显示全部楼层
我还是先把我的Linux下的GTK搞明白再说吧。

出0入0汤圆

发表于 2008-6-9 19:37:17 | 显示全部楼层
果然强大,赶紧收了,细细品读!

出0入0汤圆

发表于 2008-6-9 23:31:05 | 显示全部楼层
好贴,收藏

出0入0汤圆

发表于 2008-6-12 15:12:18 | 显示全部楼层
狂顶!!!狂顶!!!狂顶!!!狂顶!!!狂顶!!!狂顶!!!

出0入0汤圆

发表于 2008-6-12 17:22:24 | 显示全部楼层
MARK

出200入0汤圆

发表于 2008-6-14 01:00:52 | 显示全部楼层
好帖,支持

出0入0汤圆

发表于 2008-6-14 07:38:45 | 显示全部楼层
学习。。。。。。。

出0入8汤圆

发表于 2008-6-14 11:17:50 | 显示全部楼层
要认真拜读,好贴。

出0入0汤圆

发表于 2008-6-26 14:12:54 | 显示全部楼层
cpu类的外设操作绝大多数都是虚拟成存储器的,只有很少的外设通过协处理器或者其他方式连接,
一般的外设是挂在总线上的,通过寄存器来操作,寄存器就是存储器
外扩的总线型设备,有地址空间,当然也可以看作存储起来访问,如果不是挂在总线上面可以把中间的io归到外设中去,这样就成了io设备了,也是存储器方式操作(有io指令的cpu除外)。

出0入0汤圆

发表于 2008-7-16 14:36:10 | 显示全部楼层
请问傻孩子
typedef union DeviceID
{
    UINT16 ID;
    struct
    {
        UINT8 Device;
        UINT8 Type;
    }_;
}DEVICE_ID;

以上是理解成 DeviceID==union 。而DEVICE_ID是公用体结构吗?

typedef BOOL (*_MEM_READ)
                (
                    UINT32 dwAddress,
                    UINT32 dwLength,
                    void *pData,
                    UINT8  chModel
                );
这该如何理解? 请不吝赐教!

出0入296汤圆

 楼主| 发表于 2008-7-16 15:03:31 | 显示全部楼层
to 【77楼】 maskchen  
   我定义了一个自定义类型叫做 DEVICE_ID。他使用的时候是这样的:
   DEVICE_ID   newDevice;
   相当于
   union DeviceID  newDevice;

   下面一个也是我自定义的类型,_MEM_READ是一个自定义的类型说明符,使用的时候这样:
   _MEM_READ  fnRead;
   相当于定义了一个指向 _MEM_READ所说明的类型的函数的  函数指针。

出0入0汤圆

发表于 2008-7-16 15:05:38 | 显示全部楼层
再次顶你!!

出0入0汤圆

发表于 2008-7-16 15:56:44 | 显示全部楼层
谢谢傻孩子,没想到这么快就回复我了!

出0入296汤圆

 楼主| 发表于 2008-7-16 16:26:28 | 显示全部楼层
to 【80楼】 maskchen  
    呵呵,碰巧我在而已……

出0入0汤圆

发表于 2008-8-15 22:05:07 | 显示全部楼层
强帖!!!非常感谢!

出0入0汤圆

发表于 2008-8-15 22:47:20 | 显示全部楼层
傻孩子的思考是很有意义的,不过我没看懂。。。
我倒有一个思路说一说,我觉得应该做一个引擎,实际的界面是由引擎读取数据来工作的,这样把数据与引擎分开,通过优化引擎可以获得好的速度,至于界面,应该编写一个PC程序来设计,PC程序生成数据,另外事件驱动也是很重要的
如果编写界面还要去思考如何抽象,就违反了设计GUI的初衷,标准化的GUI是为了更专注于逻辑实现

出0入0汤圆

发表于 2008-10-8 22:28:05 | 显示全部楼层
mark!

出0入0汤圆

发表于 2008-10-8 23:21:53 | 显示全部楼层
mark!!!!!

出0入0汤圆

发表于 2008-10-8 23:27:42 | 显示全部楼层
天啊,我看SED1355怎么这么熟悉

刚才在TB上看到一个好东西——MEGA128L+SED1355F+MAX1677+蓝牙模块+液晶屏&nbsp;供拆机

有福了!

出0入296汤圆

 楼主| 发表于 2008-10-9 08:17:48 | 显示全部楼层
to&nbsp;【83楼】&nbsp;dodgecat&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;谢谢你的回馈。其实这个帖子就是在讨论如何制作一个引擎,使以后使用该

GUI的人更简单,更贴近直接的界面设计,而无需再为底层操心。^_^就像你说的

“更专注于逻辑实现”

出0入0汤圆

发表于 2008-10-23 22:59:08 | 显示全部楼层
超级强帖~~

出0入0汤圆

发表于 2008-10-24 07:56:54 | 显示全部楼层
学习一个

出0入0汤圆

发表于 2008-10-24 08:05:53 | 显示全部楼层
超级强帖~~

出0入0汤圆

发表于 2008-12-4 21:47:57 | 显示全部楼层
值得关注

出0入0汤圆

发表于 2008-12-5 00:00:59 | 显示全部楼层
傻孩子:

既然是软件工程出身的,除了C,何不弄点更高级的语言。那就更傻瓜了--比C语言更傻瓜的语言。

出0入0汤圆

发表于 2008-12-5 10:48:06 | 显示全部楼层
学习

出0入0汤圆

发表于 2009-3-30 16:20:38 | 显示全部楼层
傻孩子:
你的文章不打算写完了吗?好多都标着待添加?!

出0入0汤圆

发表于 2009-3-31 11:49:45 | 显示全部楼层
期待傻孩子的完整教程!

出0入0汤圆

发表于 2009-6-21 22:13:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-23 16:05:54 | 显示全部楼层
学习GUI虽然还为画点而努力

出0入0汤圆

发表于 2009-9-23 16:45:29 | 显示全部楼层
古董贴make

出0入0汤圆

发表于 2009-9-23 19:09:17 | 显示全部楼层
谢谢,期待下文。

出0入0汤圆

发表于 2009-9-26 11:54:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-26 13:02:00 | 显示全部楼层
呵呵太好了。好好学习一下。。
界面编程是我的弱项。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 10:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表