![]() ![]() |
|
![]() |
|||||||||||||||
ハードウェアとしては、モジュールにスイッチを付加しただけです。 スイッチの状態は、A/Dコンバータを使い、電圧レベルで検出します。 抵抗を挟んでタクトスイッチを並べているだけなので、配線は非常に簡単です。 その代わり、スイッチの同時押しには対応できません。 スイッチのスキャンに時間がかかるため、高速な応答が要求される用途には向きません。 |
||||||||||||||||
↓細長いユニバーサル基板に組み付けました。![]() ☆☆☆ ソフトウェア ☆☆☆ ソフトウェアはマイクロチップ・フレームワークに含まれる「Device - HID - Keyboard」を元にして作っていきます。 デモソフトは、スイッチを押す度にキースキャンコードをインクリメントして返しています。 今回作成するのはマクロキーボードなので、スイッチを押すことにより、あらかじめ定義したマクロ(キースキャンコード)をPCに返します。 マクロの定義は、プログラム中に文字列として格納します。 こんな風---------------------------------------- rom unsigned char sw1_list[] = "key_1_on\\n" ; rom unsigned char sw2_list[] = "key_2_on\\n" ; rom unsigned char sw3_list[] = "key_3_on\\n" ; ----------------------------------------------- マクロ設定を変更する場合は、プログラム中の文字列を変更して再コンパイルし、、所謂ファームウエアの全てを書き換えます。 ファームウェアを書き換えずに、マクロ定義だけを書き換える様なアプリケーションを作ることも可能ですが、その場合はPCがデバイスを同定するためにユニークなPID(VID)が必用となります。 USBのVIDを取得するためには、は現在5000米ドルが必要です。(そもそも、個人が取得できるものなのか?) お金が無いので、ここではUSBデバイスに対する操作は諦めます。 、VID、PIDに関してははマイクロチップ社のデモプログラムの値をそのまま使っています。 OSの標準的なドライバが使用されるので、特に問題は起こらない筈です。 ソフトウェアで一番比重が大きい部分は、マクロ定義とキースキャンコードを変換している部分です。 キーボードがPCに送るのは、アスキーコードではなく、キーコードです。 キーコードには、アスキーコードが対応していない、「shift、ctrl、alt、win、func」等々のキーが有るため、これらのキーを表現するためのギミックを仕込む必用があります。 有名なキーマクロソフトの「AUTOHOTKEY」の場合、アスキーコードに対応していないキーについては、複数の文字列を使用して表現しています。 可読性の面では判りやすくて良いのですが、メモリに余裕の無いマイコンの場合、ちょっと真似ができません。 ここでは次善策として、簡単なエスケープシーケンス(風)の処理で対処しています。 場当たり的に作ったので、エスケープシーケンスの定義には規則性や他のソフトとの互換性はありません。 エスケープシーケンス定義の一覧 マウス 左クリック \l マウス 右クリック \r 「\」(エンサイン)入力 \\ Enterキー 入力 \n カーソル 上 \e カーソル 左 \s カーソル 右 \d カーソル 下 \x タブ \t BS \q DEL \w Esc \z CapsLock \c Home \h Insert \i Delete \t End \y PageUp \u PageDown \o 左シフトキー \A 右シフトキー \B 左コントロールキー \C 右コントロールキー \D 左Windowsキー \E 右Windowsキー \F 遅延 \P 長い遅延 \p 最初の遅延 \m リピート \! コントロールキー(同時押し) \1 シフトキー(同時押し) \2 ALTキー(同時押し) \3 Windowsキー(同時押し) \4 ファンクションキー1 \f1 ファンクションキー2 \f2 ファンクションキー3 \f3 ファンクションキー4 \f4 ファンクションキー5 \f5 ファンクションキー6 \f6 ファンクションキー7 \f7 ファンクションキー8 \f8 ファンクションキー9 \f9 ファンクションキー10 \fa ファンクションキー11 \fb ファンクションキー12 \fc PrtScキー \fd ScrollLockキー \fe PauseBreakキー \ff エスケープ文字は「\」(エンサイン)です。 エンサインを入力する場合 「\\」となります。 (マクロ定義はC言語の文字列としてプログラムするので、2重にエスケープする必要があります。そのため、実際の定義は「\\\\」となります。) コントロールキー、シフトキー、ALTキー及びWindowsキーには2通りの意味があります。 たとえば、「\A」は左シフトキーのキースキャンコードをPCに送出することを意味します。 ”同時押し”のコードは、後に続くキーコードを修飾します。単独で記述してもキーコードは送出されません。 「\1\2\3\4a」とした場合、「 a + ctrl + shift + alt + windows 」 が送出されます。 「\P」と「\p」を入れると、一定の待ち時間が入ります。PCのアプリケーションは人間がキーボードを叩くことを想定しているため、待ち時間を入れないと不都合が出る場合があります。 「\m」は「\!」と組み合わせて使用することを想定しています。短時間スイッチを押した場合、1回のみマクロキー入力が実行され、キーを押し続けた場合、マクロキーが連続して入力され続けます。 マウスのクリック操作がしたかったので、hidキーボードとマウスの複合デバイスになっています。 複合デバイスに対応していない環境では、マウスの部分は外してください。 (BIOS設定などに使う場合) ☆☆☆ 問題点 ※CapsLockの問題 CapsLockはoffの状態で使用してください。 キーボードのLED表示のためにcapslockの状態を取得することが可能になっているのですが、レスポンスが悪く使い物になりませんでした。 また、linuxの場合、capslockキーを一定以下の間隔で送出すると、PCがハングアップするケースがありました。 上記の理由により、CapsLockの状態には対処していないので、CapsLockがONになっていると正常に動作しません。 ※言語による差異 日本語配列のキーボードと、英語配列のキーボードでは、出力するキーコードが異なっています。PCのキーボード設定が英語キーボードになっていれば、マクロキーボードの方で英語キーボード配列に合わせる必要があります。 (プログラムではjp用の変換テーブルとus用の変換テーブルを分けてあるので、使用するPCに合わせてコンパイルしてください。) どちらかをコメントアウトする----------------------- /*#define uskey */ /* use usa type keyboard */ #define jpkey /* use OADG type keyboard */ ----------------------------------------------- ※マクロデータの長さ マクロはプログラムメモリ(rom)に格納されているため、容量の制限があります。配列は連続したメモリを要求するので、総容量に余裕が有っても配列が入るだけのメモリが確保出来ない場合も有ります。 ※漢字 漢字の入力は出来ないと思います。(全く学習機能の無いFEPならば可能か?) ) ☆☆☆ マクロの定義例 ブラウザを開く(http://jp.mouser.com) "\\4r\\P\\Prundll32.exe url.dll,FileProtocolHandler \"http://jp.mouser.com\"\\n" windowsキー + ファンクションキー1 "\\4\\f1" dos窓 開く "\\4r\\p\\pcmd\\n" my computer 開く "\\4r\\p\\p\\p\\p\\p\\p\\p\\t\\t\\t\\n" エクセル2003 コピー "\\l\\r\\Pc\\n" エクセル2003 値の貼り付け "\\l\\r\\Psv\\n" 出来上がり → MACROKE_14key_16F.zip ☆☆☆ 感想 ☆☆☆ 簡単に作れますが、これが結構便利に使えます。 PCからはキーボードデバイスに見えているため、複数接続しても、問題ありません。 (いくつでも増設可能) 頻繁にマクロの書き換えを行いたい向きには、「AUTOHOTKEY」と併用するのが良いと思います。 1ボタンでマクロが起動できるので、作業のテンポが格段に上がります。 追記 2013/08/30 懸案のCapsLock問題に対応しました。 CapsLockやNumLockの情報はPCからのOUTレポート中に格納されています。 マイクロチップのデモではこの情報を受けて、LEDを点灯しています。↓ ---------------------------------------------------- /******************************************************************** * Function: void USBHIDCBSetReportHandler(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: USBHIDCBSetReportHandler() is used to respond to * the HID device class specific SET_REPORT control * transfer request (starts with SETUP packet on EP0 OUT). * Note: *******************************************************************/ void USBHIDCBSetReportHandler(void) { //Prepare to receive the keyboard LED state data through a SET_REPORT //control transfer on endpoint 0. The host should only send 1 byte, //since this is all that the report descriptor allows it to send. USBEP0Receive((BYTE*)&CtrlTrfData, USB_EP0_BUFF_SIZE, USBHIDCBSetReportComplete); } //Secondary callback function that gets called when the above //control transfer completes for the USBHIDCBSetReportHandler() void USBHIDCBSetReportComplete(void) { //1 byte of LED state data should now be in the CtrlTrfData buffer. //Num Lock LED state is in Bit0. if(CtrlTrfData[0] & 0x01) //Make LED1 and LED2 match Num Lock state. { mLED_1_On(); mLED_2_On(); } else { mLED_1_Off(); mLED_2_Off(); } //Stop toggling the LEDs, so you can temporily see the Num lock LED state instead. //Once the CountdownTimerToShowUSBStatusOnLEDs reaches 0, the LEDs will go back to showing USB state instead. BlinkStatusValid = FALSE; CountdownTimerToShowUSBStatusOnLEDs = 140000; } ---------------------------------------------------------- やりたいことは、「現在のCapsLockの状態を取得する」です。 CapsLockの状態が取得できれば、大文字/小文字の入力についてCapsLockの影響を回避することができます。 (asciiコードと異なり、キースキャンコードには大文字/小文字の区別がありません。そのため、大文字の入力時には、シフトキーを同時に入力しています。CapsLockがonになっていると、大文字/小文字が逆になってしまいます) CapsLockの情報はPCが送出するOUTレポートから取得することができます。 キーボードはキーが押されていない時は、インタラプト転送に対しNACKで応答します。その場合、OUTレポートを得ることはできません。 そのため、キーボードデバイスがOUTレポートを受け取るためには、何かのキー情報を送出する必要があります。 ならば、ということで、空のレポートを送出してみましたが、OUTレポートに変化がありません。 ------------------------ hid_report_in[0] = 0x01; /* report ID = keyboard */ hid_report_in[1] = 0; hid_report_in[2] = 0; 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; hid_report_in[8] = 0; ------------------------- どうやら、空のレポートは無視されるようです。 キャラクタのスキャンコードを送出した場合はOUTレポートに変化が出ます。しかし、キャラクタのコードを送出すると、そのコードがキー入力されてしまうので、キーボードとしての本質的な動作に支障が発生します。 (さて、困りました) では、入力しても問題の無いコードならば送出しても問題が無い筈です。 そこで、CapsLockキーを2回送出してみました。 これはダメです。CapsLockキーを2回押すので、CapsLockのステータスは元の状態に戻る筈で、OUTレポートには操作前の情報が出力される筈だと期待しましたが、PCの方で遅延が発生するらしく、ある程度の間隔を置かないと正常に動作しません。 遅延をたくさん入れると動作しますが、マクロキーボードとしての動作が遅くなりすぎて使用に耐えません。 (またまた、困りました) そして・・・・その時天啓がありました。(単に思いつきとも言う) 「Scroll Lockを使えば善いのじゃ!!」 要らないキーの代表”ScrollLock”が使えます。 エクセルか何かでは未だに使っている様ですが、2回押して元に戻しているから、たぶん問題なし。 ------------------------ hid_report_in[0] = 0x01; /* report ID = keyboard */ hid_report_in[1] = 0; hid_report_in[2] = 0; hid_report_in[3] = 0x47; hid_report_in[4] = 0; hid_report_in[5] = 0; hid_report_in[6] = 0; hid_report_in[7] = 0; hid_report_in[8] = 0; ------------------------- やってみました、出来ました。 やっと解決。(パチパチ) → MACROKE_14key_16F_2.zip プログラムをそのままコンパイルした場合、キーマクロ定義は「部品やさんセット」になっています。 使用した開発環境はMPLAB IDE v8.85です。 特殊な事はしていないので、Xでも読み込めると思います。 |