• 沒有找到結果。

程 式 設 計 流 程

N/A
N/A
Protected

Academic year: 2021

Share "程 式 設 計 流 程"

Copied!
26
0
0

加載中.... (立即查看全文)

全文

(1)

第六章 系統軟體設計-嵌入式電腦語音溝通 系統和替代性輸入裝置軟體

本章將介紹自訂的嵌入式電腦語音溝通系統和替代性輸入裝置軟體程式的 設計概念及相關功能的說明,包括程式設計流程,軟體版面設計,輸入法設計和 聲音檔設計。圖 6-1 為系統軟體架構圖。

程 式 設 計 流 程

軟 體 版 面 設 計

輸 入 法 設 計

聲 音 檔 設 計 系統軟體

嵌入式電腦語音溝通 系統和替代性輸入裝置 系統初始化 軟體設計概念

圖 6-1 系統軟體設計之嵌入式電腦語音溝通系統和替代性輸入裝置架構圖

(2)

接著介紹本系統的程式設計流程,如圖 6-2:

進入起始點函式(WinMain)

印表機埠初始化 (ParPortInit)

註冊視窗類別

接收到 WM_LBUTTONDOWN 訊息,

呼叫(DoLButtonDownMain)函式。計算 出觸控面板之 x-y 座標並呼叫

(InvalidateRect)函式,負責通知 (DoPaintMain)函式將畫面重畫。

MainMessages table 將不斷被掃 瞄。SetTimer 函式將於每 0.01s 執行 WM_TIMER 訊息而呼叫 (DoTimerMain)函式,主要檢查 CheckKeybrd 副程式,測試電腦 端是否有信號傳送至系統。

按鍵是否被 按下 程式開始

執行

主視窗訊息被傳送到(MainWndProc)函式。訊 息不斷被掃瞄。若有,則呼叫相對應的副程式 或函式,因此它是整個程式的中心。

自動接收到 WM_SIZE 訊息,執行 (DoSizeMain)函式,將矩陣之值初始化。

自動接收到 WM_PAINT 訊息,呼叫(DoPaintMain) 函式。進行圖形的繪製。語音輸出和鍵盤按鍵碼 資料的送出也透過此函式的觸發而被執行。

自動接收到 WM_CREATE 訊息,

呼叫(DoCreateMain)函式,

執行 SetTimer(hWnd,1,10,NULL)

圖 6-2 系統程式主要流程圖

(3)

一、程式設計流程

首先從 WinMain 函式入口,它會分別傳入四個變數,為 HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow。

hInstance 為讓 Windows API(Application Programming Interface)辨識此指定程式 有別於其他應用程式的特定情況,hPrevInstance 則是保留讓舊式 Win16 API(Windows 3.1 等)使用,因此在 Win32 作業系統(包含 Windows CE),

hPrevInstance 的值多為 0,也可被忽略,lpCmdLine 主要是指到一具有 command line 文字的 Unicode 字串,其目的主要是容易分辨出此執行程式是在 Windows CE 下,因此在其他 Windows 版本下,該字串皆為 ASCII 字串。此變數也可稱為 command-line parameter,而最後一個變數 nCmdShow 有三種允許的狀況:

SW_SHOW、SW_HIDE、SW_SHOWNOACTIVATE(Show without activate),主要 是明確指定程式的主要視窗畫面的開始狀況[29]。

當視窗初始值設定完畢後,進入到 ParPortInit 副程式。此副程式主要是設定 印表機埠的初始值,因為系統印表機埠的 I/O 位子為 278H,因此我們將印表機 埠位子變數設定為 278H,而印表機埠的狀態地址(Status Address)則在 278H+1 的 位子。設定完畢後,我們將進入到 InitInstance(hInstance, lpCmdLine, nCmdShow) 函式。此函式將會呼叫 RegisterClass 註冊一視窗類別,其中第二個變數

WNDPROC lpfnWndProc 為最主要的屬性,它指定了視窗的 window procedure 地

址。當視窗類別記錄完畢,主視窗就可被產生了,此時 InitInstance 將結束。

(4)

回到 WinMain 後,將進入 GetMessage 執行訊號迴圈。它將會在應用程式的 訊息儜列裡拿接下來的訊息。若沒有訊息,則會等待,直到取得新訊息為止。

TranslateMessage 函式是將透過鍵盤或觸控面板所傳回的訊息轉換成字串訊息,

而 DispatchMessage 函式則告訴 Windows 將訊息轉送到合適的視窗。這時訊息將 會被傳送到 MainWndProc 進行處理。

第一個自動被處理的函式是 DoSizeMain,接著 DoCreateMain 函式也會被呼 叫,它主要是執行 SetTimer(hWnd,1,10,NULL)函式,其中第三個變數值 10 表示 每 0.01s 執行第四個變數指到的函式,而第四個變數 NULL 表示預設值指到(訊 息 WM_TIMER)DoTimerMain 函式,此函式只執行 CheckKeybrd 副程式,其功能 為測試電腦端是否有信息需傳送至系統。表 6-1 為 CheckKeybrd 副程式的程式片 段。

