StickKey - バーチャロンのスティックで文字入力する。

7M4MON 2008/8/28

StickKeyとは2本のスティックでPCに文字を入力する装置です。
キーボードの代わりとして使用できます。
外観図を下記に示します。
  

バーチャロンのツインスティックの改造品です。というか、見た目はオリジナルそのままです。

動作説明

まずは下の動画をご覧下さい。

左側のスティックと右側スティックの倒した方向の組み合わせで文字を決定し、右トリガーボタンを押す事により文字を入力します。
左トリガーボタンは Shift キーに、左丸ボタンは Ctrl キーに対応します。
動画より、Shiftで小文字が入力され、Ctrl+↓↑でCtrl+Aが入力されている事が分かると思います。

スティックの組み合わせは下記表のとおりです。

左スティックが直立の時、右も直立なら「ENTER」で、それ以外は上から時計回りに ↑,DEL,→,TAB,↓,ESC,←,BS となります。

ハードウェア

トリガがかかったときのスティックの状態をマイコンで取得してパソコンに送ります。
中身はシンプルで、ジョイスティック側にマイコン(16F628A)と秋月のUART-USB 変換モジュールが載っているのみです。

 

マイコン側プログラム

マイコンはキーの入力から文字を送るまでを担当します。
トリガがかかったときにスティックの倒している方向とShift,Ctrl の状態を取得して送るべき文字を選んでいます。
下記にソースを示します。CCS-Cコンパイラ用です。
/*
スティックキー    Ver2 2008年8月28日
バーチャロンのスティックの状態に応じて文字を出力する。
*/
#include <16f628a.h>
#fuses INTRC_IO,NOWDT,PUT,NOPROTECT,NOMCLR
#use delay(CLOCK = 4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1)    //ハードウェアUART
#define UP_IL PIN_A4
#define DOWN_IL PIN_A5
#define LEFT_IL PIN_A3
#define RIGHT_IL PIN_A2
#define UP_IR PIN_A7
#define DOWN_IR PIN_A6
#define LEFT_IR PIN_A0
#define RIGHT_IR PIN_A1
#define TRIG_SW PIN_B7
#define DEBUG_SW PIN_B6
#define SHIFT_SW PIN_B4
#define CTRL_SW PIN_B5
const int roundnumh[9]={0,1,5,3,2,4,7,8,6};        //roundnumのテーブルバージョン
const int zeror[9]={'\n',0x1E,0x7F,0x1C,0x09,0x1F,0x1B,0x1D,'\b'};//LF,↑,DEL,→,TAB,↓,ESC,←,BS
int X,Y,R,L,S=0;
void main(){
    port_b_pullups(FALSE);    //分りづらいから全部プルダウンで。
    while (TRUE){
        delay_ms(100);      //キーリピートのタイミング
        if(input(TRIG_SW)==1){
                     //何らかの入力待ち
                     //上から時計回りに「1,4,3,5,2,8,6,7」となります。
            R= input(UP_IR) + input(DOWN_IR)*2 + input(RIGHT_IR)*3 + input(LEFT_IR)*6;
            R= roundnumh[R];
            L= input(UP_IL) + input(DOWN_IL)*2 + input(RIGHT_IL)*3 + input(LEFT_IL)*6;
            L= roundnumh[L]*8;
                     if(L==0){X=zeror[L];}
                     else{
                             S=(0x20*input(SHIFT_SW))+(0xC0*input(CTRL_SW));
                if(S==0xE0){S=0x80;}                                //日本語
                X=0x18+R+L+S;
            }
                     if(input(DEBUG_SW)==1){
                printf(",R=%X,L=%X,R+L=%X,X=%X,S=%X\r\n",R,L,R+L,X,S);
            }
            else{
                putc(X);//文字の出力。
            }
            X,Y,R,L,S=0;//変数の初期化
        }
    }
}

まず、スティックの倒れている状態を確認します。
上下/左右は同時に倒れる事がないので、スティックの重み付けは時計回りには1,3,2,6ととします。
順番を整えるため、読み込んだ値を roundnum[] という配列を使って上から順番に1〜8と並び替えます。

読み込んだ値からアスキーコード表により文字が決定されます。


「Shift」はスティックの状態を0x20だけ(コード表で言うと右に2つ)シフトしています。
同様に、「Ctrl」 は左に4つシフトしています。(0xC0は右に12だけど一周回って左に4つ)
制御文字になっていますが、キーイベント変換時にWindows側でCtrl+に変換してくれました。
Ctrl+Shiftは左に4つ+右に2つで左に2つシフトですが、面白くないので0x80(右に8つ)シフトしてカタカナを入力させるようにしました。
と言うわけで、「!」のShiftは「A」になってしまいますが(゜ε゜)キニシナイ!!

Windows側プログラム

シリアルポートに入力された文字をキーイベントに変換するプログラムです。

シリアルポートから文字を受け取って、Convert.ToChar してキーイベントを発生させているだけです。

'If DataReceived, then Convert and Sendkeys
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim rcvChar As Char = Convert.ToChar(SerialPort1.ReadChar)
        SendKeys.SendWait(rcvChar)
End Sub


VB2008で作りました。スクリーンショットを下記に示します。


Visibleボタンはタスクトレイ収納です。

その他

トラップさんのser_code_ksimを使えばZaurusでも使えたような。。。
Make Tokyo Meeting 03 (May.2009 ) に出展した際にはなかなか好評でした。