2011年10月4日星期二

Arduino LCD programming

Today, I wrote an arduino program to control the LCD at Chaihuo. There are eight channels on the LCD, you can press the button to change the channel, current channel has a asterisk "*" mark, and tuning the knob will adjust current channel's value.



P.S: I think Tully is very good at photography, I like his photos so much :-)

2011年9月12日星期一

Be the change you want to see!

These days, I am so happy to meet a guy whose name is Mitch, a versatile person from Australia. While talking about software, I am convinced that he is a software engineer; while talking about hardware, I am also sure he is a hardware engineer; while even talking about economy, I was wondering if he is a economist? With so many deep understanding :-) .

Moreover, he is a guy who fully understands the spirit of open source. He brought beer, playpause and lots of interesting projects to SZDIY, and all of these projects are open source. So Mitch really truly thoroughly makes a change to SZDIY, that is why SZDIY has a big day called "Mitch joins SZDIY".

For me, he suggested me that "be the change you want to see". I think I am ready to go, even every step is tiny, the combination will make that change!

Thank you Mitch, I appreciate all the help you've given me!

2011年8月10日星期三

AMCC 1.0 release

I am happy to announce that AMCC 1.0 is coming, have fun!
AMCC github









/*
* AMCC (Anders Ma Copter Control)
* (www.andersma.net)
*/


General Information
===================

AMCC is an utility for copter development.
With AMCC you can monitor copter's sensors data, you can use sensors data
to develop flight control algorithm. In the future, you can use AMCC to
config and operate copter.

Licensing
=========

AMCC is released under BSD license.

Requirements
============

To compile AMCC, you must install following packages:

* libgtk2.0-dev
* libgtkglext1-dev
* freeglut3-dev
* lib3ds-dev
* libxml2-dev

HOW-TO
============

To use AMCC to monitor/control copter, copter must support AMCC protocol, How?

1) Copter MCU software must contain following code and linked with src/packet.c:

#include "packet.h"

char buffer[50];
packet_t p;

p.type = ANALOG_DATA_RESPONSE;
p.raw.analog_data.channel_number = 6;
p.raw.analog_data.value[0] = accx; /* accelerometer X axes data got from ADC */
p.raw.analog_data.value[1] = accy; /* accelerometer Y axes data got from ADC */
p.raw.analog_data.value[2] = accz; /* accelerometer Z axes data got from ADC */
p.raw.analog_data.value[3] = gyrox; /* gyroscope X axes data got from ADC */
p.raw.analog_data.value[4] = gyroy; /* gyroscope Y axes data got from ADC */
p.raw.analog_data.value[5] = gyroz; /* gyroscope Z axes data got from ADC */

packet_encode(&p);
memcpy(buffer, &p.data, p.data_length);
txd_buffer[p.data_length] = 0;
printf("%s", buffer); /* output data over serial port */

2)connecting PC with copter as below:

[PC] ---serial line----- [Copter]

3) #./amcc -d /dev/SERIALDEV -s SPEED
(replace SERIALDEV and SPEED according your environment, default is ttyUSB0, 57600)

4) Click menuitem "Monitor->Start", if copter is sending sensors data, AMCC will draw Acc & Gyro voltage graph and render 3D copter.



2011年8月6日星期六

日记 2009 07~09

2009年折腾一款STM32F103开发板的日记。回顾日记,发觉自己每年七月八月很多产,很努力!

