6.27.2007

Win32 的同步物件 - 一些

Citical Section

Critical Section 可以重複進入 ( 正確的說,是對已經進入Critical Section 的Thread而言..),但是進入的次數和退出的次數必須要一樣,才可以正確離開critical section。


和Critcal Sectin 類似的mutex 元件,使用上要比Critical Section 花比較多的時間(約100倍)。因為critical section 可以在user space中完成,mutex卻一定要進入kernel space。

所以 Critical Section 只能用在同一個process中,各thread之間的同步。無法做到 process間的同步。

mutex就可以用在 process間。

... 所以 criticalsection 沒有 "name",mutex可以有name (在create時指定)。

Semaphore

Semaphore 是counting semaphore,在 CreateSemaphore( )時就要指定 maximum counting number。


Event

Event 有AutoReset和ManualReset 兩種 (CreateEvent( )時指定)。ResetEvent( )把Event 設定為un-triggered。 SetEvent( )和 PulseEvent( )都可以把Event設定為Trigger。
PulseEvent( )是特殊的:
  • Event是AutoReset : PulseEvent( )只會Wakeup 一個Waiting Event的Thread。然後恢復un-trigger。
  • Event是ManualReset : PulseEvent( )會Wakeup 所有Waiting Event的Thread,然後恢復un-trigger。

HANDLE WINAPI CreateEvent(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in_opt LPCTSTR lpName
);


InterlockedXXX


這是用在multi-tasking 系統中常用的 if(xx > 0) xx--; 的問題,避免在if( )後被task switch 掉,導致 回來執行時,xx已經改變。所以提供一個atomic lock++, lock-- 的function。
如其名所示,InterlockXX 只能作相對於0的判斷。
  • int InterlockedIncrement( *count ) : 將count++,如果 > 0,return 1,等於0 return 0,小於0 return 負值
  • int InterlockedDecrement( *count) : 將count--....
還有另一個類似的funciton ,是作 .. oldvar = var; var=newvalue 時,位了避免在中間被task switch 掉。
  • int InterlockedExchange( *var, newvalue) : return oldvar回來。

其他,就是上次提到的... Thread 本身也是一個同步物件。

UpdateData in Thread

