2.20.2009

Kernel Debugger - debugging Release Version Kernel.

原來 relesae 版也可以作 source debug (那 release 版的 "release" 意思是...)。
好像 CE 的 symbol 是放在 *.pdb,所以 release 的 image 不會變大
Follow Instruction : 在 Platform Setting 中 check:
  • Enable Kernel Debugger
  • Enable KITL
還有 bsp 宣告的對應 option.. 後,build release 版.. dowload and run bar image (NK.NB0).. 就可以了。

因為這樣的設置,一boot就會 enable kitl,所以 nk.nb0 會enable kitl,等待連線..
platform build 開啟 workspace (或是直接拖拉 NK.NB0 到 platformbuilder 中),作 "Attach Target" (Connect option 要設好)。就可以了...

然後你就可以用 File - Open 開啟 bsp source code,設break point...
但是在 run 的匙後設breakpoint 不會馬上生效,要break 後再 run 才 會生效


在 PUBLIC, PRIVATE (如果你有install share)的 source 也會 break 進去喔

這樣build 的 kernel (NK)。也可以燒到nandflash 中用eboot boot。

KITL 可以 configure 成 Active (boot 就啟動,所以會hang住),Passive (boot沒啟動,需要時再叫起來)。

叫起來的方法 (大概是.):(http://support.microsoft.com/kb/823606)
// ActiveKitl.c
//
#include <windows.h>
#include <halether.h>

int WINAPI WinMain (
HINSTANCE hInst,
HINSTANCE hInstPrev,
LPTSTR pszCmdLine,
int nCmdShow)
{
PUCHAR pBufferPool = (PUCHAR)malloc(64*1024);
UCHAR ClientId;

if (CallEdbgRegisterClient(&ClientId, "KTC", 0, 8, pBufferPool) == FALSE)
RETAILMSG(1, (TEXT("KITLRegisterClient failed.\r\n")));
else
RETAILMSG(1, (TEXT("KITLRegisterClient succeeded.\r\n")));

while(1)
/* do nothing */;

return 0;
}
.... 我沒試過.

試了..不會動..出現 " KITLRegisterClient Failed",然後 PC 出現 不可辨認的usb裝置。

TRACE CODE,發現在 BSP 中找不到 OALKitlInit( ).
結果是在 Platform\Common\SRC\Common\OAL\kitl.c 中。 (Platformbuilder的 code)
(thanks http://space.itpub.net/16803921/viewspace-506549 ..因為我一直找不到OALKitlInit())

裡面有
    // Start KITL in desired mode
if (!KitlInit((pArgs->flags & OAL_KITL_FLAGS_PASSIVE) == 0)) {
OALMSG(OAL_ERROR, (L"ERROR: OALKitlInit: KitlInit failed\r\n"));
goto cleanUp;
}
所以 follow 這個 code,在 initialize kitl arg 時加上這個 option:

KitlArgs->flags = OAL_KITL_FLAGS_ENABLED | OAL_KITL_FLAGS_POLL | OAL_KITL_FLAGS_PASSIVE;

這樣,開機後,不會等待 kitl connection。
然後 run 上面的 ActiveKitl.exe,就會出現 waiting for connection..
之後再啟動 platform builder, attach device... 就啟動了 kitl.
然後就可以開啟 cesh.exe 下command 了。
不同的是:connect 後,target system 沒有停下來,也沒有 pause ,一樣繼續執行..

要打開 ceshell (CE target control),下 break 後才會暫停,然後就可以進行 source level debugger..

其實這個 kitl arg 是由 eboot 設定的。
在 eboot.c 的 main.c 中可以看到設定 passive 的 code,並且有 comment :
 user selected "passive" KITL (don't connect to the target at boot time)
所以,應該是..進入 eboot command menu, disable kernel debugger,然後開機,kernel 就會有這個 PASSIVE參數...根本就不用去改 initial kitl argument .

所以...

2.18.2009

AVPicture structure 的內容 - 還是 convert_yuv420_rgb565.S

tyedef struct AVPicture {
uint8_t *data[4];
int linesize[4];
} AVPicture;

是給說明一個 frame 的資料內容。
data 是 channel data.
linesize 是channel 的 linesize (寬度).

所以最多有 4 個 channel 資料 (? 哪一種 format 會有四個 channel ?).
以 YUV420 為例,320 x 240 的圖檔,有 Y.U.V 三個 channel,Y 的 linesize 是 320。U, V 的 linesize 都是 160.
所以用到 data[0]~data[3],linesize[0]~linesize[3]。

以 bgr565為例,一個 pixel 一個 word:bgr565,所以沒有分開 channel。所以只有用到 data[0] 和 linesize[0]。

所以 convert _yuv420_rgb565.S 的一開始的 argument 處裡:

ldr r7, [r0, #0] ; Y ptr
ldr r9, [r0, #4] ; U ptr
ldr r10, [r0, #8] ; V ptr
subs r10, r10, r9 ; V ptr - U ptr
ldr r8, [r0, #12]
add r8, r8, r7 ; Y + stride_Y
ldr r4, [r0, #12] ; Stride_Y
mov r4, r4, lsl #1
sub r4, r4, r2 ; (2 * Stride_Y) - width
ldr r5, [r0, #16] ; Stride_U
sub r5, r5, r2, lsr #1 ; Stride_U - (width / 2)
ldr r6, [r0, #20] ; Stride_V
sub r6, r6, r2, lsr #1 ; Stride_V - (width / 2)
add r0, r1, r2, lsl #1 ; RGB + 1
stmdb sp!, { r0-r10 }
; Stack description :
; (sp+ 0) RGB + one line
; (sp+ 4) RGB
; (sp+ 8) width (save)
; (sp+12) height
; (sp+16) (2 * stride_Y) - width
; (sp+20) stride_U - (width / 2)
; (sp+24) stride_V - (width / 2) !!! UNUSED !!!
; (sp+28) Y ptr
; (sp+32) Y ptr + one line
; (sp+36) U ptr
; (sp+40) V - U
就是分別取出
data[0] : Y, data[1] : U, data[2] : V

linesize[0] : stride_Y, linesize[1] : stride_U, linesize[2] : stride[V].
convert_yuv420_rgb565(AVPicture *pic,unsigned char *out,int width,int height)
的參數 width, 和 Stride_Y 有什麼不一樣?

Stride_Y 是 source 影像的寬度。
width 是你要顯示的寬度 (clip)。

有一張 1024x768 的圖,你可以只顯示 800x768 (左邊部份)。

所以不一樣.

從 assembly 看,AVPicture 的 structure 好像不是這樣,他用的好像是:
struct AVPicture{
char *data[3];
int linesize[3];
} AVPicture;
實際上...也是用這個 structure Run 起來的...

2.17.2009

Optimize - learned from yuv420_rgb565

所以optimze 的方法就是..
  • optimze with speed
  • 盡量使用 mla ( a = (b*c)+d))
  • 盡量不使用 condition jump
  • 反組譯
  • exam asm - 盡量使用所有 register
  • 打亂 instruction. 混合 register only arithematic 和 data load/store
所以應該要try 一下:
  1. 先照 assembly algorithm 寫出 c code. - cpu % , 1000 loop time.
  2. 反組譯, 寫成 .S link - 確認 work
  3. follow yuv420_rgb565.s 略為修改,但不作 scramble - cpu %, 1000 loop time.
  4. 作 scamble, 混合 load/store 和 register only instruction. - cpu %, 1000 loop time
如果有空要這樣作.....

Code Reading - 上一篇的YUV - RGB assembly

最後的 table : rb_clip_dummy, rb_clip, 還有 g_clip_dummy, g_clip。
dummy 都是0,然後兩個加起來, rb 是 16 x 8, g 是16 x 16。
這個大概是跟 paper 講的一樣,用 table 取代 saturation 判斷。
0 的部份就是 負 值的部份。

所以 整個 assembly code 中沒有 compare jmp 指令 (除了最後的 line end 判斷)。
YUV 計算部份直接用 mla ( x +),沒有使用 table -- 大概是因為 ARM 作 16x16 只要1 個 clock,所以沒必要。

一樣是作 w (寬度),然後 line.. 一次(loop) 4 pixel。

因為先作 bit shift (5-6-5)再做查表,所以table[]不用太大。

code 沒有避免使用 mul (mla),反而大量使用,避免不需要的 ldr 動作 (大概是 ldr 和 mla 都是一個 clk 吧)。其中:
  • r8 : multy 0x00012A15
  • r9 : (Y-16)
  • r6 : Coef *(V-128) + 32768
  • r5 : Coef*(U-128) + 32768
  • r4 : -Coef *(U-128) - Coef*(V-128) + 32768
剩下的就..


原來 eVC 的 ARMASM 最佳 example code 就是 OS bsp 下所有的 .s file。
所以語法參考 BSP 就可以了。
MSDN : CE .NET 4.2 ASM

大概要改的是:
  1. MS armasm 規定只有 label 可以從一行的第一格開始,所以所有其他的 instruction, directive 都要先空
  2. comment 是以 ; 開頭
  3. label 不可以加 : 號
  4. .byte 改為 DCB
  5. .word 改為 DCD
  6. .text 宣告要改為 AREA |.text|,CODE, ARM
  7. .global 要改 EXPORT
reference
http://checko.blogspot.com/2006/09/writting-arm-assembly-in-embedded-vc_28.html
  • 手動加入 yuv420_rgb565.s
  • project setting - yuv420_rgb565.s - custom build : 填入 armasm ... (Debug, Relese 都要加)
  • 引用的 .cpp 加入:
     extern "c" void convert_yuv420_rgb565(char *,char*,int,int);
Q_Q ,, argument passing type 不一樣...


這個 assembly code 有"適當安排過". 可以看到:
有 memory access 的 instruction,接著的會是 register-only 的 operation。
這樣instruction pipeline 就可以沒有阻礙的run 下去 (如果一個 load 下一個 store, pipe line 要等 cache/memory 的同步?)
作法是:要使用之前,在 n 個 instruction 前就 load...

所以下面是重新安排後的 code,變得比較容易看....
;
; void convert_yuv420_rgb565(AVPicture *picture, unsigned char *results, int w, int h) ;
;

AREA |.text|,CODE,ARM

EXPORT convert_yuv420_rgb565

convert_yuv420_rgb565
stmdb sp!, { r4 - r12, lr } ; all callee saved regs
ldr r7, [r0, #0] ; Y ptr
ldr r9, [r0, #4] ; U ptr
ldr r10, [r0, #8] ; V ptr
subs r10, r10, r9 ; V ptr - U ptr
ldr r8, [r0, #12]
add r8, r8, r7 ; Y + stride_Y
ldr r4, [r0, #12] ; Stride_Y
mov r4, r4, lsl #1
sub r4, r4, r2 ; (2 * Stride_Y) - width
ldr r5, [r0, #16] ; Stride_U
sub r5, r5, r2, lsr #1 ; Stride_U - (width / 2)
ldr r6, [r0, #20] ; Stride_V
sub r6, r6, r2, lsr #1 ; Stride_V - (width / 2)
add r0, r1, r2, lsl #1 ; RGB + 1
stmdb sp!, { r0-r10 }
; Stack description :
; (sp+ 0) RGB + one line
; (sp+ 4) RGB
; (sp+ 8) width (save)
; (sp+12) height
; (sp+16) (2 * stride_Y) - width
; (sp+20) stride_U - (width / 2)
; (sp+24) stride_V - (width / 2) !!! UNUSED !!!
; (sp+28) Y ptr
; (sp+32) Y ptr + one line
; (sp+36) U ptr
; (sp+40) V - U
mov lr, r2 ; Initialize the width counter
add r0, pc, #(const_storage-.-8) ; r0 = base pointer to the constants array
ldr r8, [r0, #(4*4)] ; r8 = multy
yuv_loop

ldr r10, [sp, #28] ; r10 = Y
ldrb r9, [r10, #0] ; r9 = *Y

add r10, r10, #2 ; r10 = Y + 2
str r10, [sp, #28] ; save Y + 2

ldr r1, [sp, #36] ; r1 = U
ldrb r11, [r1] ; r11 = *U
add r1, r1, #1 ;; r1 = U++
str r1, [sp, #36] ; store U++

ldr r2, [sp, #40] ; r2 = V - U
add r2, r1, r2 ; r2 = V+1
ldrb r12, [r2, #-1] ; r12 = *V

sub r11, r11, #128 ; r11 = *U - 128
sub r12, r12, #128 ; r12 = *V - 128

mov r7, #32768 ; r7 = 32768 (for additions in MLA)

add r0, pc, #(const_storage-.-8) ; r0 = base pointer to the constants array
ldr r1, [r0, #(4*0)] ; r1 = crv
mla r6, r1, r12, r7 ; r6 = nonyc_r = crv * (*V - 128) + 32768

ldr r2, [r0, #(4*3)] ; r2 = -cgv
mla r4, r2, r12, r7 ; r4 = - cgv * (*V - 128) + 32768

ldr r3, [r0, #(4*1)] ; r3 = cbu
mla r5, r3, r11, r7 ; r5 = nonyc_b = cbu * (*U - 128) + 32768

sub r9, r9, #16 ; r9 = *Y - 16
mla r7, r8, r9, r6 ; r7 = (*Y - 16) * multy + nonyc_r

ldr r0, [r0, #(4*2)] ; r0 = -cgu
mla r4, r0, r11, r4 ; r4 = nonyc_g = - cgu * (*U - 128) + r4 = - cgu * (*U - 128) - cgv * (*V - 128) + 32768

add r0, pc, #(rb_clip-.-8) ; r0 contains the pointer to the R and B clipping array
ldrb r7, [r0, r7, asr #(16+3)] ; r7 = R composant

mla r12, r8, r9, r5 ; r12 = (*Y - 16) * multy + nonyc_b
mla r1, r8, r9, r4 ; r1 = (*Y - 16) * multy + nonyc_g

ldrb r12, [r0, r12, asr #(16+3)] ; r12 = B composant (and the start of the RGB word)
add r12, r12, r7, lsl #11 ; r12 = .GB ...

add r11, pc, #(g_clip-.-8) ; r11 now contains the pointer to the G clipping array
ldrb r1, [r11, r1, asr #(16+2)] ; r1 contains the G part of the RGB triplet
add r12, r12, r1, lsl #5 ; r12 = RGB ... (ie the first pixel (half-word) is done)

; --- next pixel
ldrb r9, [r10, #-1] ; r9 = *(Y+1)
sub r9, r9, #16 ; r9 = *(Y+1) - 16

mla r10, r8, r9, r6 ; r10 is the Red part of the RGB triplet
mla r7, r8, r9, r5 ; r7 is the Blue part of the RGB triplet
mla r2, r8, r9, r4 ; r2 is the Green part of the RGB triplet

ldrb r2, [r11, r2, asr #(16+2)] ; r2 = G composant
add r12, r12, r2, lsl #(5+16) ; r12 = RGB .G.
ldrb r7, [r0, r7, asr #(16+3)] ; r7 = B composant
add r12, r12, r7, lsl #(0+16) ; r12 = RGB .GB
ldrb r10, [r0, r10, asr #(16+3)] ; r10 = R composant
add r12, r12, r10, lsl #(11+16) ; r12 = RGB RGB

;---- do store ----
ldr r3, [sp, #4] ; r3 = RGB
add r3, r3, #4 ; r3 = RGB++ (ie next double-pixel)
str r3, [sp, #4] ; store the RGB pointer
str r12, [r3] ; store the rgb pixel at *RGB

;---- next line ----
ldr r1, [sp, #32] ; r1 = Ynext
ldrb r9, [r1] ; r9 = *Ynext
sub r9, r9, #16 ; r9 = *Ynext - 16

mla r2, r8, r9, r4 ; r2 is the Green part of the RGB triplet
mla r7, r8, r9, r5 ; r7 is the Blue part of the RGB triplet
mla r10, r8, r9, r6 ; r10 is the Red part of the RGB triplet

ldrb r12, [r0, r7, asr #(16+3)] ; r12 = ..B ...
ldrb r10, [r0, r10, asr #(16+3)] ; r10 = B composant
add r12, r12, r10, lsl #11 ; r12 = R.B ...
ldrb r2, [r11, r2, asr #(16+2)] ; r2 = G composant
add r12, r12, r2, lsl #5 ; r12 = RGB ...

;---- next pixel
ldrb r9, [r1, #1] ; r9 = *(Ynext+1)
sub r9, r9, #16 ; r9 = *(Ynext+1) - 16

add r1, r1, #2 ; r1 = Ynext + 2
str r1, [sp, #32] ; store the increased Ynext pointer

mla r7, r8, r9, r5 ; r7 is the Blue part of the RGB triplet
mla r10, r8, r9, r6 ; r10 is the Red part of the RGB triplet
mla r2, r8, r9, r4 ; r2 is the Green part of the RGB triplet

ldrb r7, [r0, r7, asr #(16+3)] ; r7 = B composant
add r12, r12, r7, lsl #(16+0) ; r12 = RGB ..B
ldrb r10, [r0, r10, asr #(16+3)] ; r10 = R composant
add r12, r12, r10, lsl #(16+11) ; r12 = RGB R.B
ldrb r2, [r11, r2, asr #(16+2)] ; r2 = G composant
add r12, r12, r2, lsl #(16+5) ; r12 = RGB RGB

;---- do store
ldr r3, [sp, #0] ; r3 = RGBnext pointer
add r3, r3, #4 ; r3 = next pixel on the RGBnext line
str r12, [r3, #-4] ; store the next pixel
str r3, [sp, #0] ; store the increased 'next line' pixel pointer

;-- complete, do loop --
subs lr, lr, #2 ; decrement the line counter
bne yuv_loop ; and restart if not at the end of the line

ldr r0, [sp, #8] ; r0 = saved width
ldr r1, [sp, #0] ; r1 = RGBnext pointer
mov lr, r0 ; lr = saved width (to restart the line counter)
str r1, [sp, #4] ; current RGBnext pointer is next iteration RGB pointer
add r1, r1, r0, lsl #1 ; r1 = update RGBnext to next line
str r1, [sp, #0] ; store updated RGBnext pointer

ldr r3, [sp, #16] ; r3 = (2 * stride_Y) - width
ldr r4, [sp, #28] ; r4 = Y ptr
ldr r5, [sp, #32] ; r5 = Ynext ptr
add r4, r4, r3 ; r4 = Y ptr for the next two lines
add r5, r5, r3 ; r5 = Ynext ptr for the next two lines
str r4, [sp, #28] ; store updated Y pointer
str r5, [sp, #32] ; store update Ynext pointer

ldr r1, [sp, #20] ; r1 = stride_U - (width / 2)
ldr r2, [sp, #36] ; r2 = U ptr

ldr r6, [sp, #12] ; get height counter

add r2, r2, r1 ; update U ptr
str r2, [sp, #36] ; store updated U ptr (and update 'V' at the same time :-) )

subs r6, r6, #2
str r6, [sp, #12]
bne yuv_loop

; Exit cleanly :-)
add sp, sp, #(11*4) ; remove all custom things from stack
ldmia sp!, { r4 - r12, pc } ; restore callee saved regs and return


const_storage
; In order : crv, cbu, - cgu, - cgv, multy
DCD 0x00019895, 0x00020469, 0xffff9bb5, 0xffff2fe1, 0x00012A15
rb_clip_dummy
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
rb_clip
DCB 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
DCB 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
DCB 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
DCB 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
DCB 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
g_clip_dummy
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
g_clip
DCB 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
DCB 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
DCB 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
DCB 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
DCB 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
END

2.16.2009

YUV to RGB in ARMv4 assembly

以前 ipaq 3630 familiar 的bbplayer 有一段code作 yuv to rgb..
(http://www.koders.com/noncode/fid9B79A2EAD6C3F6EE8454AB93E5D9F77A1C509D19.aspx?s=mp3)
用 assembly 寫的,因為看到 版權宣告是 free 的,所以把全部內容都貼出來:

/*
Copyright (c) 2001 Lionel Ulmer (lionel.ulmer@free.fr / bbrox@bbrox.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/* WARNING : this function only works when stride_U == stride_V (I use some hacks to
not have to do too many computations at line's end)...

C-like prototype :
void convert_yuv420_rgb565(AVPicture *picture, unsigned char *results, unsigned char *_py,unsigned char *_pu,unsigned char *_pv);

*/

#ifdef __arm__

.text
.align

.global convert_yuv420_rgb565
convert_yuv420_rgb565:

stmdb sp!, { r4 - r12, lr } @ all callee saved regs
ldr r7,[r0,#0] @dest width
ldr r9,[r0,#4] @dest height
ldr r10,[r0, #12] @ sourcewidth
ldr r5, [r0, #16] @ source_height
mul r4,r5,r10 @zll
mov r4,r4,lsr#2 @ Vptr - U ptr
ldr r6, [r0, #20] @ rgbstrid
ldr r8,[r0, #12] @zll width
add r8, r8, r2 @ Y + stride_Y
add r0,r1,r6 @ RGB + 1
stmdb sp!, { r0-r10 }
@ Stack description :
@ (sp+ 0) RGB + one line r0
@ (sp+ 4) RGB r1
@ (sp+ 8) _py r2
@ (sp+12) _pu r3
@ (sp+16) _pv - _pu r4
@ (sp+20) sourceheight r5
@ (sp+24) rgbstrid r6
@ (sp+28) destwidth r7
@ (sp+32) Ynext r8
@ (sp+36) destheight r9
@ (sp+40) sourcewidth r10

mov lr,r10 @ Initialize the width counter
add r0, pc, #(const_storage-.-8) @ r0 = base pointer to the constants array
ldr r8, [r0, #(4*4)] @ r8 = multy
yuv_loop:
add r0, pc, #(const_storage-.-8) @ r0 = base pointer to the constants array
ldr r10, [sp, #8] @ r10 = Y ...
ldr r1, [sp, #12] @ r1 = U ...
ldrb r9, [r10, #0] @ r9 = *Y ...
ldrb r11, [r1] @ r11 = *U
add r1, r1, #1 @ r1 = U++
ldr r2, [sp, #16] @ r2 = V - U ...
str r1, [sp, #12] @ store U++
add r2, r2, r1 @ r2 = V+1
ldrb r12, [r2, #-1] @ r12 = *V
sub r11, r11, #128 @ r11 = *U - 128
sub r12, r12, #128 @ r12 = *V - 128
ldr r1, [r0, #(4*0)] @ r1 = crv
mov r7, #32768 @ r7 = 32768 (for additions in MLA)
ldr r2, [r0, #(4*3)] @ r2 = -cgv
mla r6, r1, r12, r7 @ r6 = nonyc_r = crv * (*V - 128) + 32768
ldr r3, [r0, #(4*1)] @ r3 = cbu
mla r4, r2, r12, r7 @ r4 = - cgv * (*V - 128) + 32768
sub r9, r9, #16 @ r9 = *Y - 16
mla r5, r3, r11, r7 @ r5 = nonyc_b = cbu * (*U - 128) + 32768
ldr r0, [r0, #(4*2)] @ r0 = -cgu
mla r7, r8, r9, r6 @ r7 = (*Y - 16) * multy + nonyc_r
add r10, r10, #2 @ r10 = Y + 2
mla r4, r0, r11, r4 @ r4 = nonyc_g = - cgu * (*U - 128) + r4 = - cgu * (*U - 128) - cgv * (*V - 128) + 32768
add r0, pc, #(rb_clip-.-8) @ r0 contains the pointer to the R and B clipping array
mla r12, r8, r9, r5 @ r12 = (*Y - 16) * multy + nonyc_b
ldrb r7, [r0, r7, asr #(16+3)] @ r7 = R composant
mla r1, r8, r9, r4 @ r1 = (*Y - 16) * multy + nonyc_g
ldrb r9, [r10, #-1] @ r9 = *(Y+1)
str r10, [sp, #8] @ save Y + 2
ldrb r12, [r0, r12, asr #(16+3)] @ r12 = B composant (and the start of the RGB word)
add r11, pc, #(g_clip-.-8) @ r11 now contains the pointer to the G clipping array
ldrb r1, [r11, r1, asr #(16+2)] @ r1 contains the G part of the RGB triplet
sub r9, r9, #16 @ r9 = *(Y+1) - 16
mla r10, r8, r9, r6 @ r10 is the Red part of the RGB triplet
add r12, r12, r7, lsl #11 @ r12 = .GB ...
mla r7, r8, r9, r5 @ r7 is the Blue part of the RGB triplet
add r12, r12, r1, lsl #5 @ r12 = RGB ... (ie the first pixel (half-word) is done)
mla r2, r8, r9, r4 @ r2 is the Green part of the RGB triplet
ldrb r10, [r0, r10, asr #(16+3)] @ r10 = R composant
ldrb r7, [r0, r7, asr #(16+3)] @ r7 = B composant
ldr r1, [sp, #32] @ r1 = Ynext
ldrb r2, [r11, r2, asr #(16+2)] @ r2 = G composant
ldrb r9, [r1] @ r9 = *Ynext
add r12, r12, r2, lsl #(5+16) @ r12 = RGB .G.
sub r9, r9, #16 @ r9 = *Ynext - 16
mla r2, r8, r9, r4 @ r2 is the Green part of the RGB triplet
add r12, r12, r7, lsl #(0+16) @ r12 = RGB .GB
mla r7, r8, r9, r5 @ r7 is the Blue part of the RGB triplet
add r12, r12, r10, lsl #(11+16) @ r12 = RGB RGB
ldr r3, [sp, #4] @ r3 = RGB
mla r10, r8, r9, r6 @ r10 is the Red part of the RGB triplet
str r12, [r3] @ store the rgb pixel at *RGB
add r3, r3, #4 @ r3 = RGB++ (ie next double-pixel)
str r3, [sp, #4] @ store the RGB pointer
ldrb r9, [r1, #1] @ r9 = *(Ynext+1)
add r1, r1, #2 @ r1 = Ynext + 2
sub r9, r9, #16 @ r9 = *(Ynext+1) - 16
ldrb r12, [r0, r7, asr #(16+3)] @ r12 = ..B ...
ldrb r10, [r0, r10, asr #(16+3)] @ r10 = B composant
mla r7, r8, r9, r5 @ r7 is the Blue part of the RGB triplet
add r12, r12, r10, lsl #11 @ r12 = R.B ...
ldrb r2, [r11, r2, asr #(16+2)] @ r2 = G composant
mla r10, r8, r9, r6 @ r10 is the Red part of the RGB triplet
add r12, r12, r2, lsl #5 @ r12 = RGB ...
mla r2, r8, r9, r4 @ r2 is the Green part of the RGB triplet
ldrb r7, [r0, r7, asr #(16+3)] @ r7 = B composant
str r1, [sp, #32] @ store the increased Ynext pointer
add r12, r12, r7, lsl #(16+0) @ r12 = RGB ..B
ldrb r10, [r0, r10, asr #(16+3)] @ r10 = R composant
ldr r3, [sp, #0] @ r3 = RGBnext pointer
add r12, r12, r10, lsl #(16+11) @ r12 = RGB R.B
ldrb r2, [r11, r2, asr #(16+2)] @ r2 = G composant
add r3, r3, #4 @ r3 = next pixel on the RGBnext line
add r12, r12, r2, lsl #(16+5) @ r12 = RGB RGB
str r12, [r3, #-4] @ store the next pixel
str r3, [sp, #0] @ store the increased 'next line' pixel pointer
subs lr, lr, #2 @ decrement the line counter
bne yuv_loop @ and restart if not at the end of the line


ldr r0, [sp, #40] @ r0 = saved sourcewidth ....


ldr r1, [sp, #0] @ r1 = RGBnext pointer
ldr r2, [sp, #24] @ zll rgbstrid
mov lr, r0 @ lr = saved width (to restart the line counter)

subs r3,r2,r0,lsl#1 @ (rgbstride - 2 width)
add r1,r1,r3 @ the nest two RGBline
str r1, [sp, #4] @ current RGBnext pointer is next iteration RGB pointer
add r1,r1,r2 @ r1 = update RGBnext to next line
str r1, [sp, #0] @ store updated RGBnext pointer

ldr r3, [sp, #40] @ sourcewidth
ldr r4, [sp, #8] @ r4 = Y ptr
ldr r5, [sp, #32] @ r5 = Ynext ptr
add r4, r4, r3 @ r4 = Y ptr for the next two lines
add r5, r5, r3 @ r5 = Ynext ptr for the next two lines
str r4, [sp, #8] @ store updated Y pointer
str r5, [sp, #32] @ store update Ynext pointer


ldr r6, [sp, #20] @ get height counter
subs r6, r6, #2
str r6, [sp, #20]
bne yuv_loop

@ Exit cleanly :-)
add sp, sp, #(11*4) @ remove all custom things from stack
ldmia sp!, { r4 - r12, pc } @ restore callee saved regs and return


const_storage:
@ In order : crv, cbu, - cgu, - cgv, multy
.word 0x00019895, 0x00020469, 0xffff9bb5, 0xffff2fe1, 0x00012A15
rb_clip_dummy:
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
rb_clip:
.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
.byte 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
.byte 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
.byte 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f
g_clip_dummy:
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
g_clip:
.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f
.byte 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f

#endif

CeGCC - Try Inline Assembly

Reference 這一篇:ARM GCC Inline Assembly
寫一段 inline assemly code 試試..

可以reference mpegvideo_armv5te.c

CeGCC : 繼續..

先試試看 cegcc compile .o 能不能被 eVC link..
加上 argument . build form v5TE 看看能不能run..
-march=armv5te
用 cegcc build add10.c 。(裡面只有 add10( ) 這個 function)。
將 add10.obj 放到 eVC 中。eVC 的其他 source 可以call 到 add10()。
雖然會有 warnning:
 multiple '.text' sections found with different attributes (E00000020)
那就這樣用吧..

有關 gcc 中 embedded assembly 的用法:Extended Asm.

還有,reference 的範本就是 ffmpeg 的 mpegvideo_armv5te.c

arm v5te 的 dsp instruction 可以 reference msdn : http://msdn.microsoft.com/en-gb/library/ms253986.aspx

2.13.2009

Build DLL - using CeGcc

目標是要 build DLL 檔。
剛好在 這裡 看到有一個 instruction ,target 是 DLL:

arm-wince-cegcc-gcc -shared *.o -o libvorbisidec.dll
看來應該是先用 -c compile 成 .o ,再用 -shareed *.o 把所有 .o 包裝成 DLL. (猜的)
這是build tremor : libvorbisidec.dll 的instruction.
順便看一下 Xiph.org , 原來是 ogg codec ,:
Ogg Vorbis is a fully open, non-proprietary, patent-and-royalty-free, general-purpose compressed audio format for mid to high quality (8kHz-48.0kHz, 16+ bit, polyphonic) audio and music at fixed and variable bitrates from 16 to 128 kbps/channel.

所以大家 default 都要用這個才對,別再用 mp3 了..

照著這篇試試看..
svn co -r14321 http://svn.xiph.org/branches/lowmem-branch/Tremor
需要 libtool..
照著 make 就 fail, 說是 arm_asm 有不知道的定義,所以大概要用 0.50 版的 cegcc 吧!

最後是follow 同一篇的 zlib example 完成。
make 最後 example 時會fail,說是libz.a 沒有 index,要 run ranlib 產生,但是用 host 的 ranlib 還是沒效,要run 'arm-wince-cegcc-ranlib' 才有效。 run 過後再 make 就OK

CeGcc : gcc for Windows CE (ARM) -- 安裝篇

optimize似乎已經到極限。
接下來只能用 ARM v5TE 的 DSP instruction 來作。
但是 eVC 沒有 support v5TE。
所以.. 要試試看 cegcc.

我要 用的應該是 arm-mingw32ce : 是在 Windows 的 Cygwin下 build Windows CE 的 native apps.

所以到 這裡 (還真難找),download win-cegcc-mingw32ce-0.51.0-1.tar.gz
解開是一個 opt folder (? 放到 Cygwin 下的 opt 就OK?)

沒有 for windows 的 installation guid,Linux 倒是有 (還是 安裝到 Linux ?)

就裝在 Linux 吧..

Wiki 有更詳細的說明.. for ubuntuSDL 喔.
就 follow ubuntu 的好了.. 要install alien..
然後 download 兩個 rpm,,,然後
sudo alien -i cegcc-cegcc-0.51.0-1.i586.rpm mandriva-cegcc-mingw32ce-0.51.0-1.i586.rpm
安裝很久...幾乎以為是當機..
裝完後..他說要自己建 symbolic link 到剛剛安裝的 path..

sudo ln -s /opt/mingw32ce/bin/* /usr/bin/
sudo ln -s /opt/cegcc/bin/* /usr/bin/

原Wiki是手動copy 所有 bin 內的 file 過去..

然後,試試看 sample.c:
#include <windows.h>

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
MessageBoxW(0, L"HELLO!", L"H3LLO!", 0);
}
build:
有兩個command 都可以 build ..
arm-wince-cegcc-gcc
arm-wince-mingw32ce-gcc
build 出來後,第二個 command 的 target size 比較大。
文件說build 出來的 exe 不能直接 run,需要 dll.

但是測試結果第二個 command : arm-wince-mingw32e-gcc build 出來的 sample program 可以直接 run (大概用得的 funciton 不多吧...)

文件有說明這兩個 gcc 的不同處:
In an apparent attempt to complicate matters, we implement not only the arm-wince-cegcc target (see above), but also the arm-wince-mingw32ce target. MinGW is a free software project implementing a Minimalist GNU for Windows. We're using this target to build applications that merely use the Windows CE API, not our CeGCC (newlib based) library. (Note that this is neither a full nor an official port of MinGW.)
大概是說: mingw32e 版本 利用mingw 的環境,build 出只有呼叫Windows CE API 的 program,沒有呼叫cegcc 自己的api (大概是說 link 的 function 吧...)。

所以應該要用 mingw32ce 版本。

2.12.2009

Windows用Eclipse 開發 Android ---- 安裝

還是 follow 這一篇.. getting start
  1. JRE : -- 機器中原來就有了,所以沒裝
  2. JDK : jdk-6u12-windows-i586-p.exe
  3. Eclipse : eclipse-java-ganymede-SR1-win32 ---- 解開就好
  4. Android SDK : android-sdk-windows-1.0_r2.zip --- 解開就好
Eclipse 安裝完,要裝 ADT (Android Developement Toolkit for Eclipse)

這部份用 Eclipse 的 "software update" 功能來安裝。
所以有 proxy 的要設好Eclipse中的 proxy)。

Eclipse 還要設定 Android SDK 的位置

裝完 ADT 後,Eclipse 的 "preference" 會出現 Android 選項,需要設定 Android SDK folder 的位置 (就是 Android SDK 解開後的位置)。


這樣環境就算是弄好了,可以開始寫 sample code:

寫起來有點囉唆,create一個 project 要指定 3, 4 個 class name。還有啟動什麼的...
create 完 project,基本的 source outline 會自動 create 好。

寫好按"RUN"就會啟動 emulator.... 然後就是...等.....

[2009-02-12 09:34:04 - HelloAndroid] ------------------------------
[2009-02-12 09:34:04 - HelloAndroid] Android Launch!
[2009-02-12 09:34:04 - HelloAndroid] adb is running normally.
[2009-02-12 09:34:04 - HelloAndroid] Launching: helloAndroid.Hello.HelloAndroidAct
[2009-02-12 09:34:04 - HelloAndroid] Automatic Target Mode: launching new emulator.
[2009-02-12 09:34:04 - HelloAndroid] Launching a new emulator.
[2009-02-12 09:34:10 - HelloAndroid] New emulator found: emulator-5554
[2009-02-12 09:34:10 - HelloAndroid] Waiting for HOME ('android.process.acore') to be launched...
[2009-02-12 09:38:39 - HelloAndroid] HOME is up on device 'emulator-5554'
[2009-02-12 09:38:39 - HelloAndroid] Uploading HelloAndroid.apk onto device 'emulator-5554'
[2009-02-12 09:38:39 - HelloAndroid] Installing HelloAndroid.apk...
以上是按下RUN後Eclipse的 console log.. 最後一個 message出來,到畫面出現桌面圖案。約還要 3 min..
所以按下RUN到真的RUN起來,是 5 min !!!
不要、以為當機了喔

2.11.2009

ARM core

ARM v5T 在 ARM v4T 的instruction 增加了 BLX, CLZ, BRK 等新指令。
ARM v5TE 在 ARM v5T 的instruction 增加了 signal processing instruction set extension.
在 furber 的書中有說明到 這個 signal processing instruction set extension 的內容:
mul then add , saturation 判斷,一個 register 同時處理兩個 16 bit 資料 (high, low word).
ARM v5TEJ 則是多加了 Jazelle for Java.
ARM v6 則多了 SIMD instruction.


ARM920T 是 v4T
ARM926EJS 是 v5TE

但是 若是用 eVC的話,就不用考慮這麼多了,因為他只會產生 ARM v4...
先把 YUV420 (8-8-8)砍成 YUV420(5-5-5)好了。
這樣 table 就可以縮減

15873 - 最原始的,compile option 是 Default
12363 - 最原始的,compile optin 是 Maximun speed.
12366 - 最原始的,修改 saturation 判斷 - 原來的有錯.
10376 - combine 兩個 shift動作
9720 - 使用一次查表
8964 - 兩次計算存入一次 (fit to 32bit) <-- 這個有寫錯,所以


11942 - 原來的
12323 - 先縮成 5 bit : 大概是shift的動作增加了時間..
11984 - 再把 combine 的bit shit 移掉 : 回到原來..
12342 - 再把 >>8 改為 / 256 : 大概是/256要keep sign bit,MS是用第二個 shift作的。
13694 - 再加入 0~255的bound check
25501 - 再把CoefRU[] table 由unsigned int改為int !!!
13496 - 剛剛的再執行一次 ,比較合理,but why ?
13234 - 再把Coef[] table 由 int 改為 short.
13360 - 再把Coef[1024]table由 unsigned int 改為 unsigned short -- 雖然現在這個 table 沒有用到。

無法瞭解MS的optimization

結果使用"雙查表",速度反而變慢。
assembly code 是變短了,但是速度反而變慢。
是因為 table 太大,無法放在 cache 的關係嗎?

無法瞭解MS的optimization 和 codegen. 為什麼
 rgb565 = r | g | b;
*(unsigned int*)target_buf = rgb565;
執行時間會比
 rgb565 = (r<<11) | (g<<5) | (b>>3);
*target_buf++ = (char)rgb565;
*target_buf = rgb565>>8;
來得慢..

2.10.2009

Qt is slow if no floating point support

Qt 慢的原因,本來猜是 framebuffer 沒有直接操作,結果是 floating point 的關係。
劃 Line.. 竟然轉成 float 在計算...在沒有 floating point 運算器的 mcu ,簡直是無法接受....

Qt, 還是在高階平台使用好了.

YUV420 轉 RGB565


R = 1.164 * (Y-16) + + 1.596 * (V-128) final : 5 bit
G = 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 * (V-128) final : 6 bit
B = 1.164 * (Y-16) + 2.018 * (U-128) final : 5 bit

R.G.B Range : (Y.U.V are 8 bits):

max : B : 1.164 * (255-16) + 2.018 * (255-128) = 534.482
min : G : 1.164 * (0 - 16) - 0.391 * (255-128) - 0.813 * (255-128) = -171.832

所以 8 bit YUV 轉成 RGB 後,最高只有到
take advantage of the final 5-6-5 bits.
source not need to be 8 bits.
R =  ( 1.164 * (Y-16) +                 + 1.596 * (V-128) )/8          final : 5 bit
G = ( 1.164 * (Y-16) - 0.391 * (U-128) - 0.813 *(V-128) )/4 final : 6 bit
B = ( 1.164 * (Y-16) + 2.018 * (U-128) )/8 final : 5 bit

變成:
R =  0.1455 * (Y-16) +                   + 0.1995 * (V-128)           final : 5 bit
G = 0.291 * (Y-16) - 0.09775 * (U-128) - 0.04575 *(V-128) final : 6 bit
B = 0.1455 * (Y-16) + 0.25225 * (U-128) final : 5 bit

目標是希望..

word rgb565 = ( RY[Y]+RV[V] ) | ( GY[Y]+GU[U]+GV[V] ) | ( BY[Y]+BU[U] )

因為是 YUV420 ,最好是..(U.V矩陣 的HighWord和LowWord一樣)

DWORD rgb565x2 =( (RYL[Y1]|RYH[Y2])+RV[V] ) |
( (GYL[Y1]|GYG[Y2])+GU[U]+GV[V] ) |
( (BYL[Y1]|BYH[Y2])+BU[U] )
問題:如何確保 + 後不會16 bit overfload ?

if possible 再共用下一個scanline (因為是 YUV420)..

RP=RV[v];
GP=GU[U]+GV[V];
BP=BU[U];

DWORD rgb565x2linea =( (RYL[Y1a]|RYH[Y2a])+RP ) |
( (GYL[Y1a]|GYG[Y2a])+GP ) |
( (BYL[Y1a]|BYH[Y2a])+BP );
DWORD rgb565x2lineb =( (RYL[Y1b]|RYH[Y2b])+RP ) |
( (GYL[Y1b]|GYG[Y2b])+GP ) |
( (BYL[Y1b]|BYH[Y2b])+BP );
但是好像無法保證不會overflow (saturation)。
回到:
word rgb565 = ( RY[Y]+RV[V] ) | ( GY[Y]+GU[U]+GV[V] ) | ( BY[Y]+BU[U] )

ref http://msdn.microsoft.com/en-us/library/ms867704.aspx

2.07.2009

在 Gea Suan Lin's Blog 看到這一篇,覺得他說得真不錯,所以我也把這一段 copy 過來..
Here’s the problem with copying:
Copying skips understanding. Understanding is how you grow.
You have to understand why something works or why something is how it is.
When you copy it, you miss that. You just repurpose the last layer instead of understanding all the layers underneath.
完全贊同這句話。
親自去作才是最重要的事..

直接Copy,就失掉成長的機會。


vendor已經送 demo code 過來,而且已經幫你改好了.......

讀 datasheet,自己作一次?
還是直接就用了,有問題call FAE ?

當然,還有更糟的作法啦...

唉! 當然....
可能正確的作法,老闆可能會不高興...

2.06.2009

食譜材料中英文翻譯

別人寄的,archive一下。

麵粉/中筋麵粉 Plain flour /all-purpose flour
低筋麵粉/低根粉 cake flour / soft flour / weak flour / low protein flour
高筋麵粉/筋麵/根麵/高根粉 gluten flour / strong flour / bread flour / baker's flour / high protein flour
全麥麵粉 whole wheat flour
澄麵粉/澄粉/澄麵 non-glutinous flour / wheat flour / wheat starch
自發麵粉 self- raising flour
粗玉米豆粉 polenta / yellow cornmeal
粟粉/粟米粉/玉米粉/玉米澱粉 corn flour / cornstarch
生粉/太白粉/地瓜粉 potato starch / potato flour
樹薯粉/木薯粉/茨粉/菱粉/泰國生粉/太白粉/地瓜粉 Tapioca starch / tapioca flour
蕃薯粉/地瓜粉 sweet potato flour
馬蹄粉 water chestnut flour
葛粉 arrowroot flour
臭粉/胺粉/阿摩尼亞粉/嗅粉 powdered baking ammonia / carbonate of ammonia / ammonia bicarbonate / ammonia carbonate / hartshorn
發粉/泡打粉/泡大粉/速發粉/蛋糕發粉 baking powder
蘇打粉/小蘇打/梳打粉/小梳打/食粉/重曹 baking soda / bicarb ofsoda
塔塔粉/他他粉 cream of tartar
卡士達粉/蛋黃粉/吉士粉/吉時粉/ custard powder
卡士達/克林姆/奶皇餡/蛋奶餡 custard / pastry cream
蛋白粉 egg white powder?
粘米粉/黏米粉/在來米粉/在萊米粉/再來米粉 rice flour
糕仔粉 cooked rice flour
糯米粉 glutinous rice flour / sweet rice flour
鳳片粉/熟糯米粉/糕粉/加工糕粉 fried sweet rice flour / fried glutinous rice flour
綠豆粉 mung bean flour / tepung hun kwee
小麥胚芽/麥芽粉 wheat germ
小麥蛋白/麵筋粉 wheat gluten
鹼水/(木見)水 alkaline water/lye water/potassium carbonate
白礬 alum
硼砂 borax
石膏 gypsum
酵母/酒餅 yeast/ibu roti
麵包/麵飽 bread
土司麵包/吐司 toast
麵包糠/麵包屑 breadcrumbs
香草豆/香草莢/香草片/香子蘭莢 vanilla bean/vanilla pod
香草精/雲尼拉香精/凡尼拉香精 vanilla extract/vanilla essence
香草粉 vanilla powder
班蘭粉/香蘭粉 ground pandan/ground screwpine leaves/serbok daun pandan
班蘭精/香蘭精 pandan paste/pasta pandan
玫瑰露/玫瑰露精 rosewater/rosewater essence essence
杏仁粉 almond flour/almond mieal
皮屑 grated zest/grated rind
海苔粉 ground seaweed
黑蔗糖漿/糖蜜/甘蔗糖蜜 molasses
金黃糖漿 golden syrup
楓糖漿/楓樹糖漿/楓糖 maple syrup
玉米糖漿 corn syrup/karo syrup
葡萄糖漿 glucose syrup
麥芽糖漿 barley maltsyrup/maltsyrup
麥芽糖 maltose/malt sugar
焦糖 carmael
果糖 Efructos
乳糖 lactose
轉化糖 invert sugar
日式糙米糖漿 amazake
綿花糖霜 marshmallow cream cream
冰糖 ROCK sugar
椰糖/爪哇紅糖 palm sugar/gula malacca
黃砂糖 brown sugar
紅糖?/黑糖? dark brown sugar
紅糖?/黑糖? muscovado sugar
金砂糖? demerara sugar
原蔗糖 raw sugar/raw cane sugar/unrefined cane sugar
白砂糖/粗砂糖 white sugar/refined sugar/refined cane sugar/coarse granulated sugar
細砂糖/幼砂糖 castor sugar
糖粉 icing sugar/confectioners' sugar
糖霜/點綴霜 icing/frosting
蜜葉糖/甜葉菊 stevia/honey leaf
代糖/阿斯巴甜 aspartame/sweetener/sugar substitute
牛油忌廉 butter cream
巧克力米/朱古力米 chocolate vermicelli
巧克力削/朱古力削 chocolate curls
巧克力珠/朱古力珠 choc bits/chocolate chips
椰絲/椰茸/椰子粉 desiccated coconut/shredded coconut
涼粉/仙草 grass jelly
果子凍/果凍粉/(口者)喱 jelly
魚膠粉/吉利丁/明膠 gelatine sheets/powdered gelatine 
大菜/大菜絲/菜燕/燕菜精/洋菜/洋菜粉/瓊脂 agar agar powder
食用色素 food colouring
牛油/奶油/黃油 butter
瑪珈琳/瑪琪琳/乳瑪琳/雅瑪琳/人造奶油/菜油 margarine
起酥油/起酥瑪琪琳 pastry margarine / oleo margarine
豬油/白油/大油/板油? lard / cooking fat
酥油/雪白奶油 shortening
硬化椰子油 copha
烤油? dripping
淡忌廉 light cream/coffee cream/table cream
鮮奶油/忌廉/鮮忌廉 cream/whipping cream
包括﹕
1 light whipping cream
2 heavy whipping cream/heavy cream/thickened cream
3 double cream/pure cream
酸奶油/酸忌廉/酸奶酪/酸乳酪 sour cream
酸奶 buttermilk
牛奶/鮮奶/鮮乳 milk
奶粉 powdered milk / milk powder
花奶/淡奶/奶水/蒸發奶/蒸發奶水 evaporated milk
煉奶 condensedmilk/sweetened condensed milk
起士/起司/芝士/乳酪/奶酪/乾酪/乳餅 cheese
起司粉 powdered cheese
奶油起司/芝士忌廉/奶油乳酪/凝脂乳酪 cream cheese
瑪斯卡波尼起司/馬司卡膨起司/馬斯卡波涅起司/義大利乳酪 mascarpone cheese
優格/乳果/酸奶酪/酸乳酪 yoghurt
優酪乳 /酸奶yoghurt drink/drinking yoghurt
黃豆 soy bean
紅豆 red bean/adzuki bean
紅豆沙/烏豆沙 red bean paste
綠豆 mung bean
綠豆片 split mung bean
薏米 pearl barley
沙莪粒/西米/小茨丸 pearl sago/pearl tapioca
蓮藕 lotus root
蓮蓉 lotus paste
紅棗 chinese red dates
蜜棗 preserved red dates
棗泥 red date paste
龍眼乾/龍眼肉/桂圓/圓肉dried longan
葡萄乾 raisin
柿餅 dried persimmon
桃脯 dried peach
杏脯 dried apricot
蘋果脯/蘋果乾 dried apple
陳皮 dried orange peel/dried tangerine peel
百合 dried lily bulb
蜜漬櫻桃/露桃/車梨子 glace cherry/candied cherry
蜜漬鳳梨 glace pineapple/candied pineapple
腰子豆/腰果/腰果仁/介壽果 cashew nut
花生 peanut
瓜子/南瓜子 pepitas / dried pumpkin seeds
崧子/松子仁 pine nut
栗子 chestnut
栗蓉 chestnut puree / chestnut paste
核桃/核桃仁/合桃/胡桃 walnut
杏仁/杏仁片/扁桃 almond
北杏/苦杏仁 apricot kernel / chinese almond / bitter almond
南杏 apricot kernel
榛果/榛仁 hazelnut / filbert / cobnut
開心果/阿月渾子 pistachio
堅果/澳洲堅果/夏威夷果/澳洲胡桃/澳洲栗/澳洲核桃/
昆士蘭龍眼/昆士蘭栗macadamia / california nut
山胡桃/胡桃 pecan
石鼓仔/馬加拉/油桐子 candlenut / buah keras
白果/銀杏 ginkgo nut
檳榔 betel
芝麻 sesame seed
蓮子 lotus seed
罌粟子 poppy seed
亞答子 atap seed
法式吐司 french toast
裸麥麵包 rye bread
派/批 pie
塔/撻 tart
凍派/凍批 cream pie
蛋塔 egg tart / custard tart
法式蛋塔 quiche lorraine
戚風蛋糕 chiffon cake
海綿蛋糕 sponge cake
泡芙 choux pastry / puff
瑪琳/焗蛋泡 meringue
蛋蜜乳 eggnog
可麗餅 Ecrepe
煎餅/熱餅/薄烤餅 pancake
厚鬆餅 pikelet / hotcake
墨西哥麵餅 tortillas
曲奇 cookies
慕斯/慕思 mousse
布甸/布丁 pudding
司康/比司吉 scones
舒芙蕾 souffles
洋芋塊 hash brown
英式鬆餅/瑪芬 english muffin
鬆糕/瑪芬 american muffin 
格子鬆餅 waffle
蕃茄醬: ketchup
水蜜桃罐頭: peaches in syrup
切片水蜜桃罐頭: sliced peaches in syrup
綜合水果罐頭: cocktail fruit in syrup 
蘇打餅干: saltine crackers
白醋: rice vinegar (工研醋)
烏醋: black vinggar
辣椒醬: chili sauce
牛頭牌沙茶醬: bull head barbecue sauce/Chinese barbecue sauce
抹茶粉: green tea powder
餛鈍皮: wonton wrapper/wonton skins
水餃皮: dumpling wrapper / dumpling skins /gyoza wrapper.
春捲皮: spring roll wrapper , egg roll wrapper......
黑木耳: dried black fungus
燒海苔: roasted seaweed sushi nori
蝦米: dried shrimp
鹹蛋黃: salted egg yolk
杏桃果膠 apricot glaze
薑粉 ginger powder
耐烤巧克力豆 choc bits(澳洲的英文名) / chocolate chips(美國、加拿大的英文名?)
洋梨 pear
杏桃 apricot
無花果乾 dried fig
手指餅乾 sponge fingers / ladyfingers / savoiardi(義大利名)
蕃茄醬汁 tomato sauce(普通甜的)
蕃茄糊 tomato paste(義大利料理用的)
蕃茄醬 ketchup (沾薯條的那種)
白醋 white vinegar(西洋料理用的)
豆辦醬 chilli bean sauce
XO醬 XO sauce
桂圓 dried longan
黑木耳 black fungus / wood ear fungus
燒海苔 toasted nori seaweed
板海苔 nori seaweed / dried sea laver
南乳 fermented red beancurd
雜糧預拌粉 multi-grain flour
威化餅乾 wafer biscuit
細砂糖/幼糖 caster sugar
軟化牛油 soft butter
麵粉 plain flour
玉米粉 cornflour
自發麵粉 self-raising flour
乾椰絲 dessicated coconut
葡萄乾dried currant
糖份混合物 icing sugar mixture

又一天...

繼三"天"之後,又一家導航專業公司:精天
( 有規定 gps 就要有"天"嗎?)

以下是公司簡介摘錄:

本公司擁有陣容堅強的研發團隊,研發人員擁有豐富的汽車導航系統、多媒體影音系統與嵌入式作業系統及驅動程式整合經驗,能於很短時間內完成客戶委託之產品開發,並提供客戶完整的技術服務,更進一步協助客戶縮短產品及時上市的時程。...

所以不像是"貼牌"公司。

好像是作導航軟體的公司,不作hardware 和 platform。

2.05.2009

台灣流行音樂百張最佳專輯

Bookmark 一下:台灣流行音樂百張經典專輯

當年聽的歌。


  1. 之乎者也 羅大佑 羅大佑/阪部一夫 滾石 1982.4.21鹿港小鎮、戀曲1980
  2. 蘇芮專輯 蘇 芮 李壽全 飛碟 1983.6.18 一樣的月光、請跟我來
  3. 橄欖樹 齊 豫 李泰祥 新格 1979 橄欖樹、歡顏、走在雨中
  4. 天天天藍 潘越雲 李壽全 滾石 1982.8.14 天天天藍、守著陽光守著你
  5. 生命中的精靈 李宗盛 李宗盛 滾石 1986.1.23 生命中的精靈
  6. 向前走 林 強 陳昇/李宗盛/周世暉 滾石 1990.12.7 向前走、黑輪伯仔
  7. 龍的傳人 李建復 李壽全 新格 1980 龍的傳人、歸去來兮、曠野寄情
  8. 一無所有 崔 健 崔健/陳慶/王昕波 可登 1989.4.10 一無所有
  9. 未來的主人翁 羅大佑 羅大佑/王正華 滾石 1983.9.20 細亞的孤兒、現象72變、小妹
  10. 抓狂歌 黑名單工作室 王明輝/陳主惠 滾石 1989.11.7 台北帝國、計程
  11. 回 聲 齊豫/潘越雲 齊豫/王新蓮 滾石 1985.11.19 田
  12. 許景淳專輯 許景淳 鄧育慶 點將 1987.5 玫瑰人生、睡吧!我的愛
  13. 丘丘合唱團 丘丘合唱團 邱 晨 新格 1982 在今夜、為何夢見他
  14. 金韻獎第1輯 合 輯 黃克隆/姚厚笙 新格 1977 如果、小雨中的回憶
  15. 中國現代民歌集 楊 弦 楊 弦 洪建全文教基金會 1975.9 鄉愁四韻
  16. 大腳姐仔 陳小霞 陳小霞 科藝百代 1991.10.1 傀儡尪仔
  17. 此情可待 蔡 琴 吳楚楚 碟 1984.11.17 後一夜、讀你
  18. 紅螞蟻合唱團1 紅螞蟻合唱團 方龍泉/陳世興 喜馬拉雅1985.2愛情釀的酒
  19. 忙與盲 張艾嘉 李宗盛 滾石 1985.3.27 忙與盲
  20. 童 年 張艾嘉 羅大佑 滾石 1981.3.13 童年、光陰的故事
  21. 其實你不懂我的心 童安格 童安格/殷文琦 寶麗金 1989.3.13 其實你不懂我的心
  22. 跟你說、聽你說 陳淑樺 李宗盛/黃建昌 滾石 1989.11.2 夢醒時分、你走你的路
  23. 出塞曲 蔡 琴 鍾光榮 海山 1980.9 塞曲、抉擇
  24. 8又2分之1 李壽全 李壽全 飛碟 1986.8.1 張三的歌
  25. 認 錯 優客李林 韓賢光/李驥 點將 1991.10.2 認錯
  26. 陶大偉/孫越專輯 陶大偉/孫越 彭國華 滾石 1981.4.20 朋友歌、小精靈
  27. 這個世界 蔡藍欽 樓文中 飛碟 1987.6.6 這個世界
  28. 酒後的心聲 江 蕙 何慶清 點將 1992.10.2 酒後的心聲、藝界人生
  29. 情字這條路 潘越雲 李宗盛/陳揚/李壽全 滾石 1988.7.14 情字這條路、桂花巷
  30. 小雨來的正是時候 鄭 怡 李宗盛 拍譜 1983.9 小雨來的正是時候、結束
  31. 舊愛新歡 潘越雲 李宗盛 滾石 1986.9.15 謝謝你曾經愛我
  32. 我很醜,可是我很溫柔 趙 傳 沈光遠/羅紘武/羅希 滾石 1988.11.5 我很醜,可是我很溫柔
  33. 快樂天堂 滾石歌手 鄭華娟 滾石 1987.1.15 樂天堂
  34. 生老病死 薛 岳 薛 岳 新笛 1990.8.23 如果還有明天
  35. 你是我所有的回憶 齊 豫 李泰祥 金聲 1983 是我所有的回憶
  36. 下午的一齣戲 陳明章 李欣芸/林暐哲 滾石 1990.12.4 下午的一齣戲
  37. 堅固柔情 羅紘武 羅紘武 滾石 1989.2.15 堅固柔情
  38. 擁擠的樂園 陳 昇 陳 昇 滾石 1988.5.5 擁擠的樂園
  39. 一千個春天 蔡琴/李建復 李壽全 四海 1981 跟我說愛我
  40. 柴拉可汗 李建復 李壽全 四海 1981 天水流長
  41. 蛻 變 張洪量 張洪量 滾石 1990.12.21 美麗的花蝴蝶
  42. 愛人同志 羅大佑 羅大佑 滾石 1988.12.9 戀曲1990
  43. 驀然回首 蘇 芮 曹俊鴻 飛碟 1984.1.20是不是這樣、心痛的感覺
  44. 變色的長城 費玉清 何慶清 尼 1981.4 變色的長城
  45. 鄧麗君 鄧錫泉 歌林 1983.1 但願人長久、獨上西樓
  46. 天 梯 薛 岳 薛 岳 拍譜 1985.6 機場、溫柔的拒絕
  47. 梳子與刮鬍刀 李麗芬 張炳輝/陳玉正 喜馬拉雅 1986.7城市英雄
  48. 讓我一次愛個夠 瘐澄慶 瘐澄慶 福茂 1989.7 讓我一次愛個夠、整晚的音樂
  49. 楊三郎紀念專輯 陳芬蘭 紀氏音樂 吉馬 1992.6望你早歸、港都夜雨
  50. 家 羅大佑 羅大佑 滾石 1984.10.18 家
  51. 愛上一個不回家的人 林憶蓮 陳秀男 飛碟 1990.12.29 愛上一個不回家的人
  52. 胭脂北投 潘越雲 李壽全 滾石 1983.2.9 野百合也有春天
  53. 馬不停蹄的憂傷 黃舒駿 楊明煌/黃舒駿 歌林 1988.3 馬不停蹄的憂傷
  54. 歲月的歌 周治平 周治平 寶麗金 1992.3.6 蘇三起解
  55. 徐曉菁/楊芳儀專輯 徐曉菁/楊芳儀 李國強 新格 1981 就要揮別、聽泉
  56. 雁渡寒潭 黃舒駿 楊明煌/黃舒駿 歌林 1989.3 戀愛症候群、她以為她很美麗
  57. 桂花巷 潘越雲 陳 揚 滾石 1987.9 桂花巷
  58. 葉佳修專輯 葉佳修 鍾光榮 海山 1979 踏著夕陽歸去、思念總在分手後
  59. 偈 王海玲 李壽全 新格 1980 、當你生日
  60. 兒童樂園 郭 子 王明輝/陳主惠 新笛 1991.4.9 關於離別
  61. 頂尖拍檔 頂尖拍檔 瘐澄慶/頂尖拍檔 福茂 1992.5 快樂song
  62. 愛上別人是快樂的事 吳俊霖(伍 佰) 羅 希 魔岩 1992.8.13 愛上別人是快樂的事、樓仔厝
  63. 搖滾舞台 薛 岳 李宗盛 拍譜 1984.4 搖滾舞台
  64. 平 凡 黃韻玲 李琳/黃韻玲 滾石 1991.9.6 關不掉的收音機、三個人的晚餐
  65. "葬心"阮玲玉電影配樂 黃鶯鶯/小蟲 小 蟲 滾石 1991.12.30 葬心
  66. 一場遊戲一場夢 王 傑 李壽全 飛碟 1987.12.19 一場遊戲一場夢、安妮
  67. 心 情 鄭 怡 曹俊鴻 可登 1987.10.5 心情、敲痛我的心
  68. 唐 朝 唐朝樂隊 賈敏恕 滾石 1992.11.8 夢回唐朝、國際歌
  69. 讓每個人都心碎 黃大煒 樓文中 可登 1990.10.22 讓每個人都心碎
  70. 浮世情懷 鳳飛飛 陳揚/羅大佑/黃霑 真善美 1991.2追夢人、心肝寶貝
  71. 包美聖之歌 包美聖 黃克隆/姚厚笙 新格 1980 捉泥鰍、看我聽我
  72. 讓我歡喜讓我憂 周華健 周華健/劉志宏/張弘毅 滾石 1991.11.28讓我歡喜讓我憂、你現在還好嗎
  73. 狼 齊 秦 不詳 綜一 1985.5 狼、原來的我、啞口
  74. 灼熱的生命 薛 岳 薛岳/陶曉清/楊嘉 新笛 1991.11.7 薛岳過世前的演唱會紀實
  75. 新寶島康樂隊 陳昇/黃連煜 陳昇/黃連煜 滾石 1992.7.31 多情兄、壞子
  76. 夢駝鈴 費玉清 劉亞文 東尼 1984.3夢駝鈴、挑夫
  77. 四 季 娃娃 羅大佑/花比傲/林夕 滾石 1992.11.11 如今才是唯一
  78. 祭 文 張洪量 楊良智/陳聲/張洪量 喜馬拉雅 1987.9.5 祭文
  79. 原 鄉 羅大佑 羅大佑 滾石 1991.9.26 火車、大家免著驚
  80. 王芷蕾的天空 王芷蕾 陳復明 飛碟 1985.3.13 台北的天空
  81. 心事誰人知 沈文程 蔡振南 愛莉亞 1982 心事誰人知
  82. 只有分離 黃鶯鶯 何慶清 寶麗金 1983 只有分離、相思
  83. 想要彈同調 鳳飛飛 何慶清 科藝百代 1992.8.25 想要彈同調、阮若打開心內的門窗
  84. 鄭怡/王新蓮/馬宜中 同前 李國強 新格 1981 月琴、匆匆的走過
  85. 三百六十五里路 文 章 譚健常 四海 1984.10 三百六十五里路
  86. 我要的不多 馬兆駿 馬兆駿/呂曉棟 滾石 1987.9.19 我要的不多
  87. 我是不是你最疼愛的人 潘越雲 小 蟲 滾石 1989.9.12 我是不是你最疼愛的人
  88. 少年A,安啦! 林強/伍佰等 王治平/林強/羅百吉 魔 1992.6.2 無聲的所在、電火柱仔
  89. 施孝榮專輯 施孝榮 李國強 新格 1981 拜訪春天、中華之愛
  90. 光 芒 張清芳 曹俊鴻 點將 1992.12.11 出嫁、Men's talk
  91. 不只是朋友 黃小琥 孫建平 可登 1990.6.4 不只是朋友
  92. 天使之戀 黃鶯鶯 馬兆駿 寶麗金 1983 時空寄情、沙漠之足、天使之戀
  93. 愛的代價 張艾嘉 陳昇/李宗盛/周世暉 滾石 1992.16.12愛的代價、這樣愛你對不對
  94. 唐曉詩專輯 唐曉詩 李泰祥 滾石 1983.5.25告別、小木屐
  95. 愛要怎麼說 伍思凱 黃大軍 可登 1988.9.23 要怎麼說
  96. 心的方向 周華健 李宗盛 滾石 1987.7.13 心的方向
  97. 激情過後 張清芳 何慶清 點將 1985.10 激情過後、這些日子以來
  98. 老么的故事 鄭智化 陳 揚 點將 1988.12 老么的故事
  99. 洪榮宏專輯3 洪榮宏 黃 敏 光美 1983 一支小雨傘
  100. 私 奔 陳 昇 陳 昇 滾石 1991.8.14把悲傷留給自己

Google Latitude

Google 又有新玩意:Latitude
看 Video 介紹好像是前陣子 Yahoo 的 FireEagle 那樣的 Geo Info Aggregator.

可以讓其他人知道你目前的位置,也可以弄出一個 list,知道你過去...的位置。

有一個 Video 還特別講到 Privacy 問題,解法大概是..,你可設定 誰 可以知道你的資料...

上面寫到 手機 不一定需要 gps,他可以利用 註冊 基地站 的資料,PC 的話,就是用 ip address (所以可以用 Proxy 來改變位置...)。

在下一版的 Android 會是標準配備 (軟體 ) 喔。


現在知道 Google 推 Android 的原因了.. Yahoo 的 FireEagle 稿這麼久,沒有起色。
像 Google 這樣,內建在 Android 中,所有有Android 的人都會用,(大概)一下子就推廣開來了。

這個新聞我是在 這裡 看到的。
這裡 有中文的介紹。

2.04.2009

經濟退之後 --- 犯罪率要增加了!

糟糕,朱學恆 預知到,接著 犯罪率就要增加了

他是從台北市 塗鴉 的數量大幅度的增加 判斷的。

這也真的代表那些低區真的很少人在管。

2.03.2009

Command mode subversion client

TotoriseSVN的新版問題很多,像 branch 會有 file already exist error (有時候),還有網路很忙時,checkout 大量會自動中斷。

所以還是用 command mode 來輔助好了...

這裡 去 download subversion command-line client..

2.02.2009

ATOM 的 PND

ATOM 的 PND 終於(開始)出現了:

Clarion MiND

從外觀看來真的是猜不到是 x86。

$650 - 果然是 netbook 等級的價格.
有人說他要program PT6961,但是看不懂中文,所以我自己翻譯一下

PT6961 can be controlled by MCU via a bus similiar to SPI interface (SDI/SDO/CLK/CS).
The 7-seg display and keyboard is implemented by scaning the hardware pin.

The "SPI" protocol:
The 1st byte is command, and the proceeding N bytes are datas (IN/Out).
The highest 2 bits of Command byte are Command Index, the remainding bits are the command content.
All the data bytes behind the Command byte are Data.

Command 1: Display Mode Setting

There are 18 control lines for controlling 7-seg display, so can drive 6 digits + 12 segment and 7 digits + 11 segments, 2 types of 7-seg.


Command 2: Data Setting Command

用來讀寫PT6961內部的memory (register ?)。用一個bit來決定是Read還是write。
Command之後就是Data (in/out)。
Read Command代表讀取Scan Key的內容,
KeyScan一次Scan K1,K2,K3三個key。
Scan Line有SG1 - SG10。
Read Data依照Scan的內容,每一個byte只有用到前6個bit,代表兩個Scan Line。
所以keyscan總共有5個byte。
Write Command代表寫入七段顯示輸出記憶體
一個七段顯示器需要12個bit,使用2個byte。
所以write command使用的memory有 7 x 2 = 14 byte


Command 3: Address Setting Command

Set the memory address for displaying.
顯示memory也是一樣,因為PT6961支援一個digit最多支援12 segment。
所以memory一個digit需要2個byte (16 bit),但是最高4 bit不使用。只用12 bit.

Command 4: Display Control Command

Turn On/Off the scanning operation for 7-seg display.
Set the duty cycle (to adjust the brightness)


Sample Code from PTC :
Command 0x03 1 : 7 digit 11 seg
Command 0x8F 4 : Display On, Pulse width 14/16
----clear ram----
Command 0x40 2 : Normal, Increment, Write to disp
Command 0xC0 - Data 0x00 repeat 14. 3 : write 14 datas to ram, start from 0
----load---------
Command 0x44 2 : Normal, Fix, Write to disp
----address:data set
Command 0x44 2 : Normal, Fix, Write to disp
Command Addr - Data Data
-0xC0 : 0x38 write 0x38 on 0
-0xC2 : 0x18 write 0x18 on 2
-0xC4 : 0x38 write 0x38 on 4
-0xC6 : 0x2C
-0xC8 : 0x3C
-0xCA : 0x1C
-0xCC : 0x30
REPEAT 4 Times
----set ram
Command 0x40 2 : Normal, Increment, Write to disp
Command 0xC0 Data 0xFF repeat 14 3 : Write 14 0xFF to disp starts from 0
----read key
Command 0x42 Read Data repeat 4 2 : Normal, Increment, Read 4 data.


spec的recommand algorithm:
Command 2
Command 3 Clear Memory
Command 1
Command 4 Disp OFF
Command 1
Command 4 Disp ON
Loop -
Command 2 Write Data
Command 3
Command 1
Command 4


It has no response when using PIC's internal SPI controller to communicate to PT6961, so I use GPIO to control, it's OK:

The code do Initialization:

void Pt6961Init(void)
{
char i;

STB=1;
SCL=1;

// command 2 : memory r/w, address inc
STB=0;
sout(0x40);
STB=1;

// command 3 : address set, and data
STB=0;
sout(0xC0);
for(i=0;i<14;i++)
sout(0x00);
STB=1;

// command 1 : display mode : digit & seg
STB=0;
sout(0x02);
STB=1;

// command 4 : disp on/off, disp duty
STB=0;
sout(0x87);
STB=1;

// command 1 : display mode
STB=0;
sout(0x02);
STB=1;

// command 4 : disp on/off, disp duty
STB=0;
sout(0x8F);
STB=1;

}

the sout function :

void sout(char data)
{
char i;
for(i=0;i<8;i++){
SCL=0;
SDO = data&0x01;
SCL=1;
data = data >> 1;
}
}

The code to send data to LED:

void LedPrint(char *str)
{
char data;
char i=0;

// command 2
STB=0;
sout(0x40); // write mode, auto inc address
STB=1;

// command 3
STB=0;
sout(0xC0); // set write start address=0
sout(str[0]); // 1st digit
sout(0x00); // 1 digit occupy 2 bytes
sout(str[1]); // 2nd digit
sout(0x00);
sout(str[2]); // 3rd digit
sout(0x00);
STB=1;
}

The Codes to Read KeyScanCode: data[5] is the result, only the heading 6 bits in each byte are effective.

// Read
STB=0;
sout(0x42); // read mode, auto inc address
data[0]=sin(); // read in 1st scan line only 0-5 useable
data[1]=sin(); // 2nd
data[2]=sin(); // 3rd
data[3]=sin(); // 4th
data[4]=sin(); // 5th
STB=1;

sin() 是

char sin(void)
{
char i;
char rc=0;

for(i=0;i<8;i++){
SCL=0;
rc = rc>>1;
SCL=1;
if(SDI)
rc |= 0x80;
}

return rc;
}



So, there are something wrong in the datasheet..
這一顆chip的protocol是固定將STB Low後第一個byte作Command,之後的都是Data,所以在任何Command後都可以加Data。 至於Data的動作就由上次Command 2的Read/Write bit來決定是Read Data或是Write Data。
如果是Write Data,Write Target Address就依照上次 Command 2中address auto increment bit的狀態跟Command 3 : target address的設定值決定。