顯示具有 WinCE Driver 標籤的文章。 顯示所有文章
顯示具有 WinCE Driver 標籤的文章。 顯示所有文章

2008年4月17日

IPL與SPL

節錄於Mobile01 : (偽)官方 818Pro 繁中 WM6 ROM Evo5.1/EVO6.2文章

IPL SPL

IPL與SPL實質為Windows mobile的Bootloader裡的兩大部份,WM啟動的程序是IPL--SPL--OS

1.IPL 英文全稱是 Initial Program Loader,它負責主板的通電管理並把SPL裝入RAM。
IPL損壞了就把手機拿去扔進河裡吧。

2.SPL 英文全稱是 Second Program Loader,「第二次裝系統」,就是負責裝載OS你好作系統到RAM中。另外SPL還包括許多系統命令,如mtty中使用的命令等。SPL損壞了還可以用燒錄器重寫。
##CONTINUE##

2007年7月11日

Block Device Driver vs. Character Device Driver

Device Driver大 致 分 為 Block Device Driver和 Character Device Driver兩 類 。
Block Device Driver是 以 固 定 大 小 長 度 來 傳 送 轉 移 資 料 ; Character Device Driver是 以 不 定 長 度 的 字 元 傳 送 資 料 。
##CONTINUE##
且 所 連 接 的 Devices也 有 所 不 同 , Block Device大 致 是 可 以 隨 機 存 取 (Random Access)資 料 的 設 備 , 如 硬 碟 機 或 光 碟 機 ; 而 Character Device剛 好 相 反 , 依 循 先 後 順 序 存 取 資 料 的 設 備 , 如 印 表 機 、 終 端 機 等 皆 是 。

2007年4月27日

[XXX661]為Driver加入global變數

當driver間想使用共同變數時,可以於drvglob.h(...\PUBLIC\COMMON\OAK\CSP\ARM\CXXX..Y\AT4X0A\SRC\INC)中加入變數:
##CONTINUE##
typedef struct _MISC_GLOBALS
{
UCHAR offButton; // Indicate to keyboard driver when OFF button pressed
UCHAR bSysGoingSleep;
...........
DWORD iPCMStatus; //0:PCM Mode 1:Normal Mode
DWORD iRotate;
} MISC_GLOBALS, *PMISC_GLOBALS;


一般只要在MISC_GLOBALS內加入即可,在這宣告的變數皆會屬於DRIVER_GLOBALS 這個Structure,由於在drvlib.h中已經宣告了一個DRIVER_GLOBALS的變數:

volatile DRIVER_GLOBALS *m_pDriverGlobals;
.....

#define v_pDriverGlobals (g_cspRegs.m_pDriverGlobals)


因此,當我們加入自己的變數之後,使用時僅需在driver中include drvlib.h這個檔,就可以開始使用了:
例如:
v_pDriverGlobals->misc.iEchoStatus = 3;


PS:感謝Jimmy學長的提示!

2007年4月5日

讓通話中能調整聲音與麥克風的音量

調整通話中的音量可以從XX9712與XX1182來調整,由於在XX9712中更改有可能會更動到其他狀態下的設定值,且XX1182原本就可以在Runtime模式下,藉由UART傳送AT Command來達到動態調整的功能,因此由XX1182來調整,在實踐上應該會比較簡單!
##CONTINUE##
首先,必須先知道在通話模式時,調整聲音的音量是由哪個driver所控制,根據Roland的說法,通話時音量的控制是由audio_api.dll所控制,即platform\bluetooth\PCM_Audio_Control.cpp,在此程式中有四個function:SetAudioVolumeGetAudioVolumeSetAudioMicVolumeGetAudioMicVolume分別對應到speaker與microphone的音量大小,因此只要在此加入控制程式即可!

為了要能控制XX1182,所以必須在XX1182的IOControl中加入相對應的程式:

case IOCTL_FME_PCM_VOLLEVEL:
{
unsigned char FmInitStr[][7] ={
{0xFC, 0xF3, 0x3B, 0x1E,0x3D,dwLenOut,0x00},
{0xFC, 0xF3, 0x3B, 0x1E,0x3A,0x00,0x00}
};
for(i=0;i<2;i++) bresult =" WriteFile" val =" dwLenOut;" i="0;i<2;i++)" bresult =" WriteFile" val =" dwLenOut;" style="color: rgb(255, 255, 51);">PCM1SpkVol、PCM2SpkVolPCM1MicVolPCM2MicVol用來儲存兩中模式下speaker與microphone的音量大小。

增加好控制碼後,在PCM_Audio_Control.cpp中就可以控制XX1182的輸出音量了:

DllExport void SetAudioVolume(AudioLevel audioLevel)
{
HANDLE g_hFM1182=NULL;
USHORT parm01=0;
DWORD dwRet;
g_hFM1182 = CreateFile(L"FME1:",0,0,NULL,OPEN_EXISTING,0,NULL);
if (INVALID_HANDLE_VALUE == g_hFM1182)
{
RETAILMSG(0, (TEXT("=====Error calling CreateFile on g_hFM1182\r\n")));
}
else
{
RETAILMSG(0, (TEXT("=====Calling CreateFile on g_hFM1182 Success!!\r\n")));
dwRet = DeviceIoControl(g_hFM1182,IOCTL_FME_PCM_SPKVOLLEVEL,
&parm01,sizeof(USHORT),NULL,(DWORD)audioLevel,NULL,NULL);
}
CloseHandle(g_hFM1182);
}

DllExport AudioLevel GetAudioVolume(void)
{
HKEY hkey;
LONG lResult;
DWORD dwType, dwSize;
unsigned short dvalue;
dwSize = 4;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
return 0;

if(PIO_READ_INPUT(GPIO, GPIO_GROUP(3),GPIO_INDEX(20)))
{
lResult = RegQueryValueEx(hkey, _T("PCM2SpkVol"), NULL, &dwType, (LPBYTE)&dvalue, &dwSize); //query registry value
}
else
{
lResult = RegQueryValueEx(hkey, _T("PCM1SpkVol"), NULL, &dwType, (LPBYTE)&dvalue, &dwSize); //query registry value
}

RegCloseKey(hkey);
return dvalue;

}

DllExport void SetAudioMicVolume(AudioLevel audioLevel)
{
HANDLE g_hFM1182=NULL;
USHORT parm01=0;
DWORD dwRet;
g_hFM1182 = CreateFile(L"FME1:",0,0,NULL,OPEN_EXISTING,0,NULL);


if (INVALID_HANDLE_VALUE == g_hFM1182)
{
RETAILMSG(0, (TEXT("=====Error calling CreateFile on g_hFM1182\r\n")));
}
else
{
RETAILMSG(0, (TEXT("=====Calling CreateFile on g_hFM1182 Success!!\r\n")));
dwRet = DeviceIoControl(g_hFM1182,IOCTL_FME_PCM_VOLLEVEL,
&parm01,sizeof(USHORT),NULL,(DWORD)audioLevel,NULL,NULL);
}
CloseHandle(g_hFM1182);
}

DllExport AudioLevel GetAudioMicVolume(void)
{
HKEY hkey;
LONG lResult;
DWORD dwType, dwSize;
unsigned short dvalue;
dwSize = 4;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
return 0;

if(PIO_READ_INPUT(GPIO, GPIO_GROUP(3),GPIO_INDEX(20)))
{
lResult = RegQueryValueEx(hkey, _T("PCM2MicVol"), NULL, &dwType, (LPBYTE)&dvalue, &dwSize); //query registry value
}
else
{
lResult = RegQueryValueEx(hkey, _T("PCM1MicVol"), NULL, &dwType, (LPBYTE)&dvalue, &dwSize); //query registry value
}

RegCloseKey(hkey);
return dvalue;
}

目前,通話中的音量可以動態的控制(若想讓聲音靜音,只需將gain值設為即可),不過當通話結束後,gain值的大小會再回復為預設值,不會儲存通話時的調整值!

2007年4月2日

讓調整參數更方便

由於聲音的調整經常需要不斷的調整與測試,如果在整機的狀態下,又不能跳線,那從修改參數,compile code,build image以及download image,光是修改一次參數的時間可能就要光掉5分鐘的時間了,效率上蠻差的!
##CONTINUE##
在Roland的建議以及幫助下,為了改參數能更快更方便,同時,希望能在讓客戶自行調整參數又不需要更動到driver的情形下,把參數的設定值儲存到一個文字檔上,再由driver來讀檔以及設定值!

1.
因為在此案中,Audio Path共有6種,所以必須準備6個檔分別對應至這6種情形,然後在Windows CE的 Registry下加入6個參數,儲存這四個檔的放置位置與檔名 :在Platform.reg中加入6個參數

[HKEY_LOCAL_MACHINE\SOFTWARE]
"File1"="\\Windows\\Bypass1.txt"
"File2"="\\Windows\\Bypass2.txt"
"File3"="\\Windows\\Bypass3.txt"
"File4"="\\Windows\\Bypass4.txt"
"File5"="\\Windows\\pcm01.txt"
"File6"="\\Windows\\pcm02.txt"

2.
在driver裡加入讀取Registry值與讀取檔案內值的function:傳入要讀取Registry的值並讀取相對應的檔案,再透過UART將值傳送至XX1182中。

int XX1182Write(HKEY key, TCHAR *subkey, TCHAR *name, HANDLE hComPort)
{
HKEY hkey;
LONG lResult;
TCHAR str[MAX_PATH], *pStr;
DWORD dwType, dwSize;
FILE *file;
unsigned char pData[7];
int i, nResult;

if (RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
return 0;

dwSize = sizeof(str);
lResult = RegQueryValueEx(hkey, name, NULL, &dwType, (LPBYTE)str, &dwSize); //query registry value
RegCloseKey(hkey);
if (lResult != ERROR_SUCCESS || dwType != REG_SZ)
return 0;

file = _tfopen(str, _T("rt"));
if (file == NULL) //open file failed
return 0;

nResult = 0;
while (_fgetts(str, MAX_PATH, file))
{
pStr = _tcsstr(str, _T("//"));
if (pStr) //there is comment
*pStr = _T('\0'); //remove comment

pStr = str;
for (i = 0; i < pstr =" _tcsstr(pStr,">= _T('0') && *pStr <= _T('9')) pData[i] = (pData[i] <<>= _T('A') && *pStr <= _T('F')) pData[i] = (pData[i] <<>= _T('a') && *pStr <= _T('f')) pData[i] = (pData[i] << i ="="">misc.iEchoStatus == 0)
{
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File1"), hFile);
CloseHandle(hFile);
}
else if(v_pDriverGlobals->misc.iEchoStatus == 1)
{
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File2"), hFile);
CloseHandle(hFile);
}
else if(v_pDriverGlobals->misc.iEchoStatus == 2)
{
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File3"), hFile);
CloseHandle(hFile);
}
else
{
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File4"), hFile);
CloseHandle(hFile);
}
break;

case IOCTL_FME_PCM_MESSAGE:
//PCM spk -> out2 echo cancellation on
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File6"), hFile);
CloseHandle(hFile);
break;

case IOCTL_FME_PCM_MESSAGE2:
//PCM spk -> out2 echo cancellation on
nLine = XX1182Write(HKEY_LOCAL_MACHINE, _T("SOFTWARE"), _T("File5"), hFile);
CloseHandle(hFile);
break;


藉由此方式,確實可讓調整參數更快也更方便,可直接在Windows CE直接更改相對應的文字檔來調整,driver的不份則不需再更動,不過,缺點則是執行時間會變長。

2007年3月28日

XX1182設定方式

XX1182在此案子主要用來echo cancellation and noise suppression,包括錄音與與藍芽連接時PCM的聲音處理。
此Chip的參數設定方式透過UART傳入Commond的方式來更改,透過修改不同Memory Address位址,可以設定聲音傳送的路徑、設定microphone與speaker的pgagain值大小等。
##CONTINUE##
Command的格式是以FCF3為開頭作為sync word,例如:

寫值:
FC F3 3B 1E 34 00 55 代表 write memory 1E34 with 0055

讀值:
FC F3 37 1E 34 代表 read memory contents of 1E34

因此,在driver中,我們可以利用一個Array來儲存要修改的參數:
unsigned char FmInitStr[][7] ={
{0xFC, 0xF3, 0x3B, 0x1E, 0x30, 0x02, 0x21},
{0xFC, 0xF3, 0x3B, 0x1E, 0x34, 0x00, 0x0F},
{0xFC, 0xF3, 0x3B, 0x1E, 0x3D, 0x0A, 0x00},
{0xFC, 0xF3, 0x3B, 0x1E, 0x41, 0x00, 0x01},
{0xFC, 0xF3, 0x3B, 0x1E, 0x44, 0x00, 0x01},
{0xFC, 0xF3, 0x3B, 0x1E, 0x45, 0x00, 0xDE},
{0xFC, 0xF3, 0x3B, 0x1E, 0x46, 0x00, 0x10},
{0xFC, 0xF3, 0x3B, 0x1E, 0x36, 0x00, 0x1F},
{0xFC, 0xF3, 0x3B, 0x0F, 0xA9, 0x00, 0x80},
{0xFC, 0xF3, 0x3B, 0x1E, 0x70, 0x07, 0xC0},
{0xFC, 0xF3, 0x3B, 0x1E, 0x52, 0x00, 0x07},
{0xFC, 0xF3, 0x3B, 0x1E, 0x51, 0xC0, 0x00},
{0xFC, 0xF3, 0x3B, 0x1E, 0x3A, 0x00, 0x00}
};

然後再利用一個迴圈依序將Commond透過UART傳入即可!
for(i=0;i<13;i++) bresult =" WriteFile" style="color: rgb(255, 255, 51);">IE65的值,若是正常狀況下,讀取的值會不斷的增加,反之,則為0。