在Thread 中call UpdateData( )會導致Crash。
據說,Win32 programming 有一條Rule(http://forums.ni.com/ni/board/message?board.id=231&message.id=4331):
"Thou shall not access UI controls from a thread other than the one that created the UI control in the first place"
因為Dialog 不是Thread Safe。
所以,可以用UpdateData( )這個funciton 的,也只有Dialog 自己這個thread 囉。

那Dialog create 出來的Thread 要怎麼update dialog 的data呢?

一般的解法是用Message,Thread Post Message,叫Dialog UpdateData。
例如在 這一篇 (http://forums.microsoft.com/msdn/showpost.aspx?postid=95099&siteid=1)所列出的code :
#define WM_USER_UPDATE_DATA      ( WM_USER + 1 )

void UpdateUserData( BOOL bUpdate )
{
SendMessage( WM_USER_UPDATE_DATA, bUpdate, 0 );
}

LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if( message == WM_USER_UPDATE_DATA ) {
if( wParam )
UpdateData( TRUE );
else
UpdateData( FALSE );
}
}
然後其他的Thread 都呼叫UpdateUserData( )來代替 UpdateData( )。

看起來似乎OK,但是在CE這種,OEM到處定義WM_USER+XX 的系統,要找到一個safe 的 message number 還真不容易呀,稍不小心就會誤觸地雷。

Robert 說WM_USER+XX 的scope只在同一個AP。所以不用擔心會有和其他AP重複定義的問題。

另外Robert說在Thread中和Dialog要互通資料,一般會用Timer Trigger,比較安全,然後其中用queue來傳遞資料。

  • 所以如果說是經常update的資料,就用Timer。
  • 如果是偶而才 update一次,就用 WM_USER+XX。
總整理:
  • 在Dialog 本身的Thread中,用UpdateData
  • 在其他的Thread中,用PostMessage( )通知Dialog作UpdateData( )。
所以Dialog Create 的Thread在使用Dialog 本身的funciton 時,要注意那個Function 有沒有呼叫UpdateData( ),否則會發生其他人使用沒事,但是Thread用有事的情況。

不然就要一勞永逸,大家都用PostMessage,由Dialog的WinProc 統一UpdateData( )。


關於Thread中呼叫UpdateData( )來Update UI 內容,這一篇(http://blog.csdn.net/jeven2005/archive/2007/02/14/1510039.aspx)也有詳細的說明:解法也是使用USER MESSAGE。

關於這一點還真有名呀,另外類似的rule有:
這一篇(http://www.codeproject.com/cpp/
avoidupdatedata.asp?df=100&forumid=696&exp=0&select=845137
)的
DO NOT EVER TOUCH A WINDOW FROM A THREAD.

FON 天線 NT 149 - part II

歷經一番波折後..



很大一個呀..



接頭是



方向特性..



這麼大隻,要裝在哪呀......

6.26.2007

eVC+VSS : ClassView will not be available

當eVC 配合VSS 使用時,如果是先用eVC將project create好,再把整個project 拉進VSS。然後再開啟時,由於VSS會把所有的 file 都改為read-only,導致eVC開啟會出現:
Cannot access the ClassView information file. ClassView information will not be available
這時候,只要把所有的file 都改成 read/write 就可以正常開啟了。

eVC很奇怪,如果你不管,繼續開啟,還是可以正常build project,但是在run debug program時,會出現error 無法launch program。

6.25.2007

SendMessage Hang.

遇到一個糟糕的問題:

UI 的 message handler 中 正在wait 一個 low priority thread的 semaphore。
這個low priority thread 此時 SendMessage( )給 UI。

導致 low priority thread hang 著 -- 應該說是UI和thread都Hang著。
直到 UI Handler 的wait timeout後,處理完low priority thread 的SendMessage( )後。
那個low priority thread 才有機會執行。


理論上..low priority thread 的SendMessage動作,只是將messasge放進 UI 的message queue中。
即使UI的priority 比較高,但是他的state 是Waiting,所以控制權應該要立刻交回low priority thread 才對呀。

OS做到這樣有點糟糕喔..有點 priority inversion 沒做好的感覺 (其實還沒到這裡)。

同樣的一句....還是我又在耍白痴?

的確,又是我在耍白痴。

感謝 Kun-Yi 的告知(ref comment),原來 SendMessage( )就是會block and wait return。
放到message queue的是PostMessasge( )。

依照Kun-Yi 所說的修改後,block 現象就消失了。

6.23.2007

Thread Alive ?

CE中用CreateThread( ) 來Create Thread。
但是沒有query Thread State 的API (還是我沒找到?)。
所以連Thread 是活著還是死了也不知道。

GetExitCodeThread( )可以取得Thread 的ExitCode,如果Thread 還活者,ExitCode就是 "STILL_ACTIVE"。

Thread 自己可以用ExitThread(exitcode) 來設定自己的exit code。

所以要小心了,不要用 ExitThread( )來設定自己的 exit code 是 "STILL_ACTIVE",否則 用GetExitCodeThread( )來判斷的code就會判斷錯了。

那 "STILL_ACTIVE" 是多少呢? 在CE 5.0 下,是 : 0x103
果然是我耍白痴。
經過Robert的指點,Thread 本身就是一個Synchronize object,所以可以用WaitForSingleObject( ) 來取得Thread Active 狀態。或是Wait for Thread Complete。
以上兩種就是由TIMEOUT 參數決定。

VIEWBIN - information of NK.BIN

CE 最後的image是 NK.BIN。
因為build的動作不明顯,所以常常要確認自己的修改有沒有進入到image中。
但是 NK.BIN 這樣的image又不像linux 一樣,可以解開或是mount 進來看。
(所以更不要說是修改了)

單純要看的話,可以用 VIEWBIN 這個command line tool
MSDN Viewbin Tool
簡單的說,就是
viewbin -top NK.BIN
就可以列出所有的file..

6.22.2007

remote debug, dll

使用ActiveSynch 作eVC的remote debug,當有使用到其他dll 時。啟動時常常會出現 Unknown Error, error code : 126。

這時候,要開啟所有用到的DLL project (所以如果沒有source project就完蛋了)。然後一一用"update remote output file" 將DLL copy 到 remote target上。
然後再run 要debug 的 project,才會成功。

其中還要注意 Project Setting 中,debug - general - Download directory 所設定的位置。
最好是和將來實際要run 的位置。

upload 後,會出現prompt,詢問dll 所在local 的位置(大概是要load symbol吧),就指定到對應的位置 (只有一次機會,指錯了,下次就不會再問了)。

6.21.2007

phonebook entry

phonebook 長得大概是這樣..
26CDB4E9E62D63A596FB88D004D,0030003900380032003400330031003300330035
就是以' , ' 區分,前段是name,後段是 number。

但是內容不是很檢單的ASCII code,要猜一下(尤其是name的地方)。
第一個byte 好像是 encoding code (?)
  • '2' : UCS2
  • '3' : UTF-8
  • '1' : default ?
phonebook 的內容就是"code 的ascii code"
拿一個比較簡單的例子..
20066006F006F,0030003900330031003200330034003500360037
第一個code是 encode type,不處理。
解開來就是..
0x00,0x66  : 'f'
0x00,0x6F, : 'o'
0x00,0x6F, : 'o'

0x00,0x30, : '0'
0x00,0x39, : '9'
0x00,0x33, : '3'
0x00,0x30, : '0'
0x00,0x31, : '1'
0x00,0x32, : '2'
0x00,0x33, : '3'
0x00,0x34, : '4'
0x00,0x35, : '5'
0x00,0x36, : '6'
就是 : foo 0930123456

6.18.2007

Printed Exception String - 內容的意義

這一篇 : Printed Exception String - What do all these flags means ? 有詳細說明每次Exception 列出的這一些 flag 的意義。

Data Abort: Thread=9352cc9c Proc=90876ea0 'shell32.exe'

AKY=00000005 PC=03f74680(coredll.dll+0x00014680) RA=03257104(aygshell.dll+0x00037104)
BVA=060000e0 FSR=00000007
為例:

AKY 是 "Access Key" 這個 value是bitmask,上例 AKY=00000005 ,代表access 這個region 的thread 有 00000001 和 00000004。
配合下面這個table (build map ?)
Name                 VMBase        AccessKey     TrustLevel    hProcess  
btstereoappui.exe 0x1A000000 0x00001000 Full 0xB30E2766
connmgr.exe 0x16000000 0x00000400 Full 0x5311091E
cprog.exe 0x1C000000 0x00002000 Full 0xF3030772
device.exe 0x0A000000 0x00000010 Full 0xB3CEC78E
filesys.exe 0x04000000 0x00000002 Full 0x13EEE762
gwes.exe 0x0C000000 0x00000020 Full 0x737A498A
nk.exe 0xC2000000 0x00000001 Full 0x13EFF002
pmsnserver.exe 0x10000000 0x00000080 Full 0x5333CD86
poutlook.exe 0x14000000 0x00000200 Full 0xD308FA02
sddaemon.exe 0x12000000 0x00000100 Full 0x7314C62A
services.exe 0x0E000000 0x00000040 Full 0x7352CFAA
shell.exe 0x08000000 0x00000008 Full 0xD3CD7A82
shell32.exe 0x06000000 0x00000004 Full 0xD352CEDE
srvtrust.exe 0x18000000 0x00000800 Full 0x33105BCA
就是 nk.exe 和 shell32.exe

PC 就是 Program Counter

如果找得報,他會print出該位址的module和 offset coredll.dll+0x00014680
所以去找 coredll的map file,可以找到..
 0001:00013638       GetWindowLongW             10014638 f   coredll_ALL:twinuser.obj
0001:00013648 BeginPaint 10014648 f coredll_ALL:twinuser.obj
0001:000136cc EndPaint 100146cc f coredll_ALL:twinuser.obj
0001:00013750 GetDC 10014750 f coredll_ALL:twinuser.obj
0001:000137d4 ReleaseDC 100147d4 f coredll_ALL:twinuser.obj
0001:00013858 GetParent 10014858 f coredll_ALL:twinuser.obj
知道是 BeginPaint 這裡有問題。

RA 是 Return Address


所以,知道這一篇重要了吧,其他的部份到原文去看看...

build image in the background

這是在 HoppeRx這個blog看到的:How to get work done while building the tree
用過platform builder 的人都知道,不管你的 pc 多厲害,在build image時,整個系統都會進入慢動作狀態,這是因為build動作佔用了大量的disk, cpu IO。
MS的工程師也預知了這樣的狀況,所以預留的退路 -- 但是寫在很隱晦不明的地方,就是在下blddemo這個命令時,加上 "-m " option ,這樣就會讓 build process run 在 "idle" priority。

所以,就可以防止整個系統反應慢了下來,但是... 可能要花 5 min 才能build 好image。
在該文章 comment 處有列出出處: Build Tool
http://msdn2.microsoft.com/en-us/library/aa448614.aspx

6.16.2007

狼與香辛料

.........惡魔出現在一位有錢的商人面前,說道:把這裡最好吃的人帶來,不然,我就要吃了你!
商人害怕之下,就獻出了年輕貌美的女僕和一個肥胖的手下。
惡魔看了,卻搖頭表示不滿。
商人找遍城中所有地方,終於找到一個會散發出乳香與蜂蜜香味的瘦弱見習修士。
商人買下整個修道院,把這個小修士送給惡魔。
小修士站在惡魔前面,對惡魔說道:惡魔呀,這個世界上最好吃的人類不是我,而是那個靠著買賣香辛料致富,全身都被香辛料調味得洽到好處的商人呀!
這一段話和這本書沒什麼關係 --- 但是,書還是蠻好看的,不必用什麼腦筋,大概 3 hours 就看完了。
這種小說讀起來就像看電影一樣,娛樂性蠻高的,不必動什麼腦筋。

小紅點鍵盤

最近的熱門消息:在PChome買的1299 小紅點鍵盤
IMGP2511

挺不錯的喔。 :)

可惜... 太大了點...
IMGP2512

6.15.2007

FON 天線 NT 149

收到FON的信:

大意是說我可以用149買原價800的Fon 增強天線。
所以 ? OK 啦。
就按下link去買囉。

可是呀,這個seednet的購買畫面真是...
  • 首先是 地址....巷,弄,號都要用數字,不可以用國字 一二三...否則他會說你地址寫錯喔。 (還是他真的知道你不住在那?)
  • 再來是按下確認後,竟然?出現html code ?怎麼辦? copy 起來,另存成 html ,再用browser打開..就可以繼續下去...
OK,就這樣。通過這兩關考驗後。就可以跟大魔王..嗯。不是,是印出條碼囉。

然後就是去便利店繳款...接著就可以知道是不是詐騙信囉。

Resource 與 vairiable 產生關聯


用Resource Editor 增加了Control 項,只有指定 ID_XXX。並沒有在 source code中宣告control 的實體變數。
但是,已經可以run 了喔。

如果要讓resource 上的control 在source code中有一個可以"操作"的實體。
就要用 Class Wizard 為 control 加上 variable。
如上圖,選 member variable 這個tab。
然後在 Control ID中選定你要產生的control 的ID。
接著按下右邊的"Add variable"。
就會出現這這個dialog ,要你輸入 variable name。
輸入完後。就會在 class source code (header & source )中,加入variable 的宣告 (default 是public,可以自己搬到private 區)。
並且在 DoDataExchange( )這個function 中加上讓resource 與 variable 產生關聯的code:
DDX_CONTROL(pDX, IDC_SPIN,m_spin)
這樣。variable就和resource ID "同步"啦。

嗯? 刪除 ? MS的Class Wizard 中什麼時候有出現過這種東西 ?

6.14.2007

RegOpenKeyEx

MS 所有東西的"核心"(也可以說是混亂個根源) : Registry.
要開啟 Registry ,要用 RegOpenKey ( )。
但是 Registry 的內容有可能有字串,所以有機會會有 Unicode,因此..
  • UniCode : RegOpenKeyExW
  • ANSI : RegOpenKeyA
return 成功的是 ERROR_SUCCESS。
其他的就..

另外,同一個 Key 只能open 65534 次,所以Open 用完後要記得關..
否則會return error。

另外一個 : RegCreateKey( ),和 OpenKey 類似,但是就和名稱"Create"所代表的意思一樣:如果Key不存在,就Create一個,如果已經存在,就Open他。

Coding Style - again..

說到Coding Style,不得不再提到這個實際動手寫code的人定的Coding Stype :
Chapter 3: Naming

C is a Spartan language, and so should your naming be. Unlike Modula-2 and Pascal programmers, C programmers do not use cute names like ThisVariableIsATemporaryCounter. A C programmer would call that variable tmp, which is much easier to write, and not the least more difficult to understand.

HOWEVER, while mixed-case names are frowned upon, descriptive names for global variables are a must. To call a global function foo is a shooting offense.

GLOBAL variables (to be used only if you really need them) need to have descriptive names, as do global functions. If you have a function that counts the number of active users, you should call that count_active_users() or similar, you should not call it cntusr().

Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged -- the compiler knows the types anyway and can check those, and it only confuses the programmer. No wonder MicroSoft makes buggy programs.

LOCAL variable names should be short, and to the point. If you have some random integer loop counter, it should probably be called i. Calling it loop_counter is non-productive, if there is no chance of it being mis-understood. Similarly, tmp can be just about any type of variable that is used to hold a temporary value.

If you are afraid to mix up your local variable names, you have another problem, which is called the function-growth-hormone-imbalance syndrome. See next chapter.

Chapter 4: Functions

Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, as we all know), and do one thing and do that well.

