zkbd.c チャタリングとか改善してるといいなパッチ

C700でちょっと触ってみた程度ではチャタリング解消できているっぽいけどしばらく試して様子見。これでOKなら割り込み動作が半分以下で済むというオマケがついてくる。
あとC3x00にも影響するはずだけどこちらは未確認。


0. ちょっとだけ軽量化

stuck_keys[]はそこに定義されているキー番号への処理をスキップする、という感じがしたので、zkbdmap.hのキー定義テーブルを参照してC7x0/860用のテーブルを用意。ついでにC3x00用のテーブルにも追加しておく。

チャタリングとは関係ないけどとりあえず動作に問題はなさそう。

@@ -100,16 +100,23 @@
 	76,
 	77
 };
 
 static const int stuck_keys[] = {
-	7,
-	15,
-	23,
-	31
+	1,  7,  15, 22, 23, 31, 39, 47,
+	53, 55, 60, 63, 66, 67, 69, 71,
+	72, 73, 74, 75, 76, 77, 78, 79,
+	82, 85, 86, 87, 90, 91, 92, 94,
+	95
 };
 
+static const int stuck_keys_c860[] = {
+	0,  1,  47, 53, 55, 60, 63, 66,
+	67, 69, 71, 72, 73, 74, 76, 77,
+	78, 79, 80, 81, 82, 83, 85, 86,
+	87, 88, 89, 90, 91, 92, 94, 95
+};
 #define REP_DELAY1 400
 #define REP_DELAYN 100
 
 struct zkbd_softc {
 	device_t sc_dev;
@@ -252,12 +259,12 @@
 	} else if (ZAURUS_ISC860) {
 		sc->sc_sense_array = gpio_sense_pins_c860;
 		sc->sc_strobe_array = gpio_strobe_pins_c860;
 		sc->sc_nsense = __arraycount(gpio_sense_pins_c860);
 		sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c860);
-		sc->sc_stuck_keys = NULL;
-		sc->sc_nstuck = 0;
+		sc->sc_stuck_keys = stuck_keys_c860;
+		sc->sc_nstuck = __arraycount(stuck_keys_c860);
 		sc->sc_maxkbdcol = 0;
 		sc->sc_onkey_pin = -1;
 		sc->sc_sync_pin = -1;
 		sc->sc_swa_pin = -1;
 		sc->sc_swb_pin = -1;

1. キースキャンのタイミング

いったんキーが押下されてzkbd_poll()を呼ぶと、中で定周期タイマを作成して全てのキー押下が解除されるまで自身を呼び出してキースキャンをしてる、ような気がする。
なら定周期動作中はキースキャンのタイミングをタイマ満了時のみに絞って、チャタリング中のシグナルや他のキーのシグナルは破棄しまえばチャタリングを解決できそうな。

チャタリング解消できたっぽい

@@ -346,12 +353,14 @@
 /* XXX are some not in the array? */
 /* handle keypress interrupt */
 static int
 zkbd_irq(void *v)
 {
+	struct zkbd_softc *sc = (struct zkbd_softc *)v;
 
-	zkbd_poll(v);
+	if (!callout_pending(&sc->sc_roll_to))
+		zkbd_poll(v);
 
 	return 1;
 }
 
 static void

2. 割り込み条件

1.が問題ない場合、キーリリースの割り込みってあっても常に無視されてしまうので不要という疑惑がでてきたので実験してみる。

→無くても大丈夫だった

@@ -294,11 +301,11 @@
 	for (i = 0; i < sc->sc_nsense; i++) {
 		pin = sc->sc_sense_array[i];
 		if (pin == -1)
 			continue;
 		pxa2x0_gpio_set_function(pin, GPIO_IN);
-		pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH, IPL_TTY,
+		pxa2x0_gpio_intr_establish(pin, IST_EDGE_RISING, IPL_TTY,
 		    zkbd_irq, sc);
 	}
 
 	if (sc->sc_onkey_pin >= 0)
 		pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH,