Browse Source

remove to example directory

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1110 bbd45198-f89e-11dd-88c7-29a3b14d5316
qiuyiuestc 14 years ago
parent
commit
64b4a18874

+ 38 - 0
examples/module/SConstruct

@@ -0,0 +1,38 @@
+import os
+import sys
+import rtconfig
+
+RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+import mdk
+
+target = RTT_ROOT + '/bsp/mini2440/rtthread-mini2440'
+projects = []
+
+AddOption('--target',
+                  dest='target',
+                  type='string',
+                  help='set target project: mdk')
+
+if GetOption('target'):
+	SetOption('no_exec', 1)
+
+TARGET = target + '.' + rtconfig.TARGET_EXT
+
+env = Environment(tools = ['mingw'],
+	AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+	CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
+	AR = rtconfig.AR, ARFLAGS = '-rc',
+	LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+
+Export('env')
+Export('RTT_ROOT')
+Export('rtconfig')
+Export('projects')
+Export('TARGET')
+
+SConscript(RTT_ROOT + '/components/module/tetris/SConscript', duplicate=0)
+SConscript(RTT_ROOT + '/components/module/basicapp/SConscript', duplicate=0)
+SConscript(RTT_ROOT + '/components/module/extension/SConscript', duplicate=0)
+SConscript(RTT_ROOT + '/components/module/extapp/SConscript', duplicate=0)

+ 34 - 0
examples/module/basicapp/SConscript

@@ -0,0 +1,34 @@
+Import('env')
+Import('projects')
+Import('RTT_ROOT')
+Import('rtconfig')
+Import('TARGET')
+
+RTMLINKER = RTT_ROOT + '/tools/rtmlinker.exe '
+
+# group definitions
+group = {}
+group['name'] = 'examples'
+group['src'] = Glob('*.c')
+group['CCFLAGS'] = ''
+group['CPPPATH'] = [RTT_ROOT + '/include', RTT_ROOT + '/components/module']
+group['CPPDEFINES'] = ''
+
+target = 'basicapp.so'
+POST_ACTION = RTMLINKER + '-l ' + TARGET + ' -o basicapp.mo ' + '$TARGET'
+
+# add group to project list
+projects.append(group)
+
+src_local = Glob('basicapp.c')
+
+env.Append(CCFLAGS = group['CCFLAGS'])
+env.Append(CPPPATH = group['CPPPATH'])
+env.Append(CPPDEFINES = group['CPPDEFINES'])
+module_env = env.Clone(CPPDEFINE = 'RT_MODULE')
+module_env = env.Clone(CCFLAGS = ' -mcpu=arm920t -O0 -fPIC')
+module_env.Replace(LINK =  'arm-none-eabi-ld')
+module_env.Replace(LINKFLAGS = '-z max-page-size=0x4 -shared -fPIC -e rt_application_entry -nostdlib -s')
+module_env.Program(target, src_local) 
+module_env.AddPostAction(target, POST_ACTION) 
+

+ 26 - 0
examples/module/basicapp/basicapp.c

@@ -0,0 +1,26 @@
+#include <rtthread.h>
+
+int a = 0;
+int b = 1000000;
+int c = 0;
+
+static void function(int count1, int count2, int count3)
+{
+	rt_kprintf("Hello RT-Thread %d %d\n", count1, count2, count3);
+}
+
+int rt_application_entry(void)
+{
+	int i;
+	rt_kprintf("application entry\n");
+	for(i=0; i<100; i++)  
+	{	
+		a++;
+		b--;
+		c++;
+		function(a, c, b );
+	}
+ 
+	return 0;
+}
+

+ 34 - 0
examples/module/extapp/SConscript

@@ -0,0 +1,34 @@
+Import('env')
+Import('projects')
+Import('RTT_ROOT')
+Import('rtconfig')
+Import('TARGET')
+
+RTMLINKER = RTT_ROOT + '/tools/rtmlinker.exe '
+
+# group definitions
+group = {}
+group['name'] = 'examples'
+group['src'] = Glob('*.c')
+group['CCFLAGS'] = ''
+group['CPPPATH'] = [RTT_ROOT + '/include', RTT_ROOT + '/components/module', RTT_ROOT + '/components/libdl']
+group['CPPDEFINES'] = ''
+
+target = 'extapp.so'
+POST_ACTION = RTMLINKER + '-l ' + TARGET + ' -o extapp.mo ' + '$TARGET'
+
+# add group to project list
+projects.append(group)
+
+src_local = Glob('extapp.c')
+
+env.Append(CCFLAGS = group['CCFLAGS'])
+env.Append(CPPPATH = group['CPPPATH'])
+env.Append(CPPDEFINES = group['CPPDEFINES'])
+module_env = env.Clone(CPPDEFINE = 'RT_MODULE')
+module_env = env.Clone(CCFLAGS = ' -mcpu=arm920t -O0 -fPIC')
+module_env.Replace(LINK =  'arm-none-eabi-ld')
+module_env.Replace(LINKFLAGS = '-z max-page-size=0x4 -shared -fPIC -e rt_application_entry -nostdlib -s')
+module_env.Program(target, src_local) 
+module_env.AddPostAction(target, POST_ACTION) 
+

+ 35 - 0
examples/module/extapp/extapp.c

@@ -0,0 +1,35 @@
+#include <rtthread.h>
+#include <dlfcn.h>
+
+typedef void (*func)(void);
+
+int rt_application_entry(void)
+{
+	func f1, f2, f3, f4, f5;
+		
+	void* handle = dlopen("/mo/ext.so", RTLD_NOW);
+	if(handle != RT_NULL)
+	{
+		f1= (func)dlsym(handle, "function1");
+		f2= (func)dlsym(handle, "function2");
+		f3= (func)dlsym(handle, "function3");
+		f4= (func)dlsym(handle, "function4");
+		f5= (func)dlsym(handle, "function5");
+
+		if(f1 != RT_NULL) f1();
+		else rt_kprintf("dlsym function1 failed.\n");
+		if(f2 != RT_NULL) f2();
+		else rt_kprintf("dlsym function2 failed.\n");
+		if(f3 != RT_NULL) f3();
+		else rt_kprintf("dlsym function3 failed.\n");		
+		if(f4 != RT_NULL) f4();
+		else rt_kprintf("dlsym function4 failed.\n");
+		if(f5 != RT_NULL) f5();
+		else rt_kprintf("dlsym function5 failed.\n");
+	}
+
+	if(handle != RT_NULL) dlclose(handle);
+
+	return 0;
+}
+

+ 33 - 0
examples/module/extension/extension.c

@@ -0,0 +1,33 @@
+#include <rtthread.h>
+#include <rtm.h>
+
+void function1(void)
+{
+	rt_kprintf("Hello RT-Thread function1\n");
+}
+
+void function2(void)
+{
+	rt_kprintf("Hello RT-Thread function2\n");
+}
+
+void function3(void)
+{
+	rt_kprintf("Hello RT-Thread function3\n");
+}
+
+void function4(void)
+{
+	rt_kprintf("Hello RT-Thread function4\n");
+}
+
+void function5(void)
+{
+	rt_kprintf("Hello RT-Thread function5\n");
+}
+
+RTM_EXPORT(function1)
+RTM_EXPORT(function2)
+RTM_EXPORT(function3)
+RTM_EXPORT(function4)
+RTM_EXPORT(function5)

+ 213 - 0
examples/module/rtconfig.h

@@ -0,0 +1,213 @@
+/* RT-Thread config file */
+#ifndef __RTTHREAD_CFG_H__
+#define __RTTHREAD_CFG_H__
+
+/* RT_NAME_MAX*/
+#define RT_NAME_MAX	8
+
+/* RT_ALIGN_SIZE*/
+#define RT_ALIGN_SIZE	4
+
+/* PRIORITY_MAX */
+#define RT_THREAD_PRIORITY_MAX	256
+
+/* Tick per Second */
+#define RT_TICK_PER_SECOND	100
+
+/* SECTION: RT_DEBUG */
+/* Thread Debug */
+#define RT_DEBUG
+/* #define RT_THREAD_DEBUG */
+
+#define RT_USING_OVERFLOW_CHECK
+
+/* Using Hook */
+#define RT_USING_HOOK
+
+/* Using Software Timer */
+#define RT_USING_TIMER_SOFT
+#define RT_TIMER_THREAD_PRIO		8
+#define RT_TIMER_THREAD_STACK_SIZE	512
+#define RT_TIMER_TICK_PER_SECOND	10
+
+/* SECTION: IPC */
+/* Using Semaphore */
+#define RT_USING_SEMAPHORE
+
+/* Using Mutex */
+#define RT_USING_MUTEX
+
+/* Using Event */
+#define RT_USING_EVENT
+
+/* Using MailBox */
+#define RT_USING_MAILBOX
+
+/* Using Message Queue */
+#define RT_USING_MESSAGEQUEUE
+
+/* SECTION: Memory Management */
+/* Using Memory Pool Management*/
+#define RT_USING_MEMPOOL
+
+/* Using Dynamic Heap Management */
+#define RT_USING_HEAP
+
+/* Using Small MM */
+#define RT_USING_SMALL_MEM
+
+/* Using SLAB Allocator */
+/* #define RT_USING_SLAB */
+
+/* SECTION: Device System */
+/* Using Device System */
+#define RT_USING_DEVICE
+
+/* Using Module System */
+#define RT_USING_MODULE
+
+/* SECTION: Console options */
+/* the buffer size of console */
+#define RT_CONSOLEBUF_SIZE	128
+
+/* SECTION: finsh, a C-Express shell */
+/* Using FinSH as Shell*/
+#define RT_USING_FINSH
+/* Using symbol table */
+#define FINSH_USING_SYMTAB
+#define FINSH_USING_DESCRIPTION
+#define FINSH_THREAD_STACK_SIZE 4096
+
+/* SECTION: a runtime libc library */
+/* a runtime libc library */
+/* #define RT_USING_NEWLIB */
+
+/* SECTION: C++ support */
+/* Using C++ support */
+/* #define RT_USING_CPLUSPLUS */
+
+/* SECTION: Device filesystem support */
+/* using DFS support */
+#define RT_USING_DFS
+#define RT_USING_DFS_ELMFAT
+/* use long file name feature 			*/
+#define RT_DFS_ELM_USE_LFN			1
+/* the max number of file length 		*/
+#define RT_DFS_ELM_MAX_LFN		32
+/* #define RT_USING_DFS_YAFFS2 */
+
+#define RT_USING_DFS_NFS
+#define RT_NFS_HOST_EXPORT		"192.168.1.5:/"
+
+/* #define DFS_USING_WORKDIR */
+
+/* the max number of mounted filesystem */
+#define DFS_FILESYSTEMS_MAX		2
+/* the max number of opened files 		*/
+#define DFS_FD_MAX					16
+/* the max number of cached sector 		*/
+#define DFS_CACHE_MAX_NUM   		4
+
+/* Enable freemodbus protocal stack*/
+/* #define RT_USING_MODBUS */
+
+/* SECTION: lwip, a lighwight TCP/IP protocol stack */
+/* Using lighweight TCP/IP protocol stack */
+#define RT_USING_LWIP
+#define RT_LWIP_DNS
+
+/* Trace LwIP protocol */
+/* #define RT_LWIP_DEBUG */
+
+/* Enable ICMP protocol */
+#define RT_LWIP_ICMP
+
+/* Enable IGMP protocol */
+#define RT_LWIP_IGMP
+
+/* Enable UDP protocol */
+#define RT_LWIP_UDP
+
+/* Enable TCP protocol */
+#define RT_LWIP_TCP
+
+/* the number of simulatenously active TCP connections*/
+#define RT_LWIP_TCP_PCB_NUM	5
+
+/* TCP sender buffer space */
+#define RT_LWIP_TCP_SND_BUF	1024*10
+
+/* TCP receive window. */
+#define RT_LWIP_TCP_WND	1024
+
+/* Enable SNMP protocol */
+/* #define RT_LWIP_SNMP */
+
+/* Using DHCP */
+/* #define RT_LWIP_DHCP */
+
+#define RT_LWIP_DNS
+
+/* ip address of target */
+#define RT_LWIP_IPADDR0	192
+#define RT_LWIP_IPADDR1	168
+#define RT_LWIP_IPADDR2	1
+#define RT_LWIP_IPADDR3	30
+
+/* gateway address of target */
+#define RT_LWIP_GWADDR0	192
+#define RT_LWIP_GWADDR1	168
+#define RT_LWIP_GWADDR2	1
+#define RT_LWIP_GWADDR3	1
+
+/* mask address of target */
+#define RT_LWIP_MSKADDR0	255
+#define RT_LWIP_MSKADDR1	255
+#define RT_LWIP_MSKADDR2	255
+#define RT_LWIP_MSKADDR3	0
+
+/* the number of blocks for pbuf */
+#define RT_LWIP_PBUF_NUM	16
+
+/* thread priority of tcpip thread */
+#define RT_LWIP_TCPTHREAD_PRIORITY	128
+
+/* mail box size of tcpip thread to wait for */
+#define RT_LWIP_TCPTHREAD_MBOX_SIZE	32
+
+/* thread stack size of tcpip thread */
+#define RT_LWIP_TCPTHREAD_STACKSIZE	4096
+
+/* thread priority of ethnetif thread */
+#define RT_LWIP_ETHTHREAD_PRIORITY	144
+
+/* mail box size of ethnetif thread to wait for */
+#define RT_LWIP_ETHTHREAD_MBOX_SIZE	32
+
+/* thread stack size of ethnetif thread */
+#define RT_LWIP_ETHTHREAD_STACKSIZE	1024
+
+/* SECTION: RTGUI support */
+/* using RTGUI support */
+#define RT_USING_RTGUI
+
+/* name length of RTGUI object */
+#define RTGUI_NAME_MAX		16
+/* support 16 weight font */
+#define RTGUI_USING_FONT16
+/* support 16 weight font */
+#define RTGUI_USING_FONT12
+/* support Chinese font */
+#define RTGUI_USING_FONTHZ
+/* use DFS as file interface */
+#define RTGUI_USING_DFS_FILERW
+/* use font file as Chinese font */
+/* #define RTGUI_USING_HZ_FILE */
+/* use Chinese bitmap font */
+#define RTGUI_USING_HZ_BMP
+/* use small size in RTGUI */
+/* #define RTGUI_USING_SMALL_SIZE */
+/* use mouse cursor */
+/* #define RTGUI_USING_MOUSE_CURSOR */
+
+#endif

+ 83 - 0
examples/module/rtconfig.py

@@ -0,0 +1,83 @@
+import SCons.cpp
+
+# component options
+
+# toolchains options
+ARCH     = 'arm'
+CPU      = 's3c24x0'
+TextBase = '0x30000000'
+
+CROSS_TOOL 	= 'gcc'
+
+if  CROSS_TOOL == 'gcc':
+	PLATFORM 	= 'gcc'
+	EXEC_PATH 	= 'E:/Program Files/CodeSourcery/Sourcery G++ Lite/bin'
+elif CROSS_TOOL == 'keil':
+	PLATFORM 	= 'armcc'
+	EXEC_PATH 	= 'E:/Keil'
+BUILD = 'debug'
+
+if PLATFORM == 'gcc':
+    # toolchains
+    PREFIX = 'arm-none-eabi-'
+    CC = PREFIX + 'gcc'
+    AS = PREFIX + 'gcc'
+    AR = PREFIX + 'ar'
+    LINK = PREFIX + 'gcc'
+    TARGET_EXT = 'axf'
+    SIZE = PREFIX + 'size'
+    OBJDUMP = PREFIX + 'objdump'
+    OBJCPY = PREFIX + 'objcopy'
+
+    DEVICE = ' -mcpu=arm920t'
+    CFLAGS = DEVICE
+    AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + ' -DTEXT_BASE=' + TextBase
+    LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread_mini2440.map,-cref,-u,_start -T mini2440_ram.ld' + ' -Ttext ' + TextBase
+
+    CPATH = ''
+    LPATH = ''
+
+    if BUILD == 'debug':
+        CFLAGS += ' -O0 -gdwarf-2'
+        AFLAGS += ' -gdwarf-2'
+    else:
+        CFLAGS += ' -O2'
+
+    POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
+
+elif PLATFORM == 'armcc':
+    # toolchains
+    CC = 'armcc'
+    AS = 'armasm'
+    AR = 'armar'
+    LINK = 'armlink'
+    TARGET_EXT = 'axf'
+
+    DEVICE = ' --device DARMSS9'
+    CFLAGS = DEVICE + ' --apcs=interwork --diag_suppress=870'
+    AFLAGS = DEVICE
+    LFLAGS = DEVICE + ' --strict --info sizes --info totals --info unused --info veneers --list rtthread-mini2440.map --ro-base 0x30000000 --entry Entry_Point --first Entry_Point'
+
+    CFLAGS += ' -I"' + EXEC_PATH + '/ARM/RV31/INC"'
+    LFLAGS += ' --libpath "' + EXEC_PATH + '/ARM/RV31/LIB"' + ' --keep __RTMsym_*'
+
+    EXEC_PATH += '/arm/bin40/'
+
+    if BUILD == 'debug':
+        CFLAGS += ' -g -O0'
+        AFLAGS += ' -g'
+    else:
+        CFLAGS += ' -O2'
+
+    POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'
+
+elif PLATFORM == 'iar':
+    # toolchains
+    CC = 'armcc'
+    AS = 'armasm'
+    AR = 'armar'
+    LINK = 'armlink'
+
+    CFLAGS = ''
+    AFLAGS = ''
+    LFLAGS = ''

+ 42 - 0
examples/module/tetris/SConscript

@@ -0,0 +1,42 @@
+Import('env')
+Import('projects')
+Import('RTT_ROOT')
+Import('rtconfig')
+Import('TARGET')
+
+RTMLINKER = RTT_ROOT + '/tools/rtmlinker.exe '
+
+# group definitions
+group = {}
+group['CCFLAGS'] = ''
+group['CPPPATH'] = [RTT_ROOT + '/include',
+		RTT_ROOT + '/components/module',
+		RTT_ROOT + '/components/rtgui/include',
+		RTT_ROOT + '/components/rgtui/common', 
+		RTT_ROOT + '/components/rtgui/server', 
+		RTT_ROOT + '/components/rtgui/widgets']
+group['CPPDEFINES'] = ''
+
+target = 'tetris.so'
+POST_ACTION = RTMLINKER + ' -l ' + TARGET + ' -o tetris.mo ' + '$TARGET'
+
+# add group to project list
+projects.append(group)
+
+src_local = Split("""
+application.c
+tetris_ui.c
+tetris_modal.c
+tetris_view.c
+""")
+
+env.Append(CCFLAGS = group['CCFLAGS'])
+env.Append(CPPPATH = group['CPPPATH'])
+env.Append(CPPDEFINES = group['CPPDEFINES'])
+module_env = env.Clone(CPPDEFINE = 'RT_MODULE')
+module_env = env.Clone(CCFLAGS = ' -mcpu=arm920t -O0 -fPIC')
+module_env.Replace(LINK =  'arm-none-eabi-ld')
+module_env.Replace(LINKFLAGS = '-z max-page-size=0x4 -shared -fPIC -e rt_application_init -nostdlib -s')
+module_env.Program(target, src_local) 
+module_env.AddPostAction(target, POST_ACTION) 
+

+ 30 - 0
examples/module/tetris/application.c

@@ -0,0 +1,30 @@
+/*
+ * File      : app.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2010-08-28     Yi.Qiu       the first version
+ */
+ 
+#include <rtthread.h>
+#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_server.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/workbench.h>
+#include "tetris.h"
+
+int rt_application_init(void)
+{
+	rt_thread_t tid;
+
+	tid = rt_thread_create("tetris", tetris_ui_entry, RT_NULL, 2048, 20, 5);
+	if (tid != RT_NULL) rt_thread_startup(tid);
+	return 0;
+}
+

+ 61 - 0
examples/module/tetris/tetris.h

@@ -0,0 +1,61 @@
+/*
+ * File      : tetris_modal.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2010, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2010-08-14     Yi.Qiu       first version
+ */
+
+ #include <rtthread.h>
+
+ struct rt_tetris;
+ typedef struct rt_tetris rt_tetris_t;
+
+ struct rt_tetris_view;
+ typedef struct rt_tetris_view rt_tetris_view_t;
+
+ typedef rt_err_t (*on_update)(rt_tetris_view_t* thiz, rt_tetris_t* tetris);
+
+ struct rt_tetris_view
+ {
+ 	rt_uint32_t width;
+	rt_uint32_t height;
+
+	on_update update;
+	on_update update_next_brick;
+	on_update update_level;
+	on_update update_score_and_lines;
+	void *private;
+ };
+ 
+ rt_tetris_t* rt_tetris_create(rt_uint32_t width, rt_uint32_t height);
+ rt_err_t rt_tetris_destory(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_start(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_pause(rt_tetris_t* thiz);
+ rt_uint32_t rt_tetris_width(rt_tetris_t* thiz);
+ rt_uint32_t* rt_tetris_next_brick(rt_tetris_t* thiz);
+ rt_uint32_t rt_tetris_level(rt_tetris_t* thiz);
+ rt_uint32_t rt_tetris_lines(rt_tetris_t* thiz);
+ rt_uint32_t rt_tetris_score(rt_tetris_t* thiz);
+ rt_uint32_t rt_tetris_height(rt_tetris_t* thiz);
+ rt_bool_t rt_tetris_status(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_down(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_left(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_right(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_drop(rt_tetris_t* thiz);
+ rt_err_t rt_tetris_rotate(rt_tetris_t* thiz, rt_bool_t direction);
+ rt_err_t rt_tetris_add_view(rt_tetris_t* thiz, rt_tetris_view_t* view);
+ rt_err_t rt_tetris_delete_view(rt_tetris_t* thiz, rt_tetris_view_t* view);
+ rt_err_t rt_tetris_check_collision(rt_tetris_t* thiz, rt_uint32_t block);
+
+ rt_tetris_view_t* rt_tetris_view_create(void* private);
+ rt_err_t rt_tetris_view_destroy(rt_tetris_view_t* thiz);
+
+void tetris_ui_entry(void* parameter);
+

+ 730 - 0
examples/module/tetris/tetris_modal.c

@@ -0,0 +1,730 @@
+/*
+ * File      : tetris_modal.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2010, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2010-08-14     Yi.Qiu       first version
+ */
+ 
+#include <rtthread.h>
+#include <stdlib.h> 
+#include "tetris.h"
+
+struct rt_tetris
+{
+	rt_uint32_t	width;			/* the width of the tetris */
+	rt_uint32_t	height;			/* the height of the tetris */
+	rt_uint16_t* 	panel;			/* the panel of the tetris */
+	rt_uint32_t* 	brick;			/* the current brick of the tetris */
+	rt_uint32_t* 	next_brick;		/* the next brick  of the tetris */
+	rt_tetris_view_t* view;			/* the view on which the tetris show */
+	rt_uint32_t 	level;			/* game level */
+	rt_uint32_t 	lines;			/* released lines count */
+	rt_uint32_t 	score;			/* total scores statistic */
+	rt_bool_t 		status;			/* game status, pause or runing */
+};
+
+static const rt_uint32_t g_brick[][4] = 
+{
+	{23,7,8,22},
+	{23,7,8,24},
+	{24,7,8,25},
+	{8,7,9,23},	
+	{8,7,9,24},
+	{8,7,9,25},
+	{7,6,8,9},
+};
+
+static rt_err_t rt_tetris_append_brick(rt_tetris_t* thiz, rt_uint32_t brick[]);
+static rt_err_t rt_tetris_delete_brick(rt_tetris_t* thiz, rt_uint32_t brick[]);
+static rt_err_t rt_tetris_release_lines(rt_tetris_t* thiz, rt_uint32_t brick[]);
+static rt_err_t rt_tetris_is_reach_top(rt_tetris_t* thiz, rt_uint32_t brick[]);
+static rt_err_t rt_tetris_update_brick(rt_tetris_t* thiz);
+
+/**
+ * this function create a tetris instance
+ *
+ * @param width the width of tetris.
+ * @param height the height of tetris.
+ *
+ * @return the tetris instance
+ */
+rt_tetris_t* rt_tetris_create(rt_uint32_t width, rt_uint32_t height)
+{
+	int index;
+
+	rt_tetris_t* thiz = (rt_tetris_t*)rt_malloc(sizeof(rt_tetris_t));
+	RT_ASSERT(thiz != RT_NULL);
+
+	thiz->height 	= height;
+	thiz->width		= width;
+	thiz->panel 	= rt_malloc(thiz->height * sizeof(rt_uint32_t));
+	rt_memset(thiz->panel, 0, thiz->height * sizeof(rt_uint32_t));	
+
+	thiz->brick		= (rt_uint32_t*)rt_malloc(4 * sizeof(rt_uint32_t));
+	index 			= (int)(7.0 * rand()/(RAND_MAX + 1.0)); 
+	rt_memcpy(thiz->brick, g_brick[index], 4 * sizeof(rt_uint32_t));
+
+	thiz->next_brick= (rt_uint32_t*)rt_malloc(4 * sizeof(rt_uint32_t));
+	index 			= (int)(7.0 * rand()/(RAND_MAX + 1.0)); 
+	rt_memcpy(thiz->next_brick, g_brick[index], 4 * sizeof(rt_uint32_t));
+
+	thiz->view		= RT_NULL;
+	thiz->level		= 0;
+	thiz->lines 	= 0;
+	thiz->score		= 0;
+	thiz->status	= RT_FALSE;
+
+	return thiz;
+}
+
+/**
+ * this function destory a tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_tetris_destory(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz->panel && thiz->brick && thiz->next_brick);
+
+	rt_free(thiz->panel);
+	rt_free(thiz->brick);
+	rt_free(thiz->next_brick);
+	rt_free(thiz);
+
+	return RT_EOK;
+}
+
+/**
+ * this function start tetris game
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_tetris_start(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	/* update next brick on view */
+	thiz->view->update_next_brick(thiz->view, thiz);
+
+	/* update level */
+	thiz->view->update_level(thiz->view, thiz);
+
+	/* update lines and score */
+	thiz->view->update_score_and_lines(thiz->view, thiz);
+
+	thiz->status = RT_TRUE;
+
+	return RT_EOK;
+}
+
+/**
+ * this function pause tetris game
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_tetris_pause(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	thiz->status = RT_FALSE;
+
+	return RT_EOK;
+}
+
+/**
+ * this function get width of a tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the width of the tetris instance
+ */
+rt_uint32_t rt_tetris_width(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	return thiz->width;
+}
+
+/**
+ * this function get next brick of a tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the next brick of the tetris instance
+ */
+rt_uint32_t* rt_tetris_next_brick(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	return thiz->next_brick;
+}
+
+/**
+ * this function get level of the tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the level of the tetris instance
+ */
+rt_uint32_t rt_tetris_level(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	return thiz->level;
+}
+
+/**
+ * this function get released lines of the tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the released lines of the tetris instance
+ */
+rt_uint32_t rt_tetris_lines(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	return thiz->lines;
+}
+
+/**
+ * this function get score of the tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the score of the tetris instance
+ */
+rt_uint32_t rt_tetris_score(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	return thiz->score;
+}
+
+/**
+ * this function get height of a tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the height of the tetris instance
+ */
+rt_uint32_t rt_tetris_height(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);	
+
+	return thiz->height;
+}
+
+/**
+ * this function get status of a tetris instance
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return the status of the tetris instance
+ */
+rt_bool_t rt_tetris_status(rt_tetris_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);	
+
+	return thiz->status;
+}
+
+/**
+ * this function makes current brick move down
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_down(rt_tetris_t* thiz)
+{
+	int i;
+
+	RT_ASSERT(thiz != RT_NULL);	
+
+	if(thiz->status == RT_FALSE) return -RT_ERROR;
+
+	/* delete the brick from tetris panel */
+	rt_tetris_delete_brick(thiz, thiz->brick);
+
+	for(i=0; i<4; i++)
+	{
+		/* check collision and bottom*/
+		if((thiz->brick[i] >= thiz->width * (thiz->height - 1))
+			|| rt_tetris_check_collision(thiz, thiz->brick[i] + thiz->width) == RT_EOK)
+		{
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+
+			if(rt_tetris_is_reach_top(thiz, thiz->brick) == RT_EOK)
+			{
+				rt_memset(thiz->panel, 0xff, thiz->height * sizeof(rt_uint32_t));				
+
+				/* update view */
+				thiz->view->update(thiz->view, thiz);
+
+				/* game over */
+				return -RT_ETIMEOUT;
+			}
+
+			if(rt_tetris_release_lines(thiz, thiz->brick) == RT_EOK) 
+			{
+				/* update view */
+				thiz->view->update(thiz->view, thiz);
+			}
+
+			rt_tetris_update_brick(thiz);
+			return -RT_ERROR;			
+		}
+	}	
+
+	for(i=0; i<4; i++)
+	{	
+		/* increase one line */
+		thiz->brick[i] += thiz->width;
+	}		
+
+	/* append the brick to tetris panel */
+	rt_tetris_append_brick(thiz, thiz->brick);
+
+	/* update view */
+	thiz->view->update(thiz->view, thiz);
+
+	return RT_EOK;
+}
+
+/**
+ * this function makes current brick move left
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_left(rt_tetris_t* thiz)
+{
+	int i;
+	RT_ASSERT(thiz != RT_NULL);	
+
+	if(thiz->status == RT_FALSE) return -RT_ERROR;
+
+	/* delete the brick from tetris panel */
+	rt_tetris_delete_brick(thiz, thiz->brick);
+
+	for(i=0; i<4; i++)
+	{
+		/* check left board */
+		if((thiz->brick[i] % thiz->width) == 0)
+		{	
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;
+		}
+
+		if(rt_tetris_check_collision(thiz, thiz->brick[i] - 1) == RT_EOK)
+		{	
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;
+		}
+	}	
+	
+	for(i=0; i<4; i++)
+	{	
+		/* move one step to left */
+		thiz->brick[i] --;;
+	}		
+
+	/* append the brick to tetris panel */
+	rt_tetris_append_brick(thiz, thiz->brick);
+
+	/* update view */
+	thiz->view->update(thiz->view, thiz);
+
+	return RT_EOK;
+}
+
+/**
+ * this function makes current brick move right
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_right(rt_tetris_t* thiz)
+{
+	int i;
+	RT_ASSERT(thiz != RT_NULL);	
+
+	if(thiz->status == RT_FALSE) return -RT_ERROR;
+
+	/* delete the brick from tetris panel */
+	rt_tetris_delete_brick(thiz, thiz->brick);
+
+	for(i=0; i<4; i++)
+	{
+		/* check left board */
+		if(((thiz->brick[i] + 1) % thiz->width) == 0)
+		{	
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;
+		}
+
+		/* check collision */
+		if(rt_tetris_check_collision(thiz, thiz->brick[i] + 1) == RT_EOK)
+		{	
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;
+		}
+	}	
+	
+	for(i=0; i<4; i++)
+	{	
+		/* move one step to right */
+		thiz->brick[i] ++;;
+	}		
+
+	/* append the brick to tetris panel */
+	rt_tetris_append_brick(thiz, thiz->brick);
+
+	/* update view */
+	thiz->view->update(thiz->view, thiz);
+
+	return RT_EOK;
+}
+
+/**
+ * this function makes current brick drop quickly
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_drop(rt_tetris_t* thiz)
+{
+	rt_err_t ret;
+	RT_ASSERT(thiz != RT_NULL);
+
+	if(thiz->status == RT_FALSE) return -RT_ETIMEOUT;
+
+	/* move down until blocked */
+	while((ret = rt_tetris_down(thiz)) == RT_EOK);
+
+	return ret;
+}
+
+/**
+ * this function makes current brick do rotation
+ *
+ * @param thiz the tetris instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_rotate(rt_tetris_t* thiz, rt_bool_t direction)
+{
+	int i;
+	rt_uint32_t tmp[4];
+	RT_ASSERT(thiz != RT_NULL);	
+
+	if(thiz->status == RT_FALSE) return -RT_ERROR;
+
+	rt_tetris_delete_brick(thiz, thiz->brick);
+
+	tmp[0] = thiz->brick[0];
+	for(i=1; i<4; i++)
+	{
+		int diff = thiz->brick[0] - thiz->brick[i];
+		if(diff == 1)
+		{
+			tmp[i] = thiz->brick[0] - thiz->width;
+		}
+		else if(diff == -1)
+		{
+			tmp[i] = thiz->brick[0] + thiz->width;
+		}
+		else if(diff == 2)
+		{
+			tmp[i] = thiz->brick[0] - 2 * thiz->width;
+		}
+		else if(diff == -2)
+		{
+			tmp[i] = thiz->brick[0] + 2 * thiz->width;
+		}
+		else if(diff == thiz->width - 1)
+		{
+			tmp[i] = thiz->brick[0] + thiz->width + 1;
+		}
+		else if(diff == 1 - thiz->width)
+		{
+			tmp[i] = thiz->brick[0] - thiz->width - 1;
+		}
+		else if(diff == thiz->width)
+		{
+			if((thiz->brick[0] + 1) % thiz->width == 0) 
+			{
+				/* restore the deleted brick */
+				rt_tetris_append_brick(thiz, thiz->brick);				
+				return -RT_ERROR;
+			}
+			else tmp[i] = thiz->brick[0] + 1;
+		}
+		else if(diff == -1 * (thiz->width))
+		{
+			if(thiz->brick[0] % thiz->width == 0)
+			{	
+				/* restore the deleted brick */
+				rt_tetris_append_brick(thiz, thiz->brick);			
+				return -RT_ERROR;
+			}
+			else tmp[i] = thiz->brick[0] - 1;
+		}
+		else if(diff == thiz->width + 1)
+		{
+			tmp[i] = thiz->brick[0] - thiz->width + 1;
+		}
+		else if(diff == -1 - thiz->width)
+		{
+			tmp[i] = thiz->brick[0] + thiz->width - 1;
+		}
+		else if(diff == 2 * thiz->width)
+		{
+			if((thiz->brick[0] % thiz->width) >= (thiz->width - 2)) 
+			{
+				/* restore the deleted brick */
+				rt_tetris_append_brick(thiz, thiz->brick);			
+				return -RT_ERROR;
+			}
+			else tmp[i] = thiz->brick[0] + 2;
+		}
+		else if(diff == -2 * thiz->width)
+		{
+			if((thiz->brick[0] % thiz->width) < 2) 
+			{
+				/* restore the deleted brick */
+				rt_tetris_append_brick(thiz, thiz->brick);			
+				return -RT_ERROR;
+			}
+			else tmp[i] = thiz->brick[0] - 2;
+		}
+		
+		if(tmp[i] > (thiz->height) * thiz->width) 
+		{
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;		
+		}
+
+		if(rt_tetris_check_collision(thiz, tmp[i]) == RT_EOK)
+		{
+			/* restore the deleted brick */
+			rt_tetris_append_brick(thiz, thiz->brick);
+			return -RT_ERROR;		
+		}
+	}
+
+	/* do roration */
+	for(i=0; i<4; i++)
+	{
+		thiz->brick[i] = tmp[i];
+	}
+
+	/* append the brick to tetris panel */
+	rt_tetris_append_brick(thiz, thiz->brick);
+
+	/* update view */
+	thiz->view->update(thiz->view, thiz);
+
+	return RT_EOK;
+}
+
+/**
+ * this function add a view to the tetris
+ *
+ * @param thiz the tetris instance.
+ * @param view the view instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+rt_err_t rt_tetris_add_view(rt_tetris_t* thiz, rt_tetris_view_t* view)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	/* Only suppurt single view now */
+	thiz->view = view;
+
+	return RT_EOK;
+}
+
+/**
+ * this function delete a view from the tetris
+ *
+ * @param thiz the tetris instance.
+ * @param view the view instance.
+ *
+ * @return RT_EOK on success, -RT_ERROR on fail
+ */
+
+rt_err_t rt_tetris_delete_view(rt_tetris_t* thiz, rt_tetris_view_t* view)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	thiz->view = RT_NULL;
+
+	return RT_EOK;
+}
+
+/**
+ * this function used to check collision
+ *
+ * @param thiz the tetris instance.
+ * @param block the block to be checked.
+ *
+ * @return RT_EOK on collision, -RT_ERROR on not collision
+ */
+rt_err_t rt_tetris_check_collision(rt_tetris_t* thiz, rt_uint32_t block)
+{
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(block < thiz->height * thiz->width);
+
+	if((thiz->panel[block/thiz->width] & (1 << (block % thiz->width)))
+		== (1 << (block % thiz->width)))
+	{
+		return RT_EOK;
+	}
+	else
+	{
+		return -RT_ERROR;
+	}
+}
+
+static rt_err_t rt_tetris_update_brick(rt_tetris_t* thiz)
+{
+	int index;
+
+	RT_ASSERT(thiz != RT_NULL);
+
+	index = (int)(7.0 * rand()/(RAND_MAX + 1.0)); 
+
+	rt_memcpy(thiz->brick, thiz->next_brick, 4 * sizeof(rt_uint32_t));
+	rt_memcpy(thiz->next_brick, g_brick[index], 4 * sizeof(rt_uint32_t));
+
+	/* update next brick on view */
+	thiz->view->update_next_brick(thiz->view, thiz);
+		
+	return RT_EOK;
+}
+
+static rt_err_t rt_tetris_append_brick(rt_tetris_t* thiz, rt_uint32_t brick[])
+{
+	int i;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(brick != RT_NULL);
+
+	for(i=0; i<4; i++)
+	{
+		int y = brick[i]/thiz->width;
+		int x = brick[i]%thiz->width;
+
+		thiz->panel[y] |= (1<<x);
+	}
+
+	return RT_EOK;
+}
+
+static rt_err_t rt_tetris_delete_brick(rt_tetris_t* thiz, rt_uint32_t brick[])
+{
+	int i;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(brick != RT_NULL);
+
+	for(i=0; i<4; i++)
+	{
+		int y = brick[i]/thiz->width;
+		int x = brick[i]%thiz->width;
+
+		thiz->panel[y] &= ~(1<<x);
+	}
+
+	return RT_EOK;
+}
+
+static rt_err_t rt_tetris_is_reach_top(rt_tetris_t* thiz, rt_uint32_t brick[])
+{
+	int i;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(brick != RT_NULL);
+
+	for(i=0; i<4; i++)	
+	{
+		if(brick[i] / thiz->width == 0)
+			return RT_EOK;
+	}
+
+	return -RT_ERROR;
+}
+
+static rt_err_t rt_tetris_release_lines(rt_tetris_t* thiz, rt_uint32_t brick[])
+{
+	int i, j, check_line = 0;
+	rt_bool_t line_released = -RT_ERROR;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(brick != RT_NULL);
+
+	for(i=0; i<4; i++)
+	{
+		/* choose a line */
+		check_line = brick[i]/thiz->width;	
+		if((thiz->panel[check_line]) == ((1 << thiz->width) - 1))
+		{
+			for(j=check_line; j>0; j--)
+			{
+				thiz->panel[j] = thiz->panel[j-1];
+			}
+			
+			/* clear the first line */
+			thiz->panel[0] = 0;
+			
+			for(j=i+1; j<4; j++)
+			{
+				if(brick[j] < brick[i])
+				{
+					brick[j] += thiz->width;
+				}
+			}
+			
+			thiz->lines++;
+			thiz->score += 100;
+			line_released = RT_EOK;				
+		}
+	}
+
+	if(line_released == RT_EOK)
+	{
+		/* update view */
+		thiz->view->update_score_and_lines(thiz->view, thiz);
+		return RT_EOK;
+	}
+	else
+	{
+		return -RT_ERROR;
+	}
+}
+