The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case- statement, where you have to do lots of small things for a lot of different cases, it's OK to have a longer function.

However, if you have a complex function, and you suspect that a less- than-gifted first-year high-school student might not even understand what the function is all about, you should adhere to the maximum limits all the more closely. Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it's performance-critical, and it will probably do a better job of it that you would have done).

Another measure of the function is the number of local variables. They shouldn't exceed 5-10, or you're doing something wrong. Re-think the function, and split it into smaller pieces. A human brain can generally easily keep track of about 7 different things, anything more and it gets confused. You know you're brilliant, but maybe you'd like to understand what you did 2 weeks from now.

Chapter 5: Commenting

Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to write the code so that the working is obvious, and it's a waste of time to explain badly written code.

Generally, you want your comments to tell WHAT your code does, not HOW. Also, try to avoid putting comments inside a function body: if the function is so complex that you need to separately comment parts of it, you should probably go back to chapter 4 for a while. You can make small comments to note or warn about something particularly clever (or ugly), but try to avoid excess. Instead, put the comments at the head of the function, telling people what it does, and possibly WHY it does it.
這樣的說法和一般公司定的coding style大不相同,我想是因為..一般公司定Coding Stype的人,大概都已經不寫code了,不然就是以為sales, hardware engineer和助理小姐,也會有機會要讀Code,所以要....Coding Style要定得讓他們也看得懂..

