2011年12月20日 星期二

Gestures and View Transform

To use the UIGestureRecognizer for pinch and rotate gesture,
we first create it:
// Create a rotation gesture
UIRotationGestureRecognizer *rotate = [[UIRotationGestureRecognizer alloc]
initWithTarget:self
action:@selector(handleRotateEvent:)];
[rotate setDelegate:self];
[redBox addGestureRecognizer:rotate];
Then write the handleRotateEvent: method: // Called when the rotate gesture is recognized
- (void)handleRotateEvent:(UIRotationGestureRecognizer*)rotateGesture
{
// If our gesture ended, reset the box
if([rotateGesture state] == UIGestureRecognizerStateEnded) {
[self resetBox];
}
else {
// Store the value of our rotation gesture, then
// call our central update box tranform method
// Update box transform will also apply any transforms by the pinch gesture
rotation = rotateGesture.rotation;
[self updateBoxTransform];
}
}
In the updateBoxTransform, we directly use the rotation value to view’s transform: - (void)updateBoxTransform
{
// Create a new transform based on the scale (scale determined by pinch gesture)
CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);

// Rotate the transform based on the rotation gesture value
transform = CGAffineTransformRotate(transform, rotation);
//-- contineously using the gesture's rotation
// Apply the transform to our red box
redBox.transform = transform;
}
Here we initialize a transform with Identity and scale, each time.
The following paragraph uses another approach for the rotation:


   - (void)handleRotateEvent:(UIRotationGestureRecognizer *)gestureRecognizer
{
[self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
if ([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
[gestureRecognizer state] == UIGestureRecognizerStateChanged) {
[gestureRecognizer view].transform =
CGAffineTransformRotate( [ [gestureRecognizer view] transform], [gestureRecognize rotation] );
[gestureRecognizer setRotation:0]; //-- reset gesture's rotation
}
}
Since the source of transform is from the view object, we have to [gestureRecognizer setRotation:0]; such that we provide a fresh rotation quantum and add to the view’s transform

2011年11月25日 星期五

Discussions about using "Singleton" and "Archiving/Unarchiving"

This is a practical situation encountered --- We want a "Singleton" object which has the ability of "Archiving/Unarchiving", should we implement these two design patterns together? There is a discussion in Stack Overflow.
My thoughts : Maybe it is unnecessary to implement them in the same class, as "wbyoung" said, two lines of code do the same work.

2011年8月8日 星期一

deleting trailing whitespace

When using git to maintain versions of XCode4 projects,  often we need to "delete trailing whitespace" before we add or commit file to the git tree. While XCode4 leaves lots of line with trailing white spaces. How to remove them?

By Bash commands :

find -E . -type f -regex ".*\.(h|m|mm)" -print0 | xargs -0 sed -i -E "s/[[:space:]]*$//"

 

 Note:

-E for find: Interpret pattern after -regex with Extended Regular Expression(ERE) syntax,  should be placed before {directory}

".*\.(h|m|mm)" : match file name with  .h, .m, .mm at the end, which is ERE syntax.

-E for sed: Interpret pattern using ERE syntax, the [:sapce:] represents the Whitespace character set: [ \t\r\n\v\f]


Thus, we can delete trailing white space with one command line in the project top directory ! Simple and clear !

2011年7月19日 星期二

The COSCUP 2011 iPhone program

緣由: 今年 COSCUP,由於智慧型手機的普遍化,增添了 App 競賽。所以就來共襄盛舉一番。

6 月 20 日:看到 COSCUP 的公告,開始熱血沸騰...可是,我不會 Java 、剛學會 Objective-C,只會寫 Hello World;如果要選比較可能做得到的平台,好像 iPhone 比較接近一些些。所以開始研讀  Cocoa 。

7 月 9 日,可以用 COSCUP API 抓到資料,用 json framework 來 parsing,感覺很幸福!

7 月 10, 11 ... 15 日,頭髮一直掉.... 媽!我錯了!但是為了自我實現的一個目標,繼續奮戰。感謝家人,同事的默默支持,也感謝 COSCUP 工作人員的協助。

這是現在完成的三個畫面。

以時間來看

以議程的類型來看

這兩種觀看的模式,可用右上角的按鈕群來互相切換。

另外,贊助廠商的導覽,可以由畫面下方的 Sponsors tab 來選擇。

因為這是一些資料的 parsing ,目的是使大家很快的找到需要的資訊,所以以極簡風格來完成使命。

第一次執行時,會從 COSCUP 網站下載資訊,之後就存在手機裡了,之後就從手機讀檔,需要 update 的話,左上角按鈕可以再從網站下載。

另外,有提供智慧型的語系選擇,例如,如果從 COSCUP 拿到了 Intel 廠商給的資訊,只有中文,那麼不論手機的語系設定如何,都會看到中文;那如果贊助廠商給的資訊有中、英文,那就會優先以手機的語系設定來顯示出贊助廠商的資訊。

 

程式碼放在 GitHub

git clone: git@github.com:tomjpsun/Coscup.git

就這樣啦!期待大家在8/20 見面啦!

 

2011年4月27日 星期三

2011年4月12日 星期二

greedy straegy abstract

為了解一個問題,把 [ Introduction to Algorithms ] 抓來亂翻了一下,
再配合交大 [ 譚老師的講義 ],把 greedy algorithm 部份研讀了一下,
大概領悟力不夠,還是不能融會貫通,只好把重點節錄起來,慢慢消化:

以下 Greedy Algorithm 以 Greedy 簡稱之
         Dynamic Algorithm 以 Dynamic 簡稱之
         Optimal Solution 以 Opt. 簡稱之

Greedy  簡單說就是:經由一連串的選擇,找出全局最佳解,每次
選擇時,是找出當時的最佳解,這種 heuristic 的方法,就稱為 Greedy.

Greedy 異於 Dynamic 的解法,不像 Dynamic 找出所有 subproblems 的解,再慢慢
用 table 記下,累積到全局:而是先把問題分成一個 greedy choice + subproblem ,
這個 greedy choice 是一個局部最佳解,並且用 recursive 方式繼續 下去解 subproblem。
最後的結果,使得 Greedy 不一定得到 Opt.,但是很快,而且結果可以接近 Opt.

很多時候,由於這種早期決定的性質,Greedy 無法找到 Opt.
當然,如果能證明,這個 greedy choice 是全局 Opt. 的一環,那麼就可以確保,一系列
的 greedy choice 可以找到全局 Opt.

下面是從 [Wiki] 節錄的,Greedy 的兩個重要成份:

Greedy choice property
    We can make whatever choice seems best at the moment and then solve
the subproblems that arise later. The choice made by a greedy algorithm
may
depend on choices made so far but not on future choices or all the
solutions to the subproblem.
It iteratively makes one greedy choice
after another, reducing each given problem into a smaller one.

In other words, a greedy algorithm never reconsiders its choices.
This is the main difference from dynamic programming, which is exhaustive
and is guaranteed to find the solution.
After every stage, dynamic programming makes decisions based on all
the decisions made in the previous stage
, and may reconsider the
previous stage's algorithmic path to solution.

Optimal substructure
    "A problem exhibits optimal substructure if an optimal solution
 to the problem contains optimal solutions to the sub-problems."

以下列出一些例子來討論:
例一   0-1 knapsack problem : 假設有 n 種礦石,以 1,2...n 代表這 n 種礦石,
第 i 種重量是 w[i] ,價值是 v[i],限定載重上限為 W 的情形下,
怎樣拿會最有價值?

例二   fractional knapsack problem : 假設有 n 種礦石粉末,以 1,2...n 代表這 n 種礦石,
第 i 種重量是 w[i] ,價值是 v[i],限定載重上限為 W 的情形下,
怎樣拿會最有價值?

這兩種問題,都有 Optimal substructure 的特性 ----- 假設最有價值的裝法 載重是 W,
則裝入礦石 j 後,對於剩下的 n-1 種礦石 ( 就是 j 已拿光後 ) 最有價值的載重
剩下 W-W[j]

fractional knapsack problem 可以用 Greedy 找到 Opt. :
因為當每次選擇 價值/重量 比最高的礦石粉 j 時,可以確定把 j 拿完,
是最好地選擇。若 j 拿完還有多餘的載重量,就選擇 價值/重量 比
次高的礦石粉,此時 所作的 greedy selection 就是符合 global Opt. 的選擇。

0-1 knapsack problem 無法用 Greedy 找到 Opt. :
反例 :考慮三種礦石,都只有一個:
 v[1]=60 ,  w[1]=10
 v[2]=100, w[2]=20
 v[3]=120, w[3]=30
 upper weight W= 50

1 的 價值/重量 比最高,選取 1 剩下可載重 40,但是選 1 不會得到 Opt.
Opt. 是選 2+3, total value =220
但是 0-1 knapsack problem 可以用 Dynamic 找到 Opt.
 
另外,有漂亮的數學證明, 符合 matroid 結構的問題,可以用 greedy 得到 Opt.
( matroid 是比較深的主題,有空再來研究吧!)
#

2011年3月28日 星期一

simple & clean daemon code

This blog is original from here: [ uCdot ]

Here the little trick is :
Use option '-D' as a 'differentiate mark' of daemon process
from the parent process. 
  
The second time it self exec(), means the daemon process
starting with -D option, which make it goes to the 'else' block :

It's a Clean and Simple example!
#

2011年3月12日 星期六

uClinux 新手筆記

如果想要知道一些概念,這篇是很好的總整理:
[ uClinux for Linux Programmers ]

大致上的摘要是這樣:
  uClinux 給沒有 MMU 的 CPU 使用,因此不支援原來
  Linux 的 Virtual Memory (VM) 環境。

  沒有 VM,process 不能於 run time 時期增加 process
  address space,所以 brk/sbrk() 無法被實做,
  也不能用 tmpfs,因為它依賴於 VM 的支援。

  沒有 VM,每一支 uClinux app 都要在 run time 時由系統來作 relocation。
  而且是 sequential && contiguous. 的排在 file system 內,一次就得載入
  整個程式 於連續的 physical memory 上,所以只能用 romfs。

  傳統的 power of 2 memory allocation 機制在這裡會造成許多浪費
 (例如要 33k 會給 64k),所以可選其他的 memory allocation 機制
  ,例如 page_alloc2 或 kmalloc2。
  page_alloc2 以 4k 為單位分配 (例如要 33k 會給 36k)
  kmalloc2 以 8k 為判斷,大於 8k 的需求從 free memory 的底部拿,
  小於 8k 的從 free memory 的起始處拿。這樣的好處是減少由
  短暫而多次的 allocation --- 如網路程式的 buffer --- 引起的碎片問題。

  沒有 VM,對應用程式來說,就沒有 dynamic stack 可用,一旦程式超出
  stack 範圍,會引發不可預期的結果。程式要自己知道需要多大的 stack,
  在 compile time 就必須決定好。
  heap 也不能使用 VM 機制,所以 uClinux 使用了 kernel free memory
  當作一個大的 system memory pool.
 
  對於應用程式與程序來說,uClinux 沒有提供 fork();只提供替代的 vfork(),
  有別於 fork(),使用 vfork() 會使得 parent process suspend 直到
  child process  結束 或 執行 exec() 為止

  fork() 發生後,parent & child process 有各自的資源 (address space 與 stack),
  parent & child process 沒有任何共用的東西。
  反觀 vfork() ,它會使得 child process 與 parent process 共用 stack。
  因此 vfork() 後,parent process suspend 了,若此時 child process 從現在的
  stack frame 返回上層,則會影響到 parent  process stack ---
  應用程式必須自行注意,確保不會發生這種情形!(心得:難怪
  網路上有人建議 busybox API 加上 fork_and_exit())!
  另外,child process 也必須使用 _exit() 而不能用 exit() ,
  原因也是因為 stack 共用。

  沒有 VM,uClinux 的程式只能使用 flat executable format (bFLT),
  這有兩種型態:
  一、code text & data 都是 relocatable
  二、Compile 出 PIC 碼 (Position Independent Code)
         只有部份 data 需要 relocation 即可。
  其中第二項衍生出 XIP (eXecute In Place) ,就是程式可以直接在 ROM
  上面執行的方式,因為 ROM 是 read only,可以被多個 instance share 使用。

  因為 romfs 上面的程式是 contiguously 排放的,這使得 romfs 是唯一可支援
  XIP 的 file system。
  從這裡可推出這樣的關係:做出 XIP 系統 需要 compiler 支援 PIC 碼。目前
  只有 m68k & ARM 有這樣的 gcc compiler.

  編出 bFLT 的程式,其實就是先編出 ELF 格式,再由 linker 轉換。只要
  compile 選項使用 -Wl,-elf2flt 即可作到。另外例如 -Wl,-elf2flt=s16384 這樣
  可以指定 stack 為 16k,toolchain default stack is 4k。(心得:有時
  default 是不夠的)

  再來談到 shared library,僅僅想用gcc -shared 選項,無法幫你在 bFLT
  格式中製作  shared library。(心得:下面有 Analog Device 網站上
  的好文詳細描述如何製作 shared library for uClinux)
  這裡只提一個重要概念,shared  library 必須是 XIP ,否則在每個
  uClinux application 都會產生一份 copy --- 這種情形比 static linking
  還要糟糕!

  結論:伴隨著 NOMMU,uClinux 衍生出這些 與 Linux 的不同處
             uClinux 應用程式開發者,需要自行注意。
摘要(完)

[ 認識 bFLT ],當然增加概念,但是對於開發程式,沒有直接幫助。

另外,下面這幾篇好文,並沒有排在 google 的前面,但是對於在 uClinux
下開發程式, 極有幫助,特此紀錄之。
1.  Executable file formats
2.  elf2flt 的說明
3.  用 flthdr (flat header)工具來看 bFLT 檔案
4.  Creating Libries

一些 uClinux mailing list 的摘要:
[ Problems building for uClinux ]: Jamie Lokier 有教讀者一些 narrow down problem 的方法,很實用!
還有遇到 error: no memory region specified for loadable section `.plt` 的現象,是因為 linker 遇到 .plt .got ,使其無法 link 成 BFLT program--- 這個 error 在 porting  program for uClinux 時很常遇到.

1. BFLT program 的製作 ,其實就是 compile 出 elf 後,再用 elf2flt  轉換成 BFLT format program,一般都用 CFLAGS += -elf2flt 告訴 compiler 在 link time 時幫我們轉換。

2. 若您的程式有自己的 lib ,而且是 static link 的方式,則 lib 先只是作成 elf ,然後 archive 起來 ,用 ranlib 做出 library index (方便 linking ,可有可無),等到和 program linking 時才使用 elf2flt  轉換成 BFLT.

#



2011年3月11日 星期五

linux serial port programming : CLOCAL 的設定

先來看 Carrier Detect (CD) signal line 的意義。
節錄自 "Serial Communication / Mark Nelson" 一書 :
"Unfortunatly, before the era of intelligent modems, some terminals
or other DTE equipment were designed to treat a modem as unusable
without CD. Devices such as these would not send or receive
characters to a modem that had CD low. Because of these anachronisms,
most modems built today can keep CD high at all times, whether or not
a carrier has been established.

Because these feature is sometimes the default mode of operation,
using CD for accurate detection of carrier presence is somewhat risky.
However, most users should be able to configure their modems so as to
disable this troublesome behavior
."

中文口白一下:以前時代,CD 是 modem (DCE 端) 用來告訴 終端機 (DTE 端) 說:
我有連到對方喔!但是後續的 modem (DCE) 有的已經不照這種約定了---
不管有沒有跟遠端連線,一律拉 CD 起來。
所以 DTE 根據 CD 判斷 DCE 有無與對方連線的方式,已經不可靠了。
所以現在 DTE 必須可以 configure設定,不要再看這個不可靠的 CD signal.

怎樣 configure ? Linux serial driver 提供這樣的 flag --- termios 屬性若有設定
CLOCAL ,在 2.6.28 generic_serial.c ::
uart_change_speed():
{    ...
    if (termios->c_cflag & CLOCAL)
        state->info->flags &= ~UIF_CHECK_CD;
    ...
}

那 UIF_CHECK_CD 有何作用呢?

uart_handle_dcd_change(struct uart_port *port, unsigned int status)
{  ...
    if (info->flags & UIF_CHECK_CD) {
        if (status)
            wake_up_interruptible(&info->port.open_wait);
        else if (info->port.tty)
            tty_hangup(info->port.tty);
    }
    ...
}

也就是說,有 UIF_CHECK_CD 時,就 wake up 正在等待 open 的 process,
或是 hangup tty,這些都是在 CD signal change 時本來預定的動作。
 
所以在這裡,設定 CLOCAL 可以 "遮蔽" 對於 CD 訊號的判斷。
若您的應用程式 open serial port 時,忘記設定 CLOCAL,
就會照者書上所說的操作定義 --- 因為 DTE 發現 DCE 的 CD 不見了,
就 hang up tty 了。
#




2011年1月24日 星期一

Difference between .bash_profile and .bashrc Files

以下內容是從這裏節錄出來的:

.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.

就是說,當你使用 login console 或用 ssh login 時, .bash_profile 會被調用。
如果只是在 GNOME, KDE 或 emacs 裏面,打開一個 shell command 時, .bashrc 會被調用。

那麼作 global 設定時,就是這兩種情形分別對應到 /etc/profile /etc/bash.bashrc 啦!
其中,若是需要在 login 時,也希望 bashrc 被調用,就可以在 profile 裏面 source bashrc.

2011年1月23日 星期日

git 更改遠端資訊 的指令

為了轉移到新的伺服器,git 的 repository 要搬到新位置,所以 local 端的 repository 指標要換掉,下列指令依序就是轉換的步驟:

#> git remote -v
顯示目前指向哪些遠端的 repository? (URL 格式)

#> git remote rm origin
移除 URL 資訊

#> git remote add origin git@git-server:project_name
改變 URL 資訊,指向新位置 (若是用 gitosis ,就可以直接建立新的遠端 repository ,否則遠端的新增的 repository 必須先用 git init 或 git init --bare 處理過)
(目前為止,都還沒有對 remote repository 產生任何影響)

#> git push origin master
把 local repository 更新到 remote 端(這裡,才實際的更新了 remote repository)

Install sun-java5-* in debian squeeze

Debian Squeeze 已經把 sun-java5-* (亦即 java 1.5 )拿掉了,統統換成了 sun-java6-* (亦即 java 1.6)「註:這裡 * 代表 jre, bin, jdk, demo 等等部份」。
可是 Android 開發環境會檢查 java 環境,仍然需要 java 1.5 ,怎麼辦呢?
可以用 dpkg --force-depends 強制安裝 sun-java5-*  ,方法如下:

1. 首先下載 Lenny 版本的 package :
sun-java5-bin_1.5.0-22-0lenny1_i386.deb
sun-java5-jre_1.5.0-22-0lenny1_all.deb
sun-java5-demo_1.5.0-22-0lenny1_i386.deb
sun-java5-jdk_1.5.0-22-0lenny1_i386.deb

2  因為 bin 依賴於 jre , jre 依賴於 bin, jdk 依賴於 demo, demo 依賴於 jdk 。
所以用強制 depends 選項(把依賴關係列為 warning 而非 error )就可以順利安裝,指令為:
#> dpkg --force-depends -i  sun-java5-bin_1.5.0-22-0lenny1_i386.deb\
  sun-java5-jre_1.5.0-22-0lenny1_all.deb\
  sun-java5-demo_1.5.0-22-0lenny1_i386.deb\
  sun-java5-jdk_1.5.0-22-0lenny1_i386.deb

3. 切換內定 java version :
#> sudo update-java-alternatives -s java-1.5.0-sun
如果出現一堆跟 firefox plugin 的錯誤訊息,像這樣:
update-alternatives: error: alternative /usr/lib/jvm/java-1.5.0-sun/jre/plugin/i386/ns7/libjavaplugin_oji.so for firefox-javaplugin.so not registered, not setting.
...
不用管它,因為我們 compile Android 時應該不會用到 firefox 的 java plugin。

4. 驗證 java version :
#> javac -version
應該就可以看到 java 1.5 的訊息了!
#