2010/11/26
Assembly Desk
ここでは、あそ~ぶUSB のサンプルプログラムを解説していきます。
ここではUSBジョイスティックを作成します。
外部に接続したスイッチを押すと、USBジョイスティックとして、予め決めておいたコマンドを入力するハードウェアマクロを作成します。
なお、本サンプルソースはMicrochip社のMCHPFSUSBver2.7を元にして作成しています。
この文章は、開発環境が既にインストールされている事を前提としてかかれています。
まだ、開発環境を整えて居ない方はこちらを参考にして、まずは開発環境を整えて下さい。
http://a-desk.jp/modules/forum_pic/index.php?cat_id=4
まだ、ファームウェアのビルドの仕方についてはこちらを参考にして下さい。
http://a-desk.jp/modules/forum_pic/index.php?cat_id=3
“joystick_sample”は次の様な、様々なファイルで構成されています。
これらのファイルには、USBの通信を行う為の様々な記述があります。
ここでは、手っ取り早くUSBマウスのソフトを作れる様になるための、最低限の説明を行います。
“main.c”このファイルを開いてください。
次の3つの関数を用いてコマンドマクロを実現しています。
まずは、”mouse.c”の中のUserInit関数を見ていきます。
ここは、プログラムが動きだしてから最初に一回だけ実行されます。
色々な初期化ルーチンを書く事が出来ます。
また、USB関係の初期化はこの関数が実行された後にやってくれるので、よっぽど変な設定をしない限りは正常に動作してくれます。
/******************************************************************************
* Function: void UserInit(void)
*****************************************************************************/
void UserInit(void)
{
TRISA = 0x03; //RA0,1を入力に
TRISB = 0;
LATB = 0;
// タイマ0の設定
// 内部48MHz動作、1/60s毎に割り込みを発生させる
// (1/60) / (4 / 48000000) / 8 = 25000
// 65536 - 25000 = 40536 = 0x9E58
OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_8);
WriteTimer0(WRITE_TIMER0);
// 割り込み開始
INTCON2bits.TMR0IP = 0; //タイマ0を低位レベル割り込みに設定
INTCONbits.TMR0IE = 1; //タイマ0割り込み許可
INTCONbits.GIEL = 1; //低位レベル割り込みの許可
joystick_input[0] = 0x00;
joystick_input[1] = 0x80;
joystick_input[2] = 0x80;
lastTransmission = 0;
}//end UserInit
まず、ポートの初期化を行います。
RA0,1を入力に設定し、後は出力とします。
次にタイマ0の設定をします。
これは、1/60s毎に割り込みを発生させる為に使用します。
この割り込みのタイミングで、コマンド入力を変更していきます。
ここでは、タイマ0の割り込みを低位レベル割り込みに設定しています。
これは、USB通信が高位レベル割り込みで処理されるため、それを阻害しない為の処置です。
なお、Microchip社のMCHPFSUSBver2.7を元にして、USB通信と同時に割り込みを用いる場合には、usb_config.hの
#define USB_POLLING
をコメントアウトし、
#define USB_INTERRUPT
を記述します。(このジョイスティックのソフトはそのようになっています)
joystick_input[0]~[2]を初期化します。
この配列にはPCに送付するジョイスティック操作情報が入ります。
なお、配列の意味は次の様になっています。
joystick_input[0] ビット0 | ボタン1 |
joystick_input[0] ビット1 | ボタン2 |
joystick_input[0] ビット2 | ボタン3 |
joystick_input[0] ビット3 | ボタン4 |
joystick_input[0] ビット4 | ボタン5 |
joystick_input[0] ビット5 | ボタン6 |
joystick_input[0] ビット6 | ボタン7 |
joystick_input[0] ビット7 | ボタン8 |
joystick_input[1] | X軸 |
joystick_input[2] | Y軸 |
lastTransmissionは後で使うUSB通信の管理を行う為の変数です。
削除しないでください。
Joystick関数では、ジョイスティックとして、PCにどのようなデータを送信するかを記述します。
/******************************************************************************
* Function: void Joystick(void)
*****************************************************************************/
void Joystick(void)
{
if(!HIDTxHandleBusy(lastTransmission))
{
if(!PORTAbits.RA0)
{
if(command_state == 0)
command_state = COMMAND_MACRO_COUNT;
}
lastTransmission = HIDTxPacket(HID_EP, (BYTE*)&joystick_input, sizeof(joystick_input));
}
return;
}//end joystick()
if(HIDTxHandleBusy(lastTransmission) == 0)このif文の中に、ASOOVUからPCに送信するデータを入れます。
送信するデータはjoystick_input配列にいれます。
ここでは、PORT A0に繋いだスイッチが押されていたらcommand_stateをCOMMAND_MACRO_COUNTにしています。
command_stateの値にしたがって、後で述べる割り込み処理でキー入力を行っています。
この関数は低位レベル割り込み処理関数です。
ここでは、UserInit関数で設定したタイマ0割り込みが1/60秒毎に呼び出されます。
void isr_low()
{
if(INTCONbits.TMR0IF == 1)
{
INTCONbits.TMR0IF = 0;
WriteTimer0(WRITE_TIMER0);
if(command_state != 0)
command_state--;
joystick_input[0] = command_macro[command_state][0];
joystick_input[1] = command_macro[command_state][1];
joystick_input[2] = command_macro[command_state][2];
}
} //This return will be a "retfie", since this is in a #pragma interruptlow section
この処理で予めcommand_macro配列に書きこんでおいたコマンドが後ろから順に1/60秒毎に入力される事になります。
サンプルでは、command_macroは次の様になっています。
// ここにコマンドを入れる。
// コマンドは後ろから順に実行される
#define COMMAND_MACRO_COUNT 4
BYTE command_macro[COMMAND_MACRO_COUNT][3] =
{{0x00,0x80,0x80}, //ここはいじっちゃダメ
{0x01,0xff,0xff},
{0x00,0x80,0xff},
{0x00,0xff,0x80}
};
これで、最初の1/60秒は配列の最後{0x00,0xff,0x80}がjoystick_input[0]~[2]に代入され、次の1/60秒で{0x00,0x80,0xff}が代入され、と言う形でマクロが実行されて行く事になります。
この例では、「右」 ->「下」 -> 「右下+ボタン1」と言う順番で実行される事になります。