喔? 也有人說..是為了讓人不用實際去讀code,也可以知道使用的方法 ?
嗯.. 這樣的人,至少也知道C 的語法吧....

這個Coding Stype要求progrmmer Coding 時真正的思考寫出的Code,讓coding 變得像文章寫作一樣,要求流暢,易讀--嗯...是對同樣在Coding的人來說,是易讀的。
至於 匈牙利是命名法... 這一篇 Naming Notation - 1. the Hungarian Notation (中文的),有很好的說明喔。
可以去看看.. 但是是他說的,不是我說的喔 :)

導航也有P2P功能

N Y Times 的文章 :
Updating Maps on the Spot and Sharing the Fixes

TomTom 將在下個月發表 TomTom 720。

內含新的PC 端 software,配合新設計的PND 功能,讓user 在導航中能夠隨時加入路況資訊。
回家與PC同步後,這些路況資訊就會經由 TomTom設計的P2P網路,與其他TomTom User分享。

所以,有TomTom 720 的user,在出門前可以先和PC連接一下,取得該P2P資料庫的資訊(近乎是即時路況)接著再上路。

為了防止人"惡搞" (嗯 :p我已經想到要把我上下班路線標示"修路"的idea,,,)。TomTom會有人review 這些資訊,讓User可以選擇update TomTom verified data or All data.