void CheckKeybrd() {

byte cpu_cmpdata, Test_DataFromCPU=0;

cpu_cmpdata = CheckStatusPort(0x28); //change 0010 1000 bit3 為 clock if (cpu_cmpdata == 0x08) //0000 1000

{ //cpu_clock=1, cpu_data=0

DataFromCPU = ReceiveDataFromCPU();

switch(DataFromCPU) {

case 0xF6:

Send_KbCode(wordData[1676].linkArr[0]->makecodelist[0]); //KeyACK break;

case 0xFF: //System reset

CPU_ClockTesting();//送按鍵之前測 clock 是否等於 1

Send_KbCode(wordData[1676].linkArr[0]->makecodelist[0]); //KeyACK CPU_ClockTesting();//送按鍵之前測 clock 是否等於 1

LongDelay(1000);

Send_KbCode(wordData[1678].linkArr[0]->makecodelist[0]); //KeyNormal LongDelay(2000);

break;

. . }//switch

}//if }

表 6-1 測試電腦端信號傳送之程式片段

(5)

印表機的 278h、279h 及 27Ah 分別為其資料埠(Data Port)、狀態埠(Status Port) 及控制埠(Control Port)。本系統的程式裡只用了資料埠和狀態埠。因此在執行是

CheckStatusPort 副程式如表 6-2 時,透過_inp 可以讀到 PrtStatAddr(Status Port) 位置之值,和變數 cpu_data(0x28)作 AND 的動作。0x28 主要是讓 clock 和 data 信號為 1,再和收到之資料做比較,接著將比較之資料送回到 CheckKeybrd 副程 式。

接著 if (cpu_cmpdata == 0x08)就判斷讀入之時脈信號是否為 1,若是,則表 示電腦端有資料需傳送到系統端。此時就進入到 ReceiveDataFromCPU 副程式,

如表 6-3。

byte CheckStatusPort(byte cpu_data) {

byte cpu_ReadData;

cpu_ReadData = _inp(PrtStatAddr); //從 279h 讀資料回來 cpu_ReadData &= cpu_data; //把讀回來的資料跟 data 做 AND return cpu_ReadData;

}

表 6-2 從電腦端讀入時脈和資料信號

byte ReceiveDataFromCPU(){

int r;

byte cpu_cmpdata, MaskKey;

ReceiveData = 0x00;

for(r=0;r<8;r++){

cpu_cmpdata = CheckStatusPort(0x28);

if ((cpu_cmpdata & 0x20) != 0){ //data=1, clcok 不一定要 1,0010 x000 MaskKey = 0x01;

MaskKey = MaskKey << r;

} else

MaskKey = 0;

ReceiveData += MaskKey;

KeyboardClock();

}//for r

//Parity bit ignored KeyboardClock();

ParPortOut(0);

KeyboardClock();

ParPortOut(1);

return ReceiveData;

}

表 6-3 從電腦端接受資料

(6)

for 迴圈裡將 8 次收到的資料存入 ReceiveData 變數,時脈的產生主要是靠 KeyboardClock 副程式。這時,根據表 6-1 就進入到判斷從電腦端接受的資料為 什麼 command。電腦端所提供之 command 有 KeyACK( 0xFA)、KeyRESET(0xF

F)、KeyNormal(0xAA)等,不同的 command 需回傳的資料也不一樣,不過都是 透過 Send_KbCode 副程式傳送。

接著自動執行的函式則是 DoPaintMain。執行完畢後,將會進入 MainMessage

table 等待按鍵的觸發。若有合適的訊息則進入該副程式,若無合適訊息則每 0.01s 執行 DoTimerMain 函式,否則將進入 DefWindowProc,它是 Windows 所提供進 行預設動作的副程式。

當觸控螢幕被按下後,將會進入到 MainMessage table 中的

DoLButtonDownMain 函式。它的功能除了計算出被按下的版面位址外,也會以 InvalidateRect 函式去呼叫 DoPaintMain 進行前景(foreground)重畫(refresh)的動 作。

在 DoPaintMain 裡我們可以發現有幾個特別的函式是 Windows CE 程式設計 軟體在畫視窗畫面時需要呼叫到的,例如 GetClientRect、BeginPaint 和 EndPaint。

當一視窗要被畫出時,首先要確定的是視窗的大小。在標準 Windows 程式裡,

標準視窗可分為兩部份,第一部份為非使用者區(nonclient area),另一部份則為

使用者區(client area)。視窗的邊框(borders)、捲軸條(scroll bars)和各種其他控制

(controls)組成了非使用者區而這部份是由視窗管理員(window manager)負責完

(7)

成。至於使用者區則是位在非使用者區裡面的中央空間,這部分則是應用程式應 該負責完成的部份。因此我們呼叫了 GetClientRect 函式,它將回傳一 RECT 結 構的資料,其中包括區域的左、右、上、下界線。接著我們需要 BeginPaint,藉 著回傳 hdc(Handle to a device context)我們才可利用它對視窗進行繪圖的動作。所 謂 device context,它是一個 physical display device(例如螢幕或印表機)的代表,

因為我們無法直接對硬體進行控制,因此需透過制定的裝置內容進行。

至於 DoPaintMain 結束後所執行的繪圖指令,則透過 Drawing 此副程式去呼 叫,例如呼叫 Draw_Main 副程式畫出首頁,呼叫 Play_Chinese_Voice 副程式播放 音樂,呼叫 sendkey_process 副程式進行圖形按鍵的輸出等。

表 6-4 的程式片段能正確的判斷圖形按鍵該落在首頁或分頁的版面,其主要 以 Page 這個被初始化為-1 值的整數變數進行版面的判斷。第一行 First_Time 變 數是判斷第一次系統啟動軟體時該執行 Draw_Main 副程式以畫出首頁版面,剩 餘的 Draw_Page 和 Clr_Screen 則是畫出其他分頁的副程式和清除整個螢幕的副 程式。最後倒數的三行則是該圖形按鍵不為畫面切換按鍵,而是該送資料之按 鍵,此時就會進入到 Play_Chinese_Voice 副程式。

每個按紐的資料結構設計主要分成首頁的圖形按鍵設計和其餘分頁的圖形 按鍵設計。不過每個圖形按鍵的位置判斷則是靠表 6-5 的 Mouse_final 這個變數。

有了它,我們就能確定該圖形按鍵在版面上的正確位置。因此,Page 變數配合

上 Mouse_final 變數,就能正確的找到圖形按鍵的相對位置。

(8)

表 6-4 的 Draw_Main 和 Draw_Page 副程式之繪圖功能非常類似,但由於 Draw_Main 不需傳入版面的所在位置值,而 Draw_Page 是負責畫出其他除了首

if (First_Time == true) //第一次畫首頁, 不用 button#

Draw_Main(hdc,0);

else //

{

if ((Mouse_final < 49) && (Page == -1))//在首頁按下後要判斷跳到哪個盤面 {//除了從首頁切換盤面到非首頁, 還有是在非首頁發聲

Clr_Screen(hdc,hWnd);

Draw_Page(hdc,MainPage_Order[Mouse_final-1] ,0);

Page = MainPage_Order[Mouse_final-1] ; }

else

if (Mouse_final == 54)//首頁 {

Clr_Screen(hdc,hWnd);

Draw_Main(hdc,0);

Page = -1;

} else

