手機 - Nokia N900 - 自製遊戲手把(A320機架)



AVR單晶片製作的N900手把


電路圖


原本要使用的藍牙手把




最後選定的材料


STM32F103開發板


裁切D-Pad和4顆按紐的面板以及PCB板


Micro USB和Mini USB傳輸線直接對接


底座


A320的Logo還是蠻好看的


固定位置


焊接


接線


外觀


背面就比較醜陋


支架固定


調整最佳的手感間距


用膠帶固定裸線


打一根樁腳


上架並焊接到STM32F103開發板


使用AB膠固定


開始蓋房子


側面


背面


使用塑鋼土補底


使用指甲油彩繪


光亮的背面


完成


側面


厚度有點厚,不過手感很棒


厚電池加上厚手把


手把底部使用沙紙磨圓,讓手感更好


這一面沒有可以固定的東西,因此,底部使用雙面膠替代,避免手把搖晃


手感相當不錯


由於司徒改裝的手把沒有Start、Select、L、R按鈕,因此,司徒只好使用音量+/-鍵(F7/F8)當作Start和Select按鈕,捨棄L、R按鈕,Mapping的方式如下:

$ sudo apt-get install xbindkeys xdotool
$ vim ~/.xbindkeysrc
"xdotool key q"
    F7
"xdotool key w"
    F8

$ xbindkeys

司徒將音量+/-改成q/w鍵,因此,在遊戲的Key Define中,使用者直接設定Start/Select成q/w即可

電路圖:


程式碼(修改自Keil MCBSTM32 Project):

unsigned char cur_state = 0;
unsigned char pre_state = 0;
unsigned char index = 2;
unsigned char buffer[8] = {0};

void PushKey(unsigned char key)
{
    if (index >= 5) {
        buffer[0] = 0x00;
        buffer[1] = 0x00;
        buffer[2] = 0x01;
        buffer[3] = 0x01;
        buffer[4] = 0x01;
        buffer[5] = 0x01;
        buffer[6] = 0x01;
        buffer[7] = 0x01;
    }
    else {
        buffer[index] = 4 + (key - 'a');
        index+= 1;
    }
}

int main(void)
{
    stm32_Init(); // STM32 Initialization
    GPIOA->CRL = 0x88888888;
    GPIOA->CRH = 0x88888888;
    GPIOA->ODR = 0x00000000;
    GPIOB->CRL = 0x88888888;
    GPIOB->CRH = 0x88888888;
    GPIOB->ODR = 0x00000000;

    USB_Init(); // USB Initialization
    USB_Connect(TRUE); // USB Connect
    while (1) {    
        cur_state = 0; 
        if (GPIOA->IDR & 0x100) { // PA8
            cur_state |= 0x01;
        }
        if (GPIOB->IDR & 0x8000) { // PB15
            cur_state |= 0x02;
        }
        if (GPIOB->IDR & 0x4000) { // PB14
            cur_state |= 0x04;
        }
        if (GPIOB->IDR & 0x2000) { // PB13
            cur_state |= 0x08;
        }
        if (GPIOB->IDR & 0x1000) { // PB12
            cur_state |= 0x10;
        }
        if (GPIOB->IDR & 0x800) { // PB11
            cur_state |= 0x20;
        }
        if (GPIOB->IDR & 0x4) { // PB2
            cur_state |= 0x40;
        }
        if (GPIOB->IDR & 0x400) { // PB10
            cur_state |= 0x80;
        }

        if (cur_state == pre_state) {
            continue;
        }
        pre_state = cur_state;

        index = 2;
        buffer[0] = 0x00;
        buffer[1] = 0x00;
        buffer[2] = 0x00;
        buffer[3] = 0x00;
        buffer[4] = 0x00;
        buffer[5] = 0x00;
        buffer[6] = 0x00;
        buffer[7] = 0x00;
        if (pre_state & 0x01) PushKey('a');
        if (pre_state & 0x02) PushKey('b');
        if (pre_state & 0x04) PushKey('c');
        if (pre_state & 0x08) PushKey('d');
        if (pre_state & 0x10) PushKey('e');
        if (pre_state & 0x20) PushKey('f');
        if (pre_state & 0x40) PushKey('g');
        if (pre_state & 0x80) PushKey('h');
        USB_WriteEP(0x81, buffer, sizeof(buffer));
    }
}