除去"惡搞"那點不算,要是加上3G隨時上網,那還真的就是"即時資訊"了。

6.11.2007

nFore

安富科技

02 - 8768 - 3983

Chief Software Mananger : K.C
ext : 620

Event Communication on Comm Port : CE

由於ReadFile( )有很奇怪的特性,在Timeout的waiting period中,會block整個process (不是thread喔)。所以會導致整個AP沒反應。
所以在Read 的動作要使用event driven。
ref MSDN : Using Communication Event

// Specify a set of events to be monitored for the port.
SetCommMask (hPort, EV_RXCHAR);

while (1)
{
DWORD EvtMask;

WaitCommEvent (hPort, &EvtMask, 0);
SetCommMask (hPort, EV_RXCHAR);

while(1)
{
BYTE Byte;
DWORD BytesReaded;

ReadFile (hPort, &Byte, 1, &BytesReaded, 0);

if (BytesReaded == 1)
ProcessChar (Byte);
else
break;

}
}
也就是用 WaitCommEvent() C和 SetCommEventMask( )。
其中要注意的是每次WaitCommEvent( )前要重新設一次EventMask( )。

雖然不錯,但是還是有點缺陷呀...

可以Set的Event只有RX, TX, CTS, ..RING..etc。沒有timeout。
所以沒有辦法做到..."如果10sec內都沒有char送到,就return"的動作。