+ 184 - 0
examples/module/tetris/tetris_ui.c

@@ -0,0 +1,184 @@
+/*
+ * File      : tetris_ui.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2010, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2010-08-14     Yi.Qiu      first version
+ */
+ 
+#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/view.h>
+#include <rtgui/widgets/label.h>
+#include <rtgui/widgets/button.h>
+#include <rtgui/widgets/window.h>
+#include <rtgui/widgets/workbench.h>
+#include <rtgui/dc.h>
+#include "tetris.h"
+
+struct app_info
+{
+	struct rtgui_view* home_view;
+	struct rtgui_workbench* workbench;
+	rt_tetris_t * tetris;
+	rt_tetris_view_t* tetris_view;
+	rtgui_timer_t* _timer;
+};
+typedef struct app_info app_info;
+static app_info g_app_info;
+
+static void _game_over(void)
+{
+	rtgui_timer_stop(g_app_info._timer);
+	rt_tetris_pause(g_app_info.tetris);	
+	rt_tetris_destory(g_app_info.tetris);
+	rt_tetris_view_destroy(g_app_info.tetris_view);	
+	rtgui_view_destroy(g_app_info.home_view);
+	rtgui_workbench_close(g_app_info.workbench);
+	rt_kprintf("GAME OVER\n");
+}
+
+static rt_bool_t home_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	if (event->type == RTGUI_EVENT_PAINT)
+	{
+		struct rtgui_dc* dc;
+		rtgui_rect_t rect;
+
+		/* draw child */
+		rtgui_view_event_handler(widget, event);
+
+		dc = rtgui_dc_begin_drawing(widget);
+		if (dc == RT_NULL) return -RT_ERROR;
+		rect.x1 = 96;
+		rect.y1 = 0;
+		rect.x2 = 128;
+		rect.y2 = 16;
+		rtgui_dc_draw_text(dc, "next", &rect);
+		rect.y1 += 30;
+		rect.y2 = rect.y1 + 16;
+		rtgui_dc_draw_text(dc, "level", &rect);
+		rect.y1 += 22;
+		rect.y2 = rect.y1 + 16;
+		rtgui_dc_draw_text(dc, "lines", &rect);
+		rect.y1 += 22;
+		rect.y2 = rect.y1 + 16;
+		rtgui_dc_draw_text(dc, "score", &rect);
+		rtgui_dc_end_drawing(dc);
+
+		/* start tetris game, removed later */
+	   	rt_tetris_start(g_app_info.tetris);
+		return RT_FALSE;
+	}
+	else if ((event->type == RTGUI_EVENT_KBD))
+	{
+		struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
+		
+		if (ekbd->type == RTGUI_KEYDOWN)
+		{
+			if (ekbd->key == RTGUIK_RIGHT)
+			{
+				rt_tetris_right(g_app_info.tetris);	
+			}
+			else if (ekbd->key == RTGUIK_LEFT)
+			{
+				rt_tetris_left(g_app_info.tetris);	
+			}
+			else if (ekbd->key == RTGUIK_UP)
+			{
+				rt_tetris_rotate(g_app_info.tetris, RT_EOK);				
+			}
+			else if (ekbd->key == RTGUIK_DOWN)
+			{
+				if( rt_tetris_drop(g_app_info.tetris) == -RT_ETIMEOUT
+					&& rt_tetris_status(g_app_info.tetris) != RT_FALSE)
+				{
+					_game_over();
+				}
+			}
+		}
+	}
+
+	return rtgui_view_event_handler(widget, event);
+}
+
+static void _timer_timeout(rtgui_timer_t* timer, void* parameter)
+{
+	if( rt_tetris_down(g_app_info.tetris) == -RT_ETIMEOUT)
+	{
+		_game_over();
+	}		
+}
+
+static rt_bool_t workbench_event_handler(rtgui_widget_t *widget, rtgui_event_t *event)
+{
+	if (event->type == RTGUI_EVENT_KBD)
+	{
+		struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
+		if (((ekbd->type == RTGUI_KEYUP) && ekbd->key == RTGUIK_HOME)
+				&& !RTGUI_WORKBENCH_IS_MODAL_MODE(g_app_info.workbench))
+		{
+			/* active home view */
+			if (g_app_info.workbench->current_view != g_app_info.home_view)
+			{
+				rtgui_view_show(g_app_info.home_view, RT_FALSE);
+				return RT_TRUE;
+			}
+		}
+	}
+
+	return rtgui_workbench_event_handler(widget, event);
+}
+
+void tetris_ui_entry(void* parameter)
+{
+	rt_mq_t mq;
+
+	mq = rt_mq_create("tetris_ui", 256, 4, RT_IPC_FLAG_FIFO);
+	rtgui_thread_register(rt_thread_self(), mq);
+
+	g_app_info.workbench = rtgui_workbench_create("main", "workbench");
+	if (g_app_info.workbench == RT_NULL) 
+	{
+		rt_kprintf("can't find panel 'main'\n");
+		return;
+	}	
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(g_app_info.workbench), workbench_event_handler);
+
+	/* add home view */
+	g_app_info.home_view = rtgui_view_create("Home");
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(g_app_info.home_view), home_view_event_handler);
+
+	rtgui_workbench_add_view(g_app_info.workbench, g_app_info.home_view);
+	/* this view can be focused */
+	RTGUI_WIDGET(g_app_info.home_view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+	/* set widget focus */
+	rtgui_widget_focus(RTGUI_WIDGET(g_app_info.home_view));
+	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(g_app_info.home_view)) = RTGUI_RGB(0xff, 0xff, 0xff);	
+	rtgui_view_show(g_app_info.home_view, RT_FALSE);
+
+	/* create tetris modal instance */
+	g_app_info.tetris = rt_tetris_create(16, 17);
+
+	/* create tetris view instance */
+	g_app_info.tetris_view = rt_tetris_view_create(RTGUI_WIDGET(g_app_info.home_view));	
+
+	/* register tetris view to tetris modal */
+	rt_tetris_add_view(g_app_info.tetris, g_app_info.tetris_view);
+		
+	g_app_info._timer = rtgui_timer_create(40, RT_TIMER_FLAG_PERIODIC, _timer_timeout, RT_NULL);
+	rtgui_timer_start(g_app_info._timer);
+
+	rtgui_workbench_event_loop(g_app_info.workbench);
+	rtgui_workbench_destroy(g_app_info.workbench);
+
+	rtgui_thread_deregister(rt_thread_self());
+	rt_mq_delete(mq);
+}
+