7/27/2009
Vista上安装MDK 设置J8J9启动方式
7/28/2009
NOR/SRAM/NAND
仿真软件Openocd JLINK读回Flash数据并做了对比,发现板子程序与我编译出来的程序只有时间上的差异。
用MDK生成bin文件方法:fromelf.exe --bin -o $L@L.bin #L
7/29/2009
STM32 demo using Eclipse, OpenOCD and GCC http://developers.stf12.net/eclipse-demo
根据"图解MDK 3.5+Jlink V7在STM32中SRAM调试成功"文档, 成功下载GPIO程序到板子上,在不烧FLASH的情况下对程序进行了验证,非常好玩!
7/30/2009
学习 cortexm3_macro.s & stm32f10x_vector.s 文件
使用Keil Simulator 来仿真调试,查看汇编代码 分析Keil Linker control code: --ro-base 0x08000000 --entry 0x08000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors -结论是编译出来的程序以__Vectors文本区块打头
7/31/2009
阅读STM32103XX参考手册
8/10/2009 研究用串口烧写程序,用那个Demonstrator总是不能成功操作,非常不爽 :(
8/13/2009
从Micrium官方下载了 STM32的uC/OS-II,看了些文档,并与红牛板子的包做了些对比。
8/14/2009
看了一些LCD的接口,了解了大概操作LCD的步骤。下面是红牛板子的相关信息:
LCD 采用FSMC_NE4 PIN做片选,访问地址为 0X6C000000
NOR 采用FSMC_NE2 PIN做片选,访问地址为 0X64000000
SRAM 采用FSMC_NE3 PIN做片选,访问地址为 0X68000000
NAND 采用FSMC_NCE2 PIN做片选,访问地址为 0X70000000
回家把ouravr网友的tft程序放到我的板子里,可以看到屏幕显示文字,不过字却是反的,需要继续debug。
8/15/2009
合并了板子自带的LCD驱动初始化代码,依然没有解决问题,反而不显示文字了,看来需要更深入的读一下DS。
8/16/2009
修改了一下绘制行和字符的函数,目前可以正常显示字符。
8/17/2009
阅读了ILI9325的DS 1-7章
8/21/2009
阅读STM32103XX参考手册ADC章节[ST11.3.7]
8/22/2009
阅读STM32103XX参考手册ADC章节[ST11.9]
折腾串口程序,发现接收卡死在那里,最后我认定是串口有问题,与卖家协商更换。
深圳市龙岗区布吉荣超花园xx栋x单元xxx,胡先生,13392xxxxxx
8/23/2009
1. 粗略阅读STM32103XX参考手册 Memory and Bus Architecture 和 RCC 章节, 基本掌握系统架构
2. 弄清楚Rcc_Configuration()函数细节
3. 粗略阅读STM32103XX参考手册 Interrupts and Events 章节
8/24/2009
1. 阅读一下ST ADC3的例子
2. 阅读Cortex-M3 Tech Ref Manual NVIC 部分
8/25/2009~8/26/2009
1. 拿回来了板子,在家做测试
2. 目前串口可以烧写程序了,之前烧写不成功主要是速度过快的问题,设置低速比较好
3. 烧写程序应该使用hex的格式,bin的烧进去不能执行
8/26/2009
1. 晚上花了2个小时对加速度传感器模块进行实验,得出如下结论
a. SLEEP PIN 需要拉高(3.3V),才能使加速度传感器进入工作模式
b. Z轴长期处于+-g的输出电压模式,其他轴如果水平状态下呈0g电压状态
c. 实验数据:X 1.69,Y 1.50, 0.83
备注:中途实验不成功,我打算明天焊接实验班再做实验,不过时间足够,我逼迫自己继续下去,我又一次战胜自己的懒惰!
8/27/2009
1. 白天在公司写了ADC数据处理程序,带串口和LCD数据输出
2. 晚上回来对程序进行验证,串口和LCD都正常,靠,有点佩服自己了,哈~
3. 接好ADC线,发现数据正常,ADC用[0~4096]来诠释[0~3.3v]电压,目前我的XYZ轴数据分别为
8/28/2009
1. 阅读MK 0.71代码,
a 寻找如何传送加速度计调试数据
b 寻找MK如何处理加速度计的方法(起飞前用200次的数据校正加速度计,Nature/Mean方式设计得还算巧妙)
2. MK 利用了"卡尔曼滤波"理论来控制飞行姿态
3. 晚上回来调试程序,目前可以用MK的程序来显示我ADC的变化了,哈哈啊哈~
8/28/2009
1.开始重头学习高等数学
2. 尝试使用SD卡程序,结果不能读,看来是SD卡读那块有问题,需要继续解决。
1/9/2009~2/9/2009
1 研究飞控算法,有些突破的就是明白如何校正那些传感器。(a 左上校正sensor,同时NICK&ROLL的数值决定选择哪套参数 b 右上保存传感器信息到EEPROM c 右下开启马达准备飞行)
2 ENC03采用科里奥里力来获取角速度,所以我需要弄清楚陀螺仪原理 http://zh.wikipedia.org/wiki/科里奥利力
3/9/2009
1 了解电磁波/射频(>100KHZ的电磁波)定义 a c=λf
2 雷达是用电磁波来探测目标,并检测其速度和其他特征的一种电子设备
3 回想起当初TVBGONE 38K红外载波的意思,只是形成频率是38K的脉冲去驱动红外发射LED而已。
4 UAV unmanned aerial vehicles
5 1 000 000 nm = 1m
6 微波波长范围在 1mm~1m
5/9/2009
1 飞控算法电机调整口诀: 左+右-;前+后- (+-pd_result)
7/9/2009
1 为什么MK中计算陀螺仪的积分就变成了单纯的ADC差值?
13/9/2009
1 这个周末去学校玩了一下飞行器,基本掌握如何操纵它

2011年8月3日星期三

2011年7月29日星期五

NOVELL She Calves Puzzle

iIf a cow produces its first she-calf at age two years and after that
produces another single she-calf every year, how many she-calves are
there after 12 years? assuming none die.

My Answer

2011年7月17日星期日

Linux 0.11 内核完全注释 笔记(三)

>2 fork 做什么?
>半斤回答:准备LDT,TSS,页目录,页表...

在Linux内核中,一个进程是用struct task_struct类型的变量来标记。所以fork首先是创建了一个新的struct task_struct类型的变量,对其进行相应的赋值。

重要的是,新建进程的TSS,LDT表,页目录和页表是全新创建的,在存储上和父进程完全没有关系,不同的两个实体。但新进程LDT所指向的数据段和代码段完全照抄父亲进程,指令指针也同父进程一致。也就是说,父子进程共享代码段,数据段和堆栈段都是相同的地址空间。好比两个锦囊装着同一妙计,嘿嘿!

插一句:从这里看fork的两次返回是那么的自然,两个进程指令指针(EIP)都一样,能没有两个返回吗?

更重要的事,fork过程中将父子进程所有页表都设置成了Read Only, 为啥子啊? 为了实现Copy On Write技术。由于页表项设置成了只读模式,每次写页表项所对应的页面时(比如函数调用把参数放入堆栈)都会引起写保护页异常,CPU会自动执行异常处理函数,进而调用 do_wp_page 函数来分配一个新的页面,挂载到引起写异常的页表项目,之后设置页表项可读可写。这个技术就叫Copy On Write。Copy On Write 完全是一种按需分配的技术,缺页/写保护页面异常是伟大的设计,因为它缔造了Copy On Write,缔造了虚拟内存技术!

这里还有一个问题值得思考,假设fork之后的程序马上会对数据段进行写动作,进而导致CPU进入写保护页面异常处理程序,谁的页表项会指向新分配的空间呢?父 or 子?

答案取决于谁先引起写保护页面异常。假设儿子引起了异常,那么儿子的页表项会指向新的分配空间;假设是父亲引起了异常,父亲的页表项会指向新空间,这样之前父亲占用的空间就归儿子所有了。很有趣的逻辑啊!

代码参考:
sys_fork -> copy_process
http://oldlinux.org/lxr/http/source/kernel/fork.c#L68
un_wp_page
http://oldlinux.org/lxr/http/source/mm/memory.c#L221

2011年7月16日星期六

Linux 0.11 内核完全注释 笔记(二)

有句话说提出问题比解决问题重要。是啊,我想看书也是一样。能预先提出问题,带着问题去看书会事半功倍。这次我再读此书想先问自己N多关心的问题,在阅读的时候去求索,然后写出笔记一一解开自己的心结。虽然这些问题我大概略之一二,但是半斤八两的感觉和我此次刨根问底的原则不吻合。目前能想到的关键问题如下:


进程管理

1 进程如何切换?
半斤回答:JMP 到预切换到任务的 TSS

2 fork 做什么?
半斤回答:准备LDT,TSS,页目录,页表...

3 exec 做什么?

4 进程调度算法?

内存管理

5 系统的发动机,缺页异常具体实现?
半斤回答:就是从SWAP/FS往内存放数据

设备管理

6 磁盘请求队列算法?
半斤回答:电梯算法,插入使链表排序。

7 键盘驱动?

8 显示器如何折腾?

文件系统

9 fd管理与pipe通信?

10 知识盲区啊,提不出什么好问题了?!

2011年7月13日星期三

Linux 0.11 内核完全注释 笔记(一)

有人说:”初恋不懂爱情!“。的确,五年前我读了《Linux 0.11 内核完全注释》一书,茫然的看完,悄然的离去。所幸的是种下了一个Idea:“这书还是不错的。”

五年后,再读此书,感触颇多,当读到move_to_user_mode这个神器时不由自主在weibo上像文人骚客一样发出如下感叹:

”一生至少该有一次,为了某段代码而陶醉自己,不求年代,不求国籍,不求编程语言,甚至不求编译运行,只求在我思索的年华里,遇到你。“
http://oldlinux.org/lxr/http/source/include/asm/system.h#L1

言归正传,笔记开始!

写操作系统不读CPU手册和上厕所不带纸是一个概念,不是扯淡就是高手!所以此书上来先介绍了X86保护模式编程的东东,只有弄清楚这些东东,才能9浅1深的去理解Kernel。X86的保护模式编程个人感觉还是挺复杂的,毕竟要游走于N多概念之间。

Q1 逻辑地址如何转换到物理地址?

Logical Address (逻辑地址)
Linear Address (线性地址)
Physical Address (物理地址)

这些是地址,我们的程序编译完的地址可以粗略理解成逻辑地址,在开启保护模式的情况下,CPU在指令运算时,都需要把程序的逻辑地址转换到真实的物理地址上。怎么转换?靠查表!怎么查?要查表首先要知道表在哪里,然后要知道表的Index,进而得到表项,得到表项后再分析就可以得到真实的物理地址。顺藤摸瓜也!Intel的X86 CPU已经把藤和瓜所需的数据结构都准备好了。

Local Descriptor Table (局部描述符表)LDT
Gloal Descriptor Table (全局描述符表)GDT
Local Descriptor Table Register (局部描述符表寄存器)LDTR
Gloal Descriptor Table Register (全局描述符表寄存器)GDTR
LDT/GDT是表,表的线性地址放在了LDTR/GDTR寄存器中,这是“藤1”。


Code Segment Selector (代码断选择符) CS
Data Segment Selector (数据段选择符) DS
Stack Segment Selector (堆栈段选择符) SS
{C|D|S}S这些是段选择符,Bit2标识使用GDT or IDT,bit3~15是Index信息,这是“藤2”。

Code Segment Descriptor (代码段描述符)
Data Segment Descriptor (数据段描述符)
System Segment Descriptor (系统段描述符)
系统断描述符又可分为:
1 LDT段描述符
2 TSS(Task State Segment)描述符
3 中断门描述符
4 调用门描述符
5 任务门描述符
6 陷阱门描述符
LDT/GDT中的表项就是这些{断|门}描述符,每个描述符都占用8个Byte空间,这是“藤3”。

所以CPU在逻辑地址转换到物理地址过程中,顺着藤1,藤2,找到了藤3。
找到藤3之后,CPU解剖了藤3,挖出了段基地址,然后与逻辑地址相加,这样就得出线性地址。

在没有开启分页机制情况下,线性地址就是真实的物理地址。如果已经开启分页,那就要再顺着“藤4”去摸。CR3寄存器存放着当前任务使用页目录的物理地址。这是"藤4“。经过分析后直接找到物理地址,顺藤摸瓜结束。

Intel还算厚道,没来个18摸,最多也就是Inception的3重梦境。累了,以后再写!

2011年6月16日星期四

LFS 纪念

今天已经成功将LFS Linux放到了U盘。从5月初下载源码包,到今天也一个多月了。断断续续的在复制粘贴着命令,初步统计为此计划耗时应该在20小时左右。20小时的工作,我分散到了一个月做,不是我有耐力,而是有用一个poor/short记忆力,总想不起来此事。:-(

目前LFS Linux进入Shell大概需要20s,速度有些慢,主要时间是花在从U盘拷贝 kernel到RAM。后续还需要多多折腾。

我所使用的是LFS 6.8 http://www.linuxfromscratch.org/lfs/downloads/stable/LFS-BOOK-6.8-HTML.tar.bz2 只要从头到尾做,基本可以确定会顺利启动属于你自己的Linux。期间唯一遇到的问题是Kernel无法挂载ROOT文件系统,主要是没包含NVidia的SATA驱动,去Menuconig打*瞬间解决。出于对GRUB的恐惧,没有在机器大硬盘折腾GRUB,只在grub.cfg加个选项,用原有硬盘GRUB启动我的LFS Linux。

为了制作U盘版本,首先fdisk new a primary partition which is bootable,然后将GRUB放到U盘中。大致命令如下:

#
#sudo mount /dev/sdb1 /mnt
#sudo grub-install --root-directory=/mnt /dev/sdb
#sudo grub
grub>find /boot/grub/stage1
(hd1, 0)
grub>root (hd1)
grub>setup (hd1)
#

而后干了一个比较SB的事情,去Windows下玩了这个U盘,U盘还有另一个无用分区,我在Windows下点选删除此分区,结果整个U盘的分区都被删除了,U盘变成砖头!我晕!!!!!

无奈去Linux下重新fdisk建立分区,还好我之前fdisk建立分区的尺寸是+2G,我这次也用同一参数,找回了之前的分区,数据索性还在。只是我不得不承认我很贱,为何去Windows里面折腾带有Ext3的U盘!

Windows在分区这块太过傲慢,插个自己不认识的U盘,就问你是否需要格式化,一副当带头大哥的嘴脸!Windows何时能放下傲慢?拥抱非FAT/NTFS分区?

2011年6月2日星期四

partition algorithm



int partition(int array[], int start, int end)
{
int i, j, tmp;
int key = array[start];

i = start;
for (j = start + 1; j <= end; ++j) {
if (array[j] <= key && ++i != j) {
// array[j] <=> array[i]
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
array[start] = array[i];
array[i] = key;

return i;
}

void printf_array(int array[], int from, int len)
{
int i;
for (i = 0; i < len; ++i)
printf("%d,", array[from + i]);
printf("\n");
}

int main(int argc, char** argv)
{
int array[10] = {3, 7, 21, 6, 2, -3, 90, 23443, -3000, 5};

printf("partition=%d\n", partition(array, 0, 9));
printf_array(array, 0, 10);

return 0;
}

2011年5月15日星期日

config.guess - guess the build system triplet

NAME
config.guess - guess the build system triplet

SYNOPSIS
config.guess [OPTION]

DESCRIPTION
The GNU build system distinguishes three types of machines,
the 'build' machine on which the compilers are
run, the 'host' machine on which the package being built will
run, and, exclusively when you build a compiler,
assembler etc., the 'target' machine, for which the compiler
being built will produce code.

This script will guess the type of the 'build' machine.

Output the configuration name of the system 'config.guess' is run on.

Operation modes:
-h, --help
print this help, then exit

-t, --time-stamp
print date of last modification, then exit

-v, --version
print version number, then exit

ENVIRONMENT VARIABLES
config.guess might need to compile and run C code, hence it
needs a compiler for the 'build' machine: use the
environment variable 'CC_FOR_BUILD' to specify the compiler for
the build machine. If 'CC_FOR_BUILD' is not
specified, 'CC' will be used. Be sure to specify
'CC_FOR_BUILD' is 'CC' is a cross-compiler to the 'host'
machine.

CC_FOR_BUILD a native C compiler, defaults to 'cc'
CC a native C compiler, the previous variable is preferred

REPORTING BUGS
Report bugs and patches to <config-patches AT gnu.org>.

Originally written by Per Bothner. Copyright (C) 1992, 1993,
1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.

This is free software; see the source for copying
conditions. There is NO warranty; not even for MER-
CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO
autoconf(1), automake(1), autoreconf(1), autoupdate(1),
autoheader(1), autoscan(1), config.guess(1), con-
fig.sub(1), ifnames(1), libtool(1).

config.guess (2003-10-03) October 2003
CONFIG.GUESS(1)

2011年4月19日星期二

A algorithm to enumerate all the combinations of given numbers

/*
A algorithm to enumerate all the combinations of given numbers
Author : Anders Ma [2011_0419]
*/
#include

int array[100];
int cursor = 0;

void enumerate(int n)
{
int i;

for(i = 0; i < cursor; ++i)
printf("%d,", array[i]);
if (cursor != 0)
printf("\n");

for (i = 0; i < n; ++i) {
array[cursor++] = i + 1;
enumerate(i);
cursor--;
}
}

int
main(int argc, char **argv)
{
enumerate(5);
return 0;
}

anders@ubuntu:~/c$ ./enum
1,
2,
2,1,
3,
3,1,
3,2,
3,2,1,
4,
4,1,
4,2,
4,2,1,
4,3,
4,3,1,
4,3,2,
4,3,2,1,
5,
5,1,
5,2,
5,2,1,
5,3,
5,3,1,
5,3,2,
5,3,2,1,
5,4,
5,4,1,
5,4,2,
5,4,2,1,
5,4,3,
5,4,3,1,
5,4,3,2,
5,4,3,2,1,

2011年4月11日星期一

三亚游记

没做太多准备,就去了三亚。决策过程就是两条信息:她:我们去三亚吧?我:OK!然后马上订票。去之前没预定旅馆,只是联系了三亚大东海附近的一个旅馆,不过不确定去了是否还有房间。

#
#第一天 (三亚湾吃海鲜)
#

凌晨1点到了三亚,飞机晚点起飞1个多小时。我对目前的民航调拨系统真是无语,天天流量控制。不过与朋友多次在飞机上等3个多小时的经历相比,知足了。

出了机场直接打的走人,司机是个女性,来在河南。聊天中得知三亚大部分都是外地人,毕竟是旅游城市,本地人不多。有些深圳移民城市的感觉,并不陌生。计划是去大东海的,不过司机说大东海有些远,三亚湾倒是很近,于是我们改变策略,让司机在三亚湾附近帮找了一个旅馆,安顿了下来。旅馆还算干净吧,当然和酒店是没法比了,不过出游前也没打算去酒店。旅游嘛,吃好玩好最重要,住的条件就不计较太多了。洗漱后已经半夜2点,睡到9点多,在床上赖到了10点。11点才出了旅馆,在房东的推荐下去了友谊街下岗职工海鲜广场。看到这个“下岗职工”词组,倒感觉格外亲切。在一个热心大姐的指引下,我们先去选购了海鲜:带子,基围虾,濑尿虾,芒果螺,X(一个长条的贝类,忘记名字),然后去热心大姐家加工。这边吃海鲜都是在市场先买,然后再去带到加工店加工。加工店提供煎炒烹炸,火锅之类的加工方式,收取加工费。这餐海鲜吃得很饱,比较喜欢蒸带子,椒盐濑尿虾。

吃饱喝足后,去三亚湾看海,三亚湾的海水不够清澈,不适合游泳。无趣之际,沙滩上随处可见的小洞洞引起了我的注意,经过观察,原来每个小洞里面都是一个小螃蟹,看着螃蟹吃东西,出出进进自己的洞穴,有点意思。要是有大螃蟹就好了,我可以抓一个拿去加工吃,这种指甲大小的螃蟹还是由他去吧。

<螃蟹出动>

<三亚湾>

<夜幕下的大东海>

<她>

在绿海田园车站坐8路公交车去了大东海广场,有点堵车,花了快一个小时。下车觉得好饿,找了个兰州拉面店吃了碗面条,面食价钱比深圳贵1-2块,味道一般,还不如我在大冲曾经光顾的面馆。去大东海广场途中买了个椰子,好家伙,个儿太大了,我们两个人喝得膀胱都鼓了,还没喝完,由于不方便携带,只好当垃圾处理了。味道也没感觉到惊艳,可能没碰到好的椰子。

傍晚的大东海像一个风韵少妇,让我遐思尔想。的确比三亚湾那个渔家妇女有所韵味。决定明晚来这边住,开始找旅馆。先去了一个宾馆,价格138/晚,但觉得有些吵闹。然后看到附近一个小区,走过去咨询保安小区内是否有小旅馆,保安比较热心的说,2楼4楼都有,去了2楼旅馆,觉得还不错,标双100/晚,比预期的还便宜,屋子也算宽敞明亮,最重要的是离大东海太近了。交了100块定金就坐8路车回三亚湾了。

已经22点了,当然不能错过友谊街的海鲜夜宵,还是去了中午去的大姐家,让她帮着挑选海鲜,然后拿到她的店铺,让她老公加工。晚上吃了螃蟹,海鲤鱼,蒸带子,海胆蒸蛋,拍个黄瓜,喝点啤酒,不亦乐乎!期间和加工店老板聊了起来,他们夫妻也不是海南人,来自湖南,不过口音已经听不出来,毕竟在当地十几年了。干什么行业都不容易,他们这种早出晚归的一个月也赚不了几吊钱,生活啊,就是让人感慨万千,希望有人看到我这篇文章,去三亚的时候光顾一下这个加工店,老板人还不错了,厨师也算是刀法精湛!(店铺编号10排4号)

#
#第二天 (大东海戏水)
#

昨晚睡的一般,中途被蚊子叫醒了一次,还好旅馆有电蚊香,点了之后睡到了自然醒。磨蹭出门已经11点,吃了早/午餐后就退房,坐8路公交直奔大东海旅馆。这次自助游三亚除了刚到三亚那天打的以外,其他时候都是搭乘公交车,对三亚这座城市也没什么陌生感,毫无距离。到了旅馆,和旅馆的小情侣研究了一下他们提供的不同景点的旅行团。三亚这种团游很多,有纯玩的团,有需要购物的团。随后定了一个明天去蜈支洲岛的纯玩团,就是负责车接车送,门票而已。185/人,比自己打车去划算。时至下午4点,迫不及待的马上穿着泳衣直奔大东海。由于不会游泳,打算弄个游泳圈给自己壮胆。租一个20块,买一个30块,买了一个。下水,慢慢熟悉了一下,发现有游泳圈很让人烦躁,无法控制东南西北,最后脱离游泳圈,我和她反而在海水里练习起了游泳,我游向她,她游向我,互为目的地,期间回忆大学时期蛙泳技法,如何蹬腿,如何用手分水,最好战绩前行5米。难能可贵的是大学学游泳,我又是泳镜,又是鼻夹,又是耳塞,又是泳帽,这次我浑身上下就一个泳裤,毫无下海的恐惧感,不怕鼻子,耳朵进水。在水中玩了两个多小时,累了才上岸,上岸那就是玩沙子,我变成了沙子包裹的木乃伊,嘿嘿!

晚餐过后,回旅馆看《非诚勿扰》。看这节目主要是学习乐嘉,孟非如何说话,如何思考问题,如何调节气氛。受我的影响,她也比较爱看这节目了,哈哈!


#
#第三天 (蜈支洲岛看风光)
#

早晨8点坐了“韦小宝”司机的车直奔蜈支洲岛,也不知道这司机是搞笑还是真的,说自己真姓韦,名字叫小宝,搞笑!一个金杯车做了14个人,座位贴座位,倒是利用率很高。小宝说:“老板是不会让车空一个位置去旅游的。” 也是,资本逐利,合情合理。到了目的地,上船!当时是早上9点,我们坐在了船的前排,早上浪比较大,船是上下左右摇曳,好爽啊!惊呼出来!发现周围人也在叫!不过和我感觉不一样,他们是晕船的叫,汗!上了蜈支洲岛,风景真是如画,犹如人间仙境啊~ 岛的海水真叫清澈见底,里面的鱼游得貌似也格外开心!由于这里海水能见度很高,所以很多人会在这里玩潜水,30分钟,400块左右。我可能是《Planet Earth》看多了,对潜水毫无兴趣,所以在岛上就是走走停停,欣赏海滩风光,拾捡贝壳珊瑚,体味休闲人生!从9点多一直走到了下午2点,我变成了古天乐的肤色,真不抗晒啊!

<客轮>


<蜈支洲岛一角>

<偷拍路人>


<偷拍路人>

<发呆>


回去的路上,小宝说起海南的特色菜系,说黄流老鸭很好吃,回到旅馆弄清楚了去吃黄流老鸭的路线,坐4路公交车就去胜利路的老鸭店了。上车也咨询了司机胜利路哪个站下吃黄流老鸭较方便,司机很热情,在到站的时候提醒了我们下车。找了个店开吃!!!果然是老鸭,太老了啊!有些咬不动啊,我的牙齿都被塞了,味道嘛,还是可以的,可是我的牙齿啊,衰!!!吃完回去坐4路还是那个司机,好搞笑,上车就问老鸭能咬动吗?我的神啊!我的牙齿啊!看来这是注定的啊!

#
#第四天 (COOL JHACK乐队)
#

上午去了亚龙湾,没带泳衣。就是想去看看。嗯,这里的海水果然比大东海好,人也少,主要是新开发的嘛,没带泳衣就不下水了,就在沙滩上拍照。


回到大东海,再次和海亲密接触,再次练习游泳,再次明白了鸳鸯戏水这词的含义。

晚上闲逛,去了大东海的酒吧一条街,好热闹,走了一圈,最后被百乐酒吧的菲律宾COOL JHACK乐队给深深吸引住了,点了两杯饮料,从21点听到23点,我们才回去,真是流连忘返,他们演艺的歌曲大都是英文歌曲,主唱,吉他,架子鼓配合的天衣无缝,一首歌过去就是另一首歌,毫无停顿。被调动起来情绪的我们,也去歌手附近扭动起了屁股,跟着节奏跳动了起来。

<忘情的观众>

<夫妻相?有木有?>


<帅气的鼓手>

#
#第五天 (购物回家)
#

睡到自然醒,毫无压力的一天,去超市买点海南特产,下午就回旅馆看《金婚》,晚上11点回到了深圳。这次去三亚很轻松,也没做什么准备,吃好了,玩好了,oh yeah!

<支出>

2011年3月24日星期四

[Java Script]用递归方式绘制树

topology_array数组对象中存有一棵树所包含节点父子关系,通过get_topology_html生成jquery树插件所需HTML代码,最终实现树的绘制。

var topology_array = new Array(
// "switch", "designated switch", "if-traversed"
["ANDERS", "ROOT", 0],
["CINDY", "ANDERS", 0],
["DAVID", "ANDERS", 0],
["ERIC", "ANDERS", 0],
["FRANK", "ANDERS", 0],
["BILL", "ROOT", 0],
["GATES", "BILL", 0],
["HAVORD", "BILL", 0],
["IAN", "BILL", 0],
["JACK", "BILL", 0],
["KARAN", "CINDY", 0],
["LERRY", "KARAN", 0],
["MIKE", "LERRY", 0],
[ 0, 0, 0]
);

function sub(data, node)
{
for (i = 0; i <> if(data[i][1] == node && data[i][2] != 1) {
//alert(data[i][0]);
data[i][2] = 1;
return data[i][0];
}
}
return -1;
}

function get_topology_html(data, root)
{
var ret;

while((ret = sub(data, root)) != -1) {
topology_html += "<><>";
topology_html += ret;
get_topology_html(data, ret);
topology_html += "< /li >< /ul >";
}
}