真可惜,在實際通訊時,這種功能是很實用的,可以用來取代一個 housekeeping thread,常常來monitor 通訊對方是不是還活著..

6.10.2007

DLL in CE : application's view

像絲絲一樣,DLL 也有兩種:
  1. 就像是一般library 一樣,啟動時就自動load進memory了。
  2. 像Driver一樣,被動的由AP load進入memory。
使用 1 的話,比較方便,因為是一般library,所以可以export 出class 。
使用 2的話,interface就受限制了,要是一般的cedel type c function,不能export class出來。


1 的dll 中:

要export 出來的class 要加上 DLLMACRO 的宣告:
class DLLMACRO CDummy
{
public:
....
其中 DLLMACRO 的定義是:
#ifdef _AFXDLL
#define DLLMARCO __declspec(dllexport)
#else
#define DLLMARCO __declspec(dllimport)
#endif
要用 AFXDLL 來區分的原因是..
這個header file會被 DLL 和 APP include,當是 DLL 參照時,DLLMACRO 要定義成 dllimport。
當被APP參照時,DLLMACRO要定義成 dllexport。

這個方法,build出來的DLL會產生兩個 file : *.dll, *.lib
  • *.dll : 是要放在 target image中。os啟動時會load起來。
  • *.lib : 是給 app link用。
所以 application 的project setting 中要把 這個 dll build出來的 *.lib 加到 link 的 addition library 中。

6.09.2007

MultiByteToWideChar - convert char* to WCHAR

以往C的string是用 char*,在 VC 的各類control 中,是用WCHAR (因為多國語言的關係)。
要將 char* 字串轉為 WCHAR 字串的方法是:
char buffer[BUFFERLEN];
WCHAR wbuffer[BUFFERLEN*2];

... fill datas in buffer[]...
// convert
MultiByteToWideChar(CP_ACP, 0, buffer,strlen(buffer),wbuffer,sizeof(wbuffer));
// done!
  • WCHAR,一個''字''需要用兩個character來代,所以bufferlen 要 X2。
  • function 的第一個argument 是 CodePage,以往這種 char * string 都是 ANSI (ASCII) ,所以就用CP_ACP。
ref : MSDN http://msdn2.microsoft.com/en-us/library/ms776413.aspx

這個function 要注意 第4個argument ,決定要轉換的字數,所以要用 strlen( ),不要用sizeof( ),否則轉出來的 wbuffer 後面會有一堆亂碼。

6.07.2007

GPS with sensor - SiRFDiRect

SiRF的 post :

SiRFDiRect Location Technology Delivers Portable Navigation Breakthrough

這是一個內含(?) heading (compas?) 和 accelerater 的GPS receiver。
以往這類額外的sensor只能安裝在汽車上,現在SiRF 直接把他裝在一起(好像也可以拉出來用),配合SiRF的algorithm,讓這個新Receiver+Sensor能夠放在portable device中。

而且, SiRF與Mio合作,已經在Computex 2007 展示這項產品。

可惜沒有看show 出有DR和沒DR routing path 的差異..


DiRect 是 DR 的意思?
所以就是內建DR的SiRFIII

6.06.2007

Embedded VC


Embedded VC 也像 Visual Studio 一樣,有Class Wizard : View - Class Wizard。
利用這個 統一的interface。

利用這個Wizard 增加 Class 和 Message Handler。

增加 Class時,可以選 parent class (當然是MFC的)。

也可以刪除 Message Handler,但是實際上source code的function implementation 還是要手動刪除。


另外 Embedded VC 也附有help ,可以搜尋 一些 embedded VC專屬的資料。

6.04.2007

CE GIF Animation

OS 要加入 GIF Decoder 這一個item。

然後就是取得 GIF 的loopcount 和 FrameDelay,在Groupe中有一篇 : Time delay of animated gif frames...
一位好心人士 stephd 貼了一個sample code,並且說明 GIF 動畫與靜態檔的差異:
多了 :
 PropertyTagLoopCount
PropertyTagFrameDelay
這兩個property.

stephd 並且很好心的附上democode..
    int sizeloopcount = m_pImage->GetPropertyItemSize(PropertyTagLoopCount);
if (sizeloopcount != 0)
{
PropertyItem * pPropertyItem = (PropertyItem*)
malloc(sizeloopcount);
m_pImage->GetPropertyItem(PropertyTagLoopCount, sizeloopcount,
pPropertyItem);
m_AnimatedLoopCount = *((short*)pPropertyItem->value);
delete pPropertyItem;
}

int sizedelay = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay);