+ 218 - 0
examples/module/tetris/tetris_view.c

@@ -0,0 +1,218 @@
+/*
+ * File      : tetris_view.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2010, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2010-08-14     Yi.Qiu       first version
+ */
+ 
+#include <rtthread.h>
+#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/view.h>
+#include <rtgui/dc.h>
+#include "tetris.h"
+
+static rt_err_t _rt_tetris_view_update(rt_tetris_view_t* thiz, rt_tetris_t* tetris);
+static rt_err_t _rt_tetris_view_update_next_brick(rt_tetris_view_t* thiz, rt_tetris_t* tetris);
+static rt_err_t _rt_tetris_view_update_level(rt_tetris_view_t* thiz, rt_tetris_t* tetris);
+static rt_err_t _rt_tetris_view_update_score_and_lines(rt_tetris_view_t* thiz, rt_tetris_t* tetris);
+
+rt_tetris_view_t* rt_tetris_view_create(void* private)
+{
+	rt_tetris_view_t* thiz;
+
+	RT_ASSERT(private != RT_NULL)
+
+	thiz = (rt_tetris_view_t*)rt_malloc(sizeof(rt_tetris_view_t));
+	thiz->width = 96;
+	thiz->height = 96;
+
+	thiz->update = _rt_tetris_view_update;
+	thiz->update_next_brick = _rt_tetris_view_update_next_brick;
+	thiz->update_level = _rt_tetris_view_update_level;
+	thiz->update_score_and_lines = _rt_tetris_view_update_score_and_lines;
+	thiz->private = private;
+
+	return thiz;
+}
+
+rt_err_t rt_tetris_view_destroy(rt_tetris_view_t* thiz)
+{
+	RT_ASSERT(thiz != RT_NULL);
+
+	rt_free(thiz);
+
+	return RT_EOK;
+}
+
+static rt_err_t _rt_tetris_view_update_next_brick(rt_tetris_view_t* thiz, rt_tetris_t* tetris)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+	rt_uint32_t width;
+	rt_uint32_t ppb, i;
+	rtgui_widget_t* widget;
+	rt_uint32_t* next_brick;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(tetris != RT_NULL);
+
+	next_brick = rt_tetris_next_brick(tetris);
+	widget = (rtgui_widget_t*)thiz->private;
+	width = rt_tetris_width(tetris);
+	/* pixel per block */
+	ppb = thiz->width / width; 
+
+	dc = rtgui_dc_begin_drawing(widget);
+	if (dc == RT_NULL) return -RT_ERROR;
+
+	rect.x1 = 100;
+	rect.x2 = rect.x1 + 4 * ppb;
+	rect.y1 = 16;
+	rect.y2 = rect.y1 + 2 * ppb;
+
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff);
+	rtgui_dc_fill_rect(dc, &rect);
+
+	for(i=0; i<4; i++)
+	{
+		rt_uint32_t y = next_brick[i] / width;
+		rt_uint32_t x = next_brick[i] % width;
+
+		rect.x1 = 100 + ppb * (x - 6);
+		rect.x2 = rect.x1 + ppb - 1;
+		rect.y1 = 16 + ppb * y ;
+		rect.y2 = rect.y1 + ppb - 1;
+
+		RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00);
+		rtgui_dc_fill_rect(dc, &rect);
+	}
+
+	rtgui_dc_end_drawing(dc);
+
+	return RT_EOK;	
+}
+
+static rt_err_t _rt_tetris_view_update_level(rt_tetris_view_t* thiz, rt_tetris_t* tetris)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+	rtgui_widget_t* widget;
+	char text[4];
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(tetris != RT_NULL);
+
+	widget = (rtgui_widget_t*)thiz->private;
+	dc = rtgui_dc_begin_drawing(widget);
+	if (dc == RT_NULL) return -RT_ERROR;
+
+	rect.x1 = 96;
+	rect.y1 = 42;
+	rect.x2 = 128;
+	rect.y2 = rect.y1 + 10;
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff);
+	rtgui_dc_fill_rect(dc, &rect);
+	rt_sprintf(text, "%d", rt_tetris_level(tetris));
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00);
+	rtgui_dc_draw_text(dc, text, &rect);
+
+	/* Redraw panel */	
+	rtgui_dc_end_drawing(dc);
+
+	return RT_EOK;	
+}
+
+static rt_err_t _rt_tetris_view_update_score_and_lines(rt_tetris_view_t* thiz, rt_tetris_t* tetris)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+	rtgui_widget_t* widget;
+	char text[4];
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(tetris != RT_NULL);
+
+	widget = (rtgui_widget_t*)thiz->private;
+	dc = rtgui_dc_begin_drawing(widget);
+	if (dc == RT_NULL) return -RT_ERROR;
+
+	rect.x1 = 96;
+	rect.y1 = 64;
+	rect.x2 = 128;
+	rect.y2 = rect.y1 + 10;
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff);
+    	rtgui_dc_fill_rect(dc, &rect);
+	rt_sprintf(text, "%d", rt_tetris_lines(tetris));
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00);
+	rtgui_dc_draw_text(dc, text, &rect);
+
+	rect.y1 += 22;
+	rect.y2 = rect.y1 + 10;
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff);
+	rtgui_dc_fill_rect(dc, &rect);
+	rt_sprintf(text, "%d", rt_tetris_score(tetris));
+	RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00);
+	rtgui_dc_draw_text(dc, text, &rect);
+
+	/* Redraw panel */	
+	rtgui_dc_end_drawing(dc);
+
+	return RT_EOK;	
+}
+
+static rt_err_t _rt_tetris_view_update(rt_tetris_view_t* thiz, rt_tetris_t* tetris)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+	rt_uint32_t width, height;
+	rt_uint32_t j,k, ppb;
+	rtgui_widget_t* widget;
+
+	RT_ASSERT(thiz != RT_NULL);
+	RT_ASSERT(tetris != RT_NULL);
+
+	widget = (rtgui_widget_t*)thiz->private;
+	width = rt_tetris_width(tetris);
+	height = rt_tetris_height(tetris);
+	ppb = thiz->width / width;
+
+	dc = rtgui_dc_begin_drawing(widget);
+	if (dc == RT_NULL) return -RT_ERROR;
+
+	/* Redraw panel */
+	for(j=0; j<width; j++)
+	{
+		for(k=1; k<height; k++)
+		{
+			rect.x1 = ppb * j;
+			rect.x2 = ppb * (j + 1) - 1;
+			rect.y1 = ppb * (k - 1);
+			rect.y2 = ppb * k - 1;
+
+			if(rt_tetris_check_collision(tetris, k * width + j))
+			{
+				RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0xff, 0xff);
+			}
+			else
+			{
+				RTGUI_DC_BC(dc) = RTGUI_RGB(0xff, 0x00, 0x00);
+			}
+
+			rtgui_dc_fill_rect(dc, &rect);
+		}	
+	}
+
+	/* Redraw panel */	
+	rtgui_dc_end_drawing(dc);
+
+	return RT_EOK;	
+}
+