フットキーボードにスイッチをひとつ追加する

ガジェット製作

今回はベースのフットキーボード回路にスイッチをひとつ追加してキー入力できるか確認してみます。

サンプルのライセンス

Microchip社から頒布されているサンプルコードとライブラリ満載のLibraries for Applicationですが、エンドユーザ契約を確認したところ、再頒布の許可する内容が見当たりませんでした。以前は、”copy, modify and distribution”はご自由に、と書いてあったような気がするのですが。。。

ということで、ソースコードについてはサンプルコードからの変更点のみを説明しようと思います。

 

USB Device-HID-Keyboardサンプルコードを確認

フットキーボードを製作するために編集が必要なソースコードは、ハードウエアプロファイルのヘッダファイルとメインファイル(keyboard.c)だけで済みそうです。あと、USBデバイスの属性もいずれ変更すると思いますので、そのときはさらにusb_descriptor.cも編集が必要になると思います。

今後の進め方ですが、まずはスイッチを1個追加して合計2個のスイッチがうまく動作するか確認しようと思います。1個追加がうまくいけば、それを繰り返せばスイッチの数を増やせますからね(ってなんかへんな落とし穴がないといいけど)。スイッチを増やして、希望のキー入力ができるようになったら、Macからキー割当てを設定するアプリに挑戦してみたいと思います。

スイッチをひとつ追加する、ということで、サンプルのスイッチの処理を調べてみました。

まずヘッダファイルとなるハードウエアプロファイルです。ソースコードは “HardwareProfile – LPC USB Development Kit – PIC16F1459.h” …って、長っ。これです。

HardwareProfile

物理的なスイッチはポートAのRA3につながっていますので、それらしきものを確認すると、

/** SWITCH *********************************************************/
#define mInitSwitch2()      //TRISAbits.TRISA3=1
    //only one switch available so double duty
#define mInitSwitch3()      //TRISAbits.TRISA3=1
#define sw2                 PORTAbits.RA3
#define sw3                 PORTAbits.RA3
#define mInitAllSwitches()  mInitSwitch2();

ってありました。まず、PORTAbits.RA3がsw2とsw3に定義されていています(なんで?)。あと、初期化と思われるmInitAllSwitches()がmInitSwitch2()に定義されていて、mInitSwitch2()は、、、何も定義されていないみたいです。さらに”only one switch available so double duty”ってコメントがあったり、、、このあとに自分で追加したスイッチの定義を付け加えればいいんだよね。いいんだよね。(なんか不安)

次にメインプログラムですが、こちらはkeyboard.cに一通り書いてあるみたいです。これです。

Keyboard

スイッチが押されたことの判定と、そのスイッチに対するキーのデータ送信は void Keyboard(void)関数で行われているようです。具体的にはこんな感じです。

if(!HIDTxHandleBusy(lastINTransmission))
{
    if(Switch3IsPressed())
    {
    	//Load the HID buffer
    	hid_report_in[0] = 0;
    	hid_report_in[1] = 0;
    	hid_report_in[2] = key++;
    	hid_report_in[3] = 0;
    	hid_report_in[4] = 0;
    	hid_report_in[5] = 0;
    	hid_report_in[6] = 0;
    	hid_report_in[7] = 0;
       	//Send the 8 byte packet over USB to the host.
       	lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);
    
        if(key == 40)
        {
            key = 4;
        }
    }
    ....

詳しく調べていませんが、HIDTxHandleBusy(lastINTransmission)は”Busy”という文字が入っているので、おそらく前回のデータ送信が終了しているか判断するのかなって思います。それでデータが送れる状態だったら、次にSwitch3IsPressed()でスイッチが押されているか判断して、押されていればデータを詰めてHIDTxPacket()でキーデータを送信する、といった感じでしょうか。ていうか、1回のキーデータって、8バイトも送るんですね。知りませんでした(っていうかちょっとは調べろよ)。今回はスイッチをひとつ追加してそのスイッチを押したら普通のキーデータ(aとか)を送信するようにするつもりですが、shiftとかcommandの組み合わせの場合どうするんですかね。これまた後で困りそうな雰囲気。

なんとなくいけそうな気もするので(エッ?)、スイッチ回路を追加してみようと思います。

 

回路にスイッチをひとつ付け足す

スイッチを付け足す場所ですが、ワイヤ線をあまり引き回したくないので、スイッチを↓に追加したいので、PICのピンとしては、↓のあたりかな。ってことで、あんまり根拠はないけど、9番ピンのRC7につなげることにしました。このあとさらに追加スイッチはRC6, RC5, RC4につなげようかなと思ってます。

スイッチ追加場所

ところでスイッチをつける場合、チャタリング防止とプルアップ(あるいはプルダウン)が必要です。チャタリング防止に関しては、ベースの回路に特にハード的なことはしていないので、まずはスイッチそのままつけることにしました。あと、プルアップですが、PICマイコンはピンによっては設定で内部プルアップを使うことができるのですが、残念ながPIC16F1459はデータシートを確認したところポートA、ポートBにはその設定があるものの、ポートCにはありませんでした。

う〜ん、配線引き回してポートA/Bから引っ張ってくるか、ポートCにつなげてプルアップ抵抗をつけるか、ちょっと悩みどころですが、といあえずポートCを使うことにしました。ブレッドボードの上の方は何かの追加回路用に取っておこうと思います。

ということで、RC7(9番ピン)にスイッチ追加、10kオームの抵抗でプルアップ、ということで回路図はこうなりました。

スイッチ追加回路

EAGLEの回路データもつけておきます。

 

回路を組み立てる