if (sizedelay != 0)
{
PropertyItem * pPropertyItem = (PropertyItem*) malloc(sizedelay);
m_pImage->GetPropertyItem(PropertyTagFrameDelay, sizedelay,
pPropertyItem);
// pPropertyItem->value is an array of long. Each long value
// correspond to the delay between each frame / 10 ms
delete pPropertyItem;
}

CoCreateInstance : CLASSID

STDAPI CoCreateInstance(
REFCLSID rclsid,
LPUNKNOWN pUnkOuter,
DWORD dwClsContext,
REFIID riid,
LPVOID* ppv
);
好像是用來動態create class ,msdn 中說明這個function 就是..
CoGetClassObject(rclsid, dwClsContext, NULL, IID_IClassFactory, &pCF);
hresult = pCF->CreateInstance(pUnkOuter, riid, ppvObj)
pCF->Release();
那為什麼不用一般的 Class 生成方式 ?
是為了Serialize ?
所以argument 1 是 ClassID ?
生成Class ID 所指定的物件,並且把object pointer 放在最後的argument中。
-- 這樣使用者還是 要 include class header 呀,所以是為了隱藏 Class Implement Code ?

ClassID : 都是以 "CLSID_" 為開頭

像 CLSID_ImageFactory 就是 ImageFactory 這個Class的Class ID。

6.03.2007

2007.10 GundamOO

?人物設定是 -- 高河ゆん

雖然以前還蠻喜歡他的漫畫 : 源氏,地球人,B型同盟。
畫風也挺好認的,但是 跟Gundam 真的是八竿子打不著呀!

從trailer看來,Gundam 也越來越不像Gundam啦.. (還背個鑽子?)
我覺得挺不錯的呀,不要想到取代NB這件事。
就像當初palm的出現一樣,他是要create一個新的市場。
這是一個很方便你隨時隨地作筆記的東西..

想像你晚上躺在床上讀著paper或小說,讀著讀著,突然想筆記一下心得...
....你會記在那疊paper上? 拿起身邊的紙筆?
有這麼方便的東西,直接打開就可以使用,又有舒適的鍵盤(full-size喔),就像以往隨手拿起紙筆作個notes一樣。
使用這個東西並不會多花一點時間(動作) -- 尤其是那些對鍵盤比紙筆還習慣的人來說,這個東西或許更方便。
就是這樣,有些人,隨時隨地會想要紀錄一些東西,即使一個有"休眠"的NB:開機 -- launch ap -- 開始打字,這些時間一過.. 當初想打字的念頭已經消失了。

我是覺得他可以提供一個取代筆記簿的東西,同時也提供你將你的管理你筆記的能力。

挺不錯的呀 (所以我才一直強調 full-size鍵盤是個重點)。

嗯 --- 但是,提供這樣的功能,這樣的價格,似乎太貴了點..

6.01.2007

第五號屠宰場

本來覺得快要放棄了,後來看到這一段..說道新<<福音>>的那一段:
天哪!這次他們可找錯對象啦!
忍不住笑了出來。
真的是忍不住喔。 緊接著那一段 述說<<新福音>>的內容,也更加好笑了起來。

嗯 -- 這大概就是 馮內果 式的幽默吧。

書 變得好看了起來。
不過,看到最後我還是看不懂。

build openmoko u-boot from source

繼續上次的..try build u-boot from source.

主要是 follow 這一篇 .. http://wiki.openmoko.org/wiki/Migration_to_bad_block_tolerant_builds
這裡說明比u-boot那一篇仔細 (但是我apply 609 的patch 沒有成功,所以還是使用main stream的)。

工作的目錄是 /home/openmoko

設定svn 使用proxy,在./subversion/server 中加入 proxy server,port :
http-proxy-host = 10.1.1.200
http-proxy-port = 3000
checkout openmoko 到 openmoko 目錄
$ svn co https://svn.openmoko.org/ openmoko
安裝git-core,改變default git tool (debian etch)
$ aptitude install git-core
$ update-alternatives --config git
== 選 "git-scm"
export 好http_proxy,checkout u-boot
git clone http://www.denx.de/git/u-boot.git
....這個花很久..

因為monotone 出不去proxy (雖然mailing list中新版的monotone可以經過proxy,可是我這裡還是出不去),
所以只好直接從 openmoko 拿build 好的cross tool
$ wget -r -L http://buildhost.openmoko.org/tmp/cross
...這個花更久,而且 lib 下的file有些沒有抓回來,要確認一下,加上 "-c"抓沒抓到的folder。
修改 bin 下的file,設為可執行。

把抓下來的toolchain copy 到 ..
/space/fic/openmoko/gta01/tmp/cross
設好PATH:
export PATH=/space/fic/openmoko/gta01/tmp/cross/bin:$PATH
u-boot : apply patch:
$ cd u-boot
$ export export QUILT_PATCHES=/home/openmoko/openmoko/trunk/src/target/u-boot/patches
$ quilt push -a
OK. 沒有error message

build u-boot : config and make
$ make ARCH=arm gta01bv2_config
$ make ARCH=arm
OK.