if (Mouse_final == 55) //上一頁 {

if (Page == -1) Page = -1;

else

if (Page == 0) //要換到首頁的顯示 {

Clr_Screen(hdc,hWnd);

Draw_Main(hdc,0);

Page = -1;

} else {

Page = Page - 1;

Draw_Page(hdc,Page,0);

} } else

if (Mouse_final == 56)//下一頁 {

if (Page < 31) //還有畫面 若有 4 個畫面, (Page < 3 ) {

Page = Page + 1;

Clr_Screen(hdc,hWnd);

Draw_Page(hdc,Page,0);

} } else

if ((Mouse_final < 54) && (Page != -1))

Play_Chinese_Voice(hInst,Mouse_final,Page);

}

表 6-4 版面切換之程式判斷

Mouse_x = pt.x/100 ; Mouse_y = pt.y/80 ;

Mouse_final = (Mouse_y * 8) + (Mouse_x + 1);

表 6-5 觸控按鍵座標轉換方式

(9)

頁的畫面,因此將其兩個副程式分開宣告。因此,若該頁為首頁,則透過呼叫表

6-6 的 Main_table 矩陣資料以繪出對應圖形,其中 bitmapindex[50]字元矩陣變數 表示可存放之檔案名稱長度為 50,Main_table[41]為首頁之圖形按鍵數,表示共 有 41 種情境類別。若該頁為分頁,則進入到 Play_Chinese_Voice 副程式以便進 行聲音檔的輸出和按鍵碼的傳送。

但我們發現,在 eMbedded Visual C++裡,顯示一張圖形的方式並不如桌上 型的 Visual C++那麼容易。表 6-7 宣告了在嵌入式系統進行繪圖時需要用到的內 建函式。

表 6-7 繪圖函式宣告表

struct Bitmap_Info {

TCHAR bitmapindex[50];

};

struct Bitmap_Info Main_table[41]=

{

TEXT("Hard Disk\\res\\m_jialirenwu.BMP"), //家裡人物 TEXT("Hard Disk\\res\\m_jialijiaju.BMP"), //家裡家具

. . . }

表 6-6 首頁之圖形按鍵矩陣

HBITMAP hbm; //handle to a bitmap HBITMAP hbmT;

HDC hdcMem = CreateCompatibleDC(NULL);

BITMAP bm;

TCHAR *TmpBitmap;

TmpBitmap =Main_BPNList[Page_Number].List[Button_Count++].bitmapindex;

hbm = SHLoadDIBitmap(TmpBitmap);

hbmT = SelectBitmap(hdcMem,hbm);

GetObject(hbm,sizeof(bm),&bm);

BitBlt(hdc,nX,nY,bm.bmWidth,bm.bmHeight,hdcMem,0,0,SRCCOPY);

SelectBitmap(hdcMem,hbmT);

DeleteDC(hdcMem);

(10)

首先宣告了兩個以 HBITMAP 結構為主的變數,HBITMAP 為 bitmap 的

handle。CreateCompatibleDC(NULL)主要是產生一個與目前螢幕相容的記憶裝置 內容(memory device context )並放入 hdcMem 這個 DC 的 handle,因為 bitmap 在 被選擇的過程中,它所要求的顏色必須符合裝置(螢幕)可用的顏色,唯有在這個 動作完成以後,bitmap 才能呈現於螢幕上。一旦透過函式建立了記憶裝置內容 後,就可利用 SHLoadDIBitmap(TmpBitmap)將指定的 bitmap 檔案載入,並將

bitmap 的 handle 回傳到 hbm 變數裡。接著 hbmT = SelectBitmap(hdcMem,hbm) 的 SelectBitmap 將會把新的 bitmap handle 放到記憶 DC 裡。而

GetObject(hbm,sizeof(bm),&bm)主要是希望取得 hbm 所指的 bitmap 的資料,&bm 指到一存放 bitmap 資料的緩衝區。到目前為止,bitmap 仍然還未顯示在螢幕上,

必須透過 BitBlt,它會將 hdcMem 所指到的 bitmap 彩色資料(color data)轉換至 hdc 上。當 bitmap 顯示完畢後,我們必須執行 SelectBitmap(hdcMem,hbmT),因為它 會將原來的 bitmap 選擇狀態儲存到記憶裝置內容(memory DC)。最後的步驟則是 執行 DeleteDC(hdcMem)將記憶裝置內容(memory DC)釋放出來。

接著將進入到 Play_Chinese_Voice 副程式。圖形按鍵之位置和頁數

(Mouse_final 和 Page)變數也會同時被傳入以進行判斷。表 6-8 提供的音樂儲存之

資料結構和表 6-9 之音樂矩陣結合,加上圖形按鍵位置和頁數的轉換(temp =

(48*Page) + Mouse_final),就可正確的讀到相對應的聲音檔和按鍵碼。

(11)

Wave_Number 表示某圖所具有的總共音個數,waveindex 則儲存了聲音檔的 存放地方和檔名。

表 6-9 之 IDR_List 矩陣變數共有 1580 筆資料,矩陣的第一個變數 2 表此圖 形按鍵共有兩個音,其檔名為@@o1f 和@l@2f。當確定了被按下圖形按鍵的聲 音檔後,就可呼叫內建的 PlaySound 函式將指定的聲音檔播放出來。接著進入到 傳送按鍵從系統至電腦端的 sendkey_process 副程式,temp 變數也將會被傳入至 sendkey_process 副程式。

struct Wave_Node_List IDR_List[1580] = {

{2,TEXT("Hard Disk\\Wave\\@@o1f"),TEXT("Hard Disk\\Wave\\@l@2f")}, //阿姨 {2,TEXT("Hard Disk\\Wave\\0@o4f"),TEXT("Hard Disk\\Wave\\0@o3f")}, //爸爸

. . . }

表 6-9 音樂儲存之矩陣

struct Wave_Node_List {

int Wave_Number;

TCHAR waveindex1[23];

TCHAR waveindex2[23];

TCHAR waveindex3[23];

TCHAR waveindex4[23];

TCHAR waveindex5[23];

TCHAR waveindex6[23];

TCHAR waveindex7[23];

TCHAR waveindex8[23];

};

表 6-8 音樂儲存之資料結構

(12)

進入 sendkey_process 副程式之後,我們需要先確定該圖形按鍵的長度,接 著透過鍵盤時脈將資料傳送至電腦端(或從電腦端接收資料),表 6-10 和 6-11 解 釋了按鍵之資料結構。

表 6-10 是每個鍵盤按鍵(例如 a、b、ㄅ)都具有各自獨立的按鍵碼(makecode 和 breakcode),而 Code_Struct 這個資料結構定義了四個以 byte(8 bits)大小變數儲 存的鍵盤按鍵碼資料,例如 a 的 makelen 儲存的是 1,因為 a 的 makecode 長度為

1,而 makecodelist 是指到一個儲存 a 的 makecode 的指標,該指標會對應到相對 的 16 進位鍵盤按鍵碼(1CH 為 a 的 makecode),如表 6-11。

表 6-12 單一圖形按鍵碼之資料結構 表 6-10 鍵盤按鍵(單鍵)之資料結構

typedef struct KB_STRUCT {

byte makelen; // make code 的長度 byte *makecodelist; // make code 的內容 byte breaklen; // break code 的長度 byte *breakcodelist; // break code 的內容 }Code_Struct;

typedef struct KB_Word_STRUCT{

int num_of_word;

Code_Struct *linkArr[MAX_MAKE_NUM];

}Word_Struct;

Word_Struct wordData[KEY_NUM];

表 6-11 鍵盤按鍵(單鍵)之矩陣

Code_Struct codedata[CODE_NUM] = {

{ 1, &makecode[0], 2, &breakcode[0] }, //000 1,ㄅ,s_!

{ 1, &makecode[1], 2, &breakcode[2] }, //001 q,ㄆ

.

.

.

}

(13)

Word_Struct wordData[KEY_NUM]=

{

{ 7, &codedata[24], &codedata[37], &codedata[0], &codedata[21], &codedata[39], &codedata[39], &codedata[48]},//阿姨 { 7, &codedata[0], &codedata[24], &codedata[41], &codedata[4], &codedata[54], &codedata[0], &codedata[48]},//爸爸

. . . }

表 6-12 的資料結構包含了一個圖形具有的文字個數,和其多個按鍵碼資料 的連結。接著系統將呼叫 Send_KbCode 副程式進行按鍵碼傳送,這時將會在

wordData 矩陣裡找到對應圖形的鍵盤按鍵碼,如表 6-13。其中 KEY_NUM 為系 統所有圖形數,預設為 2000 張圖,資料的第一欄 7(num_of_word)為該圖形所包 含的鍵盤按鍵碼個數。

表 6-13 圖形之鍵盤按鍵碼

當系統確定了按鍵碼個數後,則進入到 codedata 指標矩陣,其第一個和第三

欄位表該按鍵碼之 makecode 和 breakcode 的長度,*makecodelist 和*breakcodelist

則分別指到兩個放了鍵盤按鍵碼資料的 16 進位矩陣。圖 6-3 就是系統圖形之鍵

盤按鍵碼的資料結構分析圖。

(14)

鍵盤按鍵碼的傳輸透過資料線和時脈線,在此我們將展示程式如何完成控制 印表機埠以傳送資料的部份。首先我們判斷從 makecode 或 breakcode 矩陣所取 得的十六進位資料其 8 個 bits 為 0 或 1,我們以表 6-14 的程式表示之。

byte makecode[MAKE_NUM] = {

0x16, //000,000/099. 1,ㄅ,s_!

0x15, //001,001/099. q,ㄆ .

. . }

byte breakcode[BREAK_NUM] = {

0xF0, 0x16, //000,000/192. 1,ㄅ,s_!

0xF0, 0x15, //001,002/192. q,ㄆ .

. . }

Code_Struct codedata[CODE_NUM] = {

{ 1, &makecode[0], 2, &breakcode[0]}, //000 1,ㄅ,s_!

{ 1, &makecode[1], 2, &breakcode[2]}, //001 q,ㄆ .

. . }

Word_Struct wordData[KEY_NUM]=

{

{ 7, &codedata[24], &codedata[37], &codedata[0], &codedata[21], &codedata[39], &codedata[39], &codedata[48]},//阿姨 { 7, &codedata[0], &codedata[24], &codedata[41], &codedata[4], &codedata[54],&codedata[0], &codedata[48]},//爸爸

. . . }

Send_KbCode(wordData[key_position].linkArr[i]->makecodelist[k]);

typedef struct KB_STRUCT { byte makelen;

byte *makecodelist;

byte breaklen;

byte *breakcodelist;

}Code_Struct;

typedef struct KB_Word_STRUCT{

int num_of_word;

Code_Struct *linkArr[MAX_MAKE_NUM];

}Word_Struct;

圖 6-3 系統圖形之鍵盤按鍵碼的資料結構分析圖

(15)

當 for 迴圈結束後,矩陣 databit[8]裡每個 byte 所儲存的值則會是 senddata 裡 8 個 bits 之相對值,而 paritybit 主要是計算 senddata 資料裡為 1 的個數是否為 偶數。前置資料處理完畢後,接著就開始傳送資料至印表機埠上。我們利用表 6-15 之 ParPortOut 副程式將資料送出。

在這裡應該特別注意的是,由於作業系統的發展逐漸嚴謹,它不允許我們直 接存取 I/O 埠(印表機埠)之資料,因此在利用_outp 此內建的傳送資料至 I/O 埠之 函式之前,我們必須將 #include <conio.h> 宣告在程式的起始端,並將

inpout32.dll 存放到 C:\Windows\system32 下,否則函式如_inp 或_outp 將無法運 行。至於 inpout32.dll 則是提供於平行埠(parallel port)的標準介面。

我們利用印表機埠的第 2 和 3 腳作為資料和時脈送出的 I/O 埠,此二腳為印 表機資料埠的第 1 和第 2 位元。由於送資料時,時脈線必須為 1,因此才將 OutData

表 6-15 傳送資料至印表機埠之程式 表 6-14 鍵盤按鍵碼位元判斷之程式

byte mask=1, databit[8],paritybit;

for(i=0;i<8;i++){

if((senddata & (mask << i)) >0)//該 bit 為 1 {

databit[i] = 1;

bitsum += 1;

} else

databit[i] = 0; //該 bit 為 0 }

paritybit = (bitsum % 2 == 0)? 1 : 0;

void ParPortOut(unsigned char OutData) {

OutData |= 0x02;

_outp(ParPortAddr, OutData);

}

(16)

之值與 2 做 OR 的動作。第一個傳送的字元為 startbit,其值為 0。接著我們會呼 叫 KeyboardClock 副程式,其主要目的是產生時脈週期,讓資料能根據時脈而傳 送。由於必須以 40μs 作為時脈的週期時間,因此在傳送 0 或 1 的時脈間隔時就 需要 delay 這個副程式將傳送時間延長。我們是透過兩個 for 迴圈達到此目的。

當 startbit 傳送結束後,根據鍵盤的標準傳送規格,接下來傳送的則是 Scan Code 資料(databit[8])。當此資料傳送結束後,則可傳送 paritybit 和值為 1 的 endbit。

這些資料的傳送過程都需要利用透過 KeyboardClock 副程式所產生的時脈。

完成了以上所有步驟,就完成了語音溝通系統和替代性輸入裝置的功能了。

二、軟體版面設計

圖 6-4 首頁版面配置圖

(17)

圖 6-6 溝通版首頁圖形

圖 6-5 內頁版面配置圖

(18)

圖 6-7 溝通版內頁(家裡人物)圖形

圖 6-8 溝通版內頁(學習)圖形

(19)

圖 6-9 溝通版內頁(吃東西-主食)圖形

圖 6-10 溝通版內頁(形狀、身體)圖形

(20)

圖 6-11 溝通版內頁(顏色、音樂、星座)圖形

圖 6-12 溝通版內頁(道路交通、方向)圖形

(21)

圖 6-4 為首頁版面配置圖,其中主要分成兩部份。第一部分為首頁圖形切換 至內頁的 48 個圖形按鍵,第二部份則是圖形畫面上下頁切換的按鍵,以圖 6-5 表示之。以下就這兩部份的功能作詳細的說明:

一、首頁圖形顯示畫面

由於人類溝通所需要之辭彙非常多,甚至對學齡前或腦性痲痺症的 小朋友而言也是如此,因此我們透過與小朋友和家長們的溝通,而自訂 了如圖 5-7 版面的配置。主要分成在家裡(包括家裡人物、家具、廚房 和衛浴)、在學校(文具、運動、學習和學校常景)、吃東西(主食、蔬菜、

水果和點心)、飲料、詞彙(比較詞、名詞、形容詞、動詞和量詞)、形狀、

身體、建築物、穿戴、時間、動物、植物、昆蟲、節慶故事、醫療、顏 色、音樂、星座、交通工具、自然景觀、電子設備、道路交通和方向圖 形,一頁以 48 個圖形為基準,以圖 6-6 至 6-12 圖為例。表 6-16 有詳細 的功能描述。

二、畫面上下頁切換鍵

主要包含了切換至首頁、上一頁和下一頁三個圖形按鍵。首頁圖形

按鍵為切換畫面至首頁,若當頁為首頁則不會切換。上一頁和下一頁則

分別切換至當頁的上一頁或下一頁。若當頁為首頁而按下上一頁則不切

換,相反的,若當頁為最後一頁而下一頁被按下,也無切換的動作產生。

(22)

表 6-16 溝通板首頁圖形切換按鍵

按鍵圖形 功能敘述

切換至內頁第一頁的人物版面,內容包括阿姨、爸爸、表弟、

大家等,共 53 個圖形,超過 48 個數的圖形將分配至下一頁。

切換至內頁第二頁的家具版面,內容包括玻璃、茶几、抽屜、

窗等,共 30 個圖形。

切換至內頁第二頁的廚房版面,內容包括杯子、冰箱、菜刀、

菜瓜布等,共 29 個圖形。

切換至內頁第三頁的衛浴版面,內容包括廁所、垃圾桶、臉 盆、蓮蓬頭等,共 29 個圖形。

切換至內頁第四頁的學校常景版面,內容包括班級、班長、

畢業典禮、操場等,共 70 個圖形。

切換至內頁第五頁的文具版面,內容包括別針、筆筒、筆心、

簿子等,共 48 個圖形。

切換至內頁第六頁的運動版面,內容包括棒球、保齡球、打 籃球、打羽毛球等,共 23 個圖形。

切換至內頁第七頁的學習版面,內容包括ㄅ、a、,、1 等,

共 93 個圖形。

切換至內頁第八頁的金錢版面,內容包括十元、百元、千元、

五十元等,共 9 個圖形。

切換至內頁第九頁的主食版面,內容包括包子、便當、炒飯、

蛋等,共 63 個圖形。

切換至內頁第九頁的蔬菜版面,內容包括白蘿蔔、菠菜、大 白菜、地瓜等,共 54 個圖形。

切換至內頁第十一頁的水果版面,內容包括百香果、芭樂、

草莓、蕃茄等,共 43 個圖形。

切換至內頁第十二頁的點心版面,內容包括棒棒糖、爆米花、

冰棒、餅乾等,共 41 個圖形。

切換至內頁第十三頁的飲料版面,內容包括茶、冰紅茶、茶 葉、豆漿等,共 25 個圖形。

切換至內頁第十三頁的比較詞版面,內容包括矮、高、骯髒、

乾淨等,共 59 個圖形。

切換至內頁第十四頁的名詞版面,內容包括芭比娃娃、存摺、

風箏、地球等,共 39 個圖形。

(23)

切換至內頁第十五頁的形容詞版面,內容包括愛、飽、不可 能、不是等,共 68 個圖形。

切換至內頁第十七頁的動詞版面,內容包括搬家、猜拳、擦 臉、吵架等,共 200 個圖形。

切換至內頁第廿一頁的量詞版面,內容包括本、個、件、片 等,共 13 個圖形。

切換至內頁第廿一頁的形狀版面,內容包括半圓形、扁的、

長方形、花花的等,共 22 個圖形。

切換至內頁第廿一頁的身體版面,內容包括背部、鼻子、脖 子、大拇指等,共 53 個圖形。

切換至內頁第廿三頁的建築物版面,內容包括百貨公司、辦 公室、便利商店、病房等,共 42 個圖形。

切換至內頁第廿三頁的穿戴版面,內容包括背包、背心、長 袖襯衫、短褲等,共 52 個圖形。

切換至內頁第廿四頁的時間版面,內容包括早晨、一月、春 天、星期二等,共 63 個圖形。

切換至內頁第廿五頁的動物版面,內容包括斑馬、豹、蝙蝠、

長頸鹿等,共 64 個圖形。

切換至內頁第廿六頁的植物版面,內容包括草、果樹、花、

花瓣等,共 22 個圖形。

切換至內頁第廿七頁的昆蟲版面,內容包括蒼蠅、蝴蝶、甲 蟲、毛毛蟲等,共 20 個圖形。

切換至內頁第廿七頁的節慶故事版面,內容包括包工、嫦娥、

端午節、父親節等,共 47 個圖形。

切換至內頁第廿八頁的醫療版面,內容包括繃帶、溝通板、

拐杖、固定系統等,共 18 個圖形。

切換至內頁第廿九頁的顏色版面,內容包括白色、彩色、粉 紅色、黑色等,共 16 個圖形。

切換至內頁第廿九頁的音樂版面,內容包括唱歌、鈸、電子 琴、鋼琴等,共 28 個圖形。

切換至內頁第廿九頁的星座版面,內容包括水瓶座、金牛座、

雙子座、天蠍座等,共 12 個圖形。

切換至內頁第卅頁的交通工具版面,內容包括船、飛機、復 康巴士、公共汽車等,共 22 個圖形。

切換至內頁第卅頁的自然景觀版面,內容包括彩虹、地震、

風、海浪等,共 35 個圖形。

(24)

切換至內頁第卅一頁的電子設備版面,內容包括吹風機、電 視、耳機、電話等,共 32 個圖形。

切換至內頁第卅一頁的道路交通版面,內容包括安全帶、安 全帽、殘障停車位、斑馬線等,共 19 個圖形。

切換至內頁第卅二頁的方向版面,內容包括上面、下面、外 面、往右上等,共 21 個圖形。

圖 6-5 的內頁版面配置圖包括三個部份:內頁圖形顯示畫面、功能鍵和畫 面上下頁切換鍵。以下為這三部份作更詳盡的說明:

一、內頁圖形顯示畫面

當使用者在首頁選擇了切換至內頁的圖形按鍵後,相關的圖形將顯示在 版面上,而當內頁的每個圖形按鍵被按下時,都會透過發聲回饋給使用者。

除此之外,相對與圖形按鍵碼也會透過外接自訂硬體而傳送到電腦端,進而 完成替代性輸入裝置的功能。此功能對於正在學習中文輸入法的小朋友有很 大的助益。為了節省畫面,若某種類圖形按鍵個數不滿足畫面個數(48 個),

接下來不同種類的圖形按鍵將會連續的放在上一種類之後,因此我們會發現 首頁的不同圖形按鍵可能分別對應到相同的內頁。

二、功能鍵

分別放了 Backspace、Enter、Home、End 和注音五個圖形按鍵。由於系

統本身就具有鍵盤符號的輸入功能,而選擇以上前四種放入至功能鍵區乃

希望能在最短時間內達到執行它們的功能,而注音則是切換輸入法按鍵。表

6-17 作了詳細的解說。

(25)

表 6-17 內頁功能鍵

按鍵圖形 功能敘述

讓使用者在使用內頁進行鍵盤輸入功能時,能直接達到退格 的功能。

讓使用者在使用內頁進行鍵盤輸入功能時,能直接達到換行 的功能。

讓使用者在使用內頁進行鍵盤輸入功能時,能直接讓游標回 到該行的最前端。

讓使用者在使用內頁進行鍵盤輸入功能時,能直接讓游標跳 到該行的最後端。

轉換至注音輸入法之版面。在 windows 作業系統中需設定注 音輸入法快速鍵為 Alt+Shift+1,則鍵盤會自動轉換輸入法至 注音輸入法。

三、畫面上下頁切換鍵

其功能與首頁之畫面切換鍵相同。若當本頁為內頁首頁,利用上一頁圖 形按鍵將會把畫面切換至首頁。

三、輸入法設計

為了讓系統達到替代性輸入裝置的功能,我們利用了外接自製硬體將按鍵碼

直接送出到電腦端而不需額外加任何軟體或硬體驅動程式。首先我們會有一大矩

陣存放每個圖形鍵盤按鍵的碼,例如圖形”人”,利用傳統注音輸入法,其對應

的輸入符號是 bp61(包含字根的選擇),因此在矩陣的相對地方將存放 bp61 的鍵

盤碼(keyboard makecode 和 breakcode),分別為 0x32、0x4D、0x36、0x16 和(0xF0

0x32)、(0xF0 0x4D)、(0xF0 0x36)、(0xF0 0x16) ,所以透過矩陣的 index 我們就

(26)

可以找到對應的鍵盤碼並送出到電腦端,此時電腦端的輸入法必須切換至傳統注 音輸入法的狀態下,也因為如此我們提供了注音輸入法快速切換的功能按鍵。

四、聲音檔設計

我們使用了自然注音輸入法所提供的聲音檔作為我們系統聲音檔發聲的來

源。聲音檔名是根據每個音的注音符號使用英文字母、數字和特殊符號加以編碼

而成。這些檔案是由中央研究院資訊研究所許聞廉教授和他的助理張永忠提供給

我們使用在輔具研發上的,共有 2,870 個聲音檔。

數據

表 6-2  從電腦端讀入時脈和資料信號
表 6-4 的 Draw_Main 和 Draw_Page 副程式之繪圖功能非常類似,但由於 Draw_Main 不需傳入版面的所在位置值,而 Draw_Page 是負責畫出其他除了首
表 6-10 是每個鍵盤按鍵(例如 a、b、ㄅ)都具有各自獨立的按鍵碼(makecode 和 breakcode),而 Code_Struct 這個資料結構定義了四個以 byte(8 bits)大小變數儲 存的鍵盤按鍵碼資料,例如 a 的 makelen 儲存的是 1,因為 a 的 makecode 長度為
圖  6-3  系統圖形之鍵盤按鍵碼的資料結構分析圖
+7

參考文獻

相關文件

在寫 8051 的程式時,必須知道幾個程式記憶體的特殊位址,這些位址是各種中 斷服務程式的進入點,表 2 列出了各種中斷的進入點位址,其中位址

隨身碟是一種攜帶方便的電腦儲存裝置。若浩南有一個容量為 8GB

mov ax,var1 ;將其中一個記憶體內容先複製到暫存器 xchg ax,var2 ;分別執行記憶體與暫存器內容的交換動作 xchg ax,var1 ;完成交換。 Swap var1

編排及設計各 級故事閱讀內 容及活動流程

Segmented Bushy Path 分為兩個步驟,第一個步驟是文件結構的切割 (Text Segmentation),也就是分析文件內容並將文件內容切割成幾個具有代 表的結構。Text Segmentation

占地面積 占地面積4000餘畝 餘畝 餘畝 餘畝... 學校概況 學校概況

 Bluetooth:為一低成本、低耗電、近距離的無線通訊技術,每個 裝置有一個唯一的 48-bit 位址,其網路容量可達 8 個 Bluetooth 裝置已 Peer-to-Peer 或

建立測試裝置 (Test device) ,記下DeviceId 與