2013年12月9日 星期一

TSLIB on Android gingerbread

TSLIB,顧名思義就是Touch Screen Library
聽說原本是拿來做滑鼠校正的,衍生出來觸控螢幕校正

基本上他的原理並不難懂,他是使用五點校正來算校正值,公式如下:
x = (Origin.x * xscale) + (Origin.y * xymix) + xoffset;
y = (Origin.x * yxmix) + (Origin.y * yscale) + yoffset;
如果對於校正的理論有興趣的話,可以參考這份文件:
http://www.tij.co.jp/jp/lit/an/slyt277/slyt277.pdf

------------------------------------------------------------------------------------------------------------
首先呢,我們要先下載for Android的tslib,網路上有很多地方可以下載
我下載的是下面這個連結的code:(裡面也有說明,可以參考)
https://github.com/etmatrix/tslib

Linux下的下載步驟:
1、首先,先切換到Android source code的目錄下的externel資料夾:
#cd <Android source>/external/

2、再來下載tslib source code:
#git clone https://github.com/etmatrix/tslib.git

3、再來切換到tslib的source code目錄下,對tslib做設定:
#cd tslib
#autoreconf -ivs
#./configure

4、設定完之後,切換回Android source code的目錄:
#cd <Android source>

5、最後,編譯tslib:
#make libts
#make ts/plugins/input
#make ts/plugins/pthres
#make ts/plugins/dejitter
#make ts/plugins/linear
#make ts/plugins/variance
#make ts_calibrate
#make ts_test

------------------------------------------------------------------------------------------------------------
編譯完tslib之後,接下來就是要開始把編譯完的tslib丟到Android系統裡了
由於我們要透過adb(Android Debug Bridge)來把資料丟到系統裡
若是您沒有adb的話,可以在google下載SDK,在platform-tools裡就會有了

SDK下載連結:
https://developer.android.com/sdk/index.html

再來我們要開始把編譯好的tslib丟進Android系統裡:
#adb push out/target/product/generic/system/lib/libts.so /system/lib/libts.so
#adb push out/target/product/generic/system/lib/ts/plugins/dejitter.so /system/lib/ts/plugins/dejitter.so
#adb push out/target/product/generic/system/lib/ts/plugins/input.so /system/lib/ts/plugins/input.so
#adb push out/target/product/generic/system/lib/ts/plugins/linear.so /system/lib/ts/plugins/linear.so
#adb push out/target/product/generic/system/lib/ts/plugins/pthres.so /system/lib/ts/plugins/pthres.so
#adb push out/target/product/generic/system/lib/ts/plugins/variance.so /system/lib/ts/plugins/variance.so
#adb push out/target/product/generic/system/bin/ts_calibrate /system/ bin/ts_calibrate
#adb push out/target/product/generic/system/bin/ts_test /system/bin/ts_test

丟進去之後,透過ADB連進Android的shell裡:
#adb shell

進到Android的shell裡之後,我們要先查觸控螢幕的event編號,可以用以下指令查:







在這裡我的觸控螢幕是event0,所以底下的環境變數就要設定/dev/input/event0

連進去之後,要來做環境變數設定:
首先,我們必須先停掉Android系統,不然沒辦法寫校正參數進去:
#stop zygote

停掉Android系統之後,再來輸入環境變數:
#export TSLIB_TSDEVICE=/dev/input/event0
#export TSLIB_CALIBFILE=/system/etc/pointercal
#export TSLIB_CONFFILE=/system/etc/ts.conf 
#export TSLIB_PLUGINDIR=/system/lib/ts/plugins 
#export TSLIB_FBDEVICE=/dev/graphics/fb0 
#export TSLIB_CONSOLEDEVICE=/dev/tty

設定完環境變數之後,就可以開始做校正:
#ts_calibrate

校正畫面:





















校正完之後,會把校正檔案寫在/etc/pointercal,校正參數的格式如下:
xscale  xymix  xoffset  yxmix  yscale  yoffset  divider  x  y

校正完之後,我們可以利用tslib內建的測試畫面來測試剛剛校正的位置:
#ts_test

測試畫面:

當然 底下畫得很醜的圖案是我畫的XD

到這裡基本上就已經校正完成了,再來就是要在Android系統上套用校正參數
我的作法是修改Android系統的source code,只修改一個檔案就可以套用校正參數:
在/framework/base/libs/ui/InputReader.cpp下:

首先先定義校正參數的struct
struct PointTouchCalibrate
{
           float xscale;
           float xymix;
           float xoffset;
           float yxmix;
           float yscale;
           float yoffset;
           bool HaveTouchCalibration;
}mPointTouchCalibrate;

定義完結構之後,加入讀取校正參數的code:
@void TouchInputMapper::parseCalibration()
//Load touchscreen calibration data
           int t_xscale;
           int t_xymix;
           int t_xoffset;
           int t_yxmix;
           int t_yscale;
           int t_yoffset;
           int divider
    FILE *file = fopen("/system/etc/pointercal","r");
   if(FILE)
   {        
          fscanf(file,"%d%d%d%d%d%d%d",
                    &t_xscale,&t_xymix,&t_xoffset,&t_yxmix,&t_yscale,&t_yoffset,&divider);
          fclose(file);
          mPointTouchCalibrate.xscale = (float)t_xscale / divider;
          mPointTouchCalibrate.xymix = (float)t_xymix / divider;
          mPointTouchCalibrate.xoffset = (float)t_xoffset / divider;
          mPointTouchCalibrate.yxmix = (float)t_yxmix / divider;
          mPointTouchCalibrate.yscale = (float)t_yscale / divider;
          mPointTouchCalibrate.yoffset = (float)t_yoffset / divider;
          mPointTouchCalibrate.HaveTouchCalibration = true;
   }else
   {
          mPointTouchCalibrate.HaveTouchCalibration = false;
    }

之後就要來修改Android坐標軸的算法了:
@void TouchInputMapper::dispatchTouch
//X and Y
//float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
//float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
float x,y,x_temp,y_temp;
if(mPointTouchCalibrate.HaveTouchCalibration)
{
        x_temp = float(in.x - mLocked.xOrigin);
        y_temp = float(in.y - mLocked.yOrigin);

        x = (x_temp * mPointTouchCalibrate.xscale) +
              (y_temp * mPointTouchCalibrate.xymix) + mPointTouchCalibrate.xoffset;

        y = (x_temp * mPointTouchCalibrate.yxmix) +
              (y_temp * mPointTouchCalibrate.yscale) + mPointTouchCalibrate.yoffset;
}else
{
        x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
        y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
}

修改完source code之後,重新compile就可以把tslib的校正參數套用進去了!

Reference:

Android Gingerbread Touchscreen Calibration