回路図に沿ってスイッチを追加します。追加部品はタクトスイッチ1つ、10kオーム抵抗1つ、接続用のワイヤ線です。こんな感じになりました。

スイッチ1つ追加

 

ソースコードに追加する

まずはハードウエアプロファイルに新しいスイッチの定義を追加します。自分でつけたスイッチということで、

/** SWITCH *********************************************************/
#define mInitSwitch2()      //TRISAbits.TRISA3=1
    //only one switch available so double duty
#define mInitSwitch3()      //TRISAbits.TRISA3=1
#define sw2                 PORTAbits.RA3
#define sw3                 PORTAbits.RA3
#define mInitAllSwitches()  mInitSwitch2();

このコードのあとに

// Added by Tool Labs
#define own_sw1             PORTCbits.RC7

と追加してみました。

次にkeyboard.cです。

まず、はじめの方に

BYTE old_sw2,old_sw3;
char buffer[8];
unsigned char OutBuffer[8];
USB_HANDLE lastINTransmission;
USB_HANDLE lastOUTTransmission;
BOOL Keyboard_out;
BOOL BlinkStatusValid;
DWORD CountdownTimerToShowUSBStatusOnLEDs;

と定義が並んでいますので、old_sw2, old_sw3と同様に、このあとに

//Added by Tool Labs
BYTE old_own_sw1;

と追加しました。あと、スイッチが押されたかの関数が必要となりますので、

/** PRIVATE PROTOTYPES *********************************************/
void BlinkUSBStatus(void);
BOOL Switch2IsPressed(void);
BOOL Switch3IsPressed(void);

のあとに、

BOOL OwnSwitch1IsPressed(void);   //Added by Tool Labs

を追加しました。あとは動作部分の追加です。

まずInitializeSystem()の中をみると、TRISC = 0x00;と定義されていて、ポートCはすべて出力設定になっていますので、RC4〜RC7を入力ピンとするため、

TRISC = 0xF0;

と書き換えます。次にスイッチ関連のコードを探すと、UserInit()にありますので、sw2, sw3と同様に

//Added by Tool Labs
old_own_sw1 = own_sw1;

と追加しました。あとは、keyboard()の中に実際にデータ送信部があますので、

if(Switch3IsPressed())
{
	//Load the HID buffer
    hid_report_in[0] = 0;
    hid_report_in[1] = 0;
    hid_report_in[2] = key++;
    hid_report_in[3] = 0;
    hid_report_in[4] = 0;
    hid_report_in[5] = 0;
    hid_report_in[6] = 0;
    hid_report_in[7] = 0;
    //Send the 8 byte packet over USB to the host.
    lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);

    if(key == 40)
    {
        key = 4;
    }
}
else
{
    //Load the HID buffer
    hid_report_in[0] = 0;
    hid_report_in[1] = 0;
    hid_report_in[2] = 0;   //Indicate no character pressed
    hid_report_in[3] = 0;
    hid_report_in[4] = 0;
    hid_report_in[5] = 0;
    hid_report_in[6] = 0;
    hid_report_in[7] = 0;
    //Send the 8 byte packet over USB to the host.
    lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);
}

を新しく追加したスイッチを押すと “a” のデータを送信するように、

if(Switch3IsPressed())
{
    //Load the HID buffer
    hid_report_in[0] = 0;
    hid_report_in[1] = 0;
    hid_report_in[2] = key++;
    hid_report_in[3] = 0;
    hid_report_in[4] = 0;
    hid_report_in[5] = 0;
    hid_report_in[6] = 0;
    hid_report_in[7] = 0;
   	//Send the 8 byte packet over USB to the host.
    lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);

    if(key == 40)
    {
        key = 4;
    }
}
else if(OwnSwitch1IsPressed())   //Added this if block by Tool Labs
{
    //Load the HID buffer
    hid_report_in[0] = 0;
    hid_report_in[1] = 0;
    hid_report_in[2] = 4;
    hid_report_in[3] = 0;
    hid_report_in[4] = 0;
    hid_report_in[5] = 0;
    hid_report_in[6] = 0;
    hid_report_in[7] = 0;
    //Send the 8 byte packet over USB to the host.
   	lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);
} else
{
    //Load the HID buffer
    hid_report_in[0] = 0;
    hid_report_in[1] = 0;
    hid_report_in[2] = 0;   //Indicate no character pressed
    hid_report_in[3] = 0;
    hid_report_in[4] = 0;
    hid_report_in[5] = 0;
    hid_report_in[6] = 0;
    hid_report_in[7] = 0;
    //Send the 8 byte packet over USB to the host.
    lastINTransmission = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);
}

というように黄色文字部分を追加しました。

 

動作確認!

早速プログラムをビルドして、PICに書き込み、動作確認してみます。

ブレッドボードのUSB端子にUSBケーブルをつなげて、テキストエディットで確認してみると、

キー入力確認

意外にもすんなり動きました。”abcdefg…”とアルファベットが順番のところが1個目のスイッチ、”aaaaa”とaが続いていることろが、新しく追加したスイッチを押したものです。なんか落とし穴があるのでは、と思っていましたが、うまく動きました。

この調子でスイッチをもっと追加して、スペース、shift+スペース、v、command+w、sのキーを割り当てれば、Google Readerが足だけで操作できる!
(スイッチは合計5個必要ですね。5個は足で押せるんでしょうか。。。)

あと、shiftとかcommandとかのキー修飾の仕方がわからないので、次回はこれについて調べてみたいと思います。

 

変更履歴

 

日付 変更内容
2013.3.8 初版

« »