Nokia N900

自製遊戲手把(A320機架)


相信在Google搜尋過N900手把的使用者,一定看過唯一一篇使用AVR單晶片製作的N900手把,如下圖:

司徒相當佩服該作者的巧思,利用鍵盤空間擺放手把,加上使用USB鍵盤製作,不需額外安裝驅動程式,雖然該作者使用PCB展示,不過可以看出整體體積相當小巧,因此,司徒決定參考該作者的想法製作並直接採用開發板的方式製作,節省開發時間。

此外,該作者相當熱心的提供程式碼以及電路圖,司徒相當欣賞願意開放程式碼的作者,因為這才會促進技術的發展。


原本司徒想要使用如下的藍牙手把改裝


但是,司徒想要的操作方式是DPad按鈕,不過這個藍牙手把的DPad卻是使用類比電阻,司徒只好打消使用該藍牙手把進行改裝的念頭


不然該手把應該是最佳首選,因為體積小、焊點夠大


最後選定的材料是Dingoo A320,由於司徒有兩台A320,加上A320的手感相當不錯,因此,成為最後的目標


接著,使用司徒現有的STM32F103開發板當作主要控制晶片


裁切DPad和4顆按紐的面板以及PCB板


STM32F103開發板使用Micro USB接頭,但是,N900是使用Mini USB接頭,司徒懶的慢慢焊接,因此,Micro USB和Mini USB傳輸線直接對接


物盡其用,A320背蓋拿來當底座


A320的Logo還是蠻好看的


固定STM32F103開發板和USB接頭的位置


焊接DPad的接線,由於共通腳位沒有被司徒剪斷,因此,只要拉五條線即可


焊接四顆按鈕的接線,因為焊點比DPad的更小,司徒只好用更細的漆包線


組裝看一下外觀,依然美麗動人


背面就比較醜陋


先用支架固定水平、垂直的距離


調整最佳的手感間距


用膠帶固定裸線


打一根樁腳


上架並焊接到STM32F103開發板


使用AB膠固定


開始蓋房子(使用Xperia Play背蓋、Nexus 4背蓋、iPhone 4藍牙鍵盤背面貼紙)


側面


背面


使用塑鋼土補底


使用指甲油彩繪


光亮的背面


完成


側面


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


厚電池加上厚手把


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


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


握在手上,手感相當不錯,現在玩遊戲的爽度真是百分百的爽


由於司徒改裝的手把沒有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, 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));
  }
}


返回上一頁