极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3244|回复: 1

arduino + v-usb + Wii Classic Controller = USB手柄

[复制链接]
发表于 2015-5-28 16:55:11 | 显示全部楼层 |阅读模式
不得不说v-usb真强大,只需要两个稳压管+三个电阻就可以把arduino变成USB hid设备。
有了USB的协议,剩下的就是arduino和其他设备的通信了。

QQ图片20150528165237.jpg
QQ图片20150528165243.jpg
QQ图片20150528165248.png

改天再用万能线路板把元件焊上。
回复

使用道具 举报

 楼主| 发表于 2015-5-28 17:02:50 | 显示全部楼层
本帖最后由 雷精灵 于 2015-5-28 17:38 编辑

核心代码如下:

  1. #include <Wire.h>
  2. #include "WiiClassicController.h"
  3. extern "C"{
  4. #include <usbconfig.h>
  5. #include <usbdrv.h>
  6. };


  7. PROGMEM const char usbHidReportDescriptor[50] = {
  8.         0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
  9.         0x09, 0x05,                    // USAGE (Game Pad)
  10.         0xa1, 0x01,                    // COLLECTION (Application)
  11.         0xa1, 0x00,                    //   COLLECTION (Physical)
  12.         0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
  13.         0x09, 0x30,                    //     USAGE (X)
  14.         0x09, 0x31,                    //     USAGE (Y)
  15.         0x09, 0x32,                    //     USAGE (Z)
  16.         0x09, 0x33,                    //     USAGE (Rx)
  17.         0x09, 0x34,                    //     USAGE (Ry)
  18.         0x09, 0x35,                    //     USAGE (Rz)
  19.         0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
  20.         0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
  21.         0x95, 0x06,                    //     REPORT_COUNT (6)
  22.         0x75, 0x08,                    //     REPORT_SIZE (8)
  23.         0x81, 0x02,                    //     INPUT (Data,Var,Abs)
  24.         0x05, 0x09,                    //     USAGE_PAGE (Button)
  25.         0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
  26.         0x29, 0x10,                    //     USAGE_MAXIMUM (Button 16)
  27.         0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
  28.         0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
  29.         0x95, 0x10,                    //     REPORT_COUNT (16)
  30.         0x75, 0x01,                    //     REPORT_SIZE (1)
  31.         0x81, 0x02,                    //     INPUT (Data,Var,Abs)
  32.         0xc0,                          //   END_COLLECTION
  33.         0xc0                           // END_COLLECTION
  34. };


  35. #define LED        13


  36. static NormalizedWiiData wiiData;

  37. // not used for game pads
  38. static unsigned char idleRate;


  39. #ifdef __cplusplus
  40. extern "C"{
  41. #endif
  42. unsigned char usbFunctionSetup(unsigned char data[8]){
  43.         usbRequest_t* rq = (usbRequest_t*)data;

  44.         // there are several request types but we only need to handle
  45.         // 3 cases of the "class" type
  46.         if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) /* class request type */
  47.         {
  48.                 if (rq->bRequest == USBRQ_HID_GET_REPORT) /* wValue: ReportType (highbyte), ReportID (lowbyte) */
  49.                 {                       
  50.                         usbMsgPtr = (unsigned char*)&wiiData;
  51.                         return sizeof(wiiData);
  52.                 }
  53.                 else if (rq->bRequest == USBRQ_HID_GET_IDLE)
  54.                 {
  55.                         usbMsgPtr = (unsigned char*)&idleRate;
  56.                         return 1;
  57.                 }
  58.                 else if (rq->bRequest == USBRQ_HID_SET_IDLE)
  59.                 {
  60.                         idleRate = rq->wValue.bytes[1];
  61.                 }
  62.         }
  63.         else
  64.         {
  65.                 // no vendor specific requests implemented
  66.         }
  67.        
  68.         return 0;
  69. }
  70. #ifdef __cplusplus
  71. } // extern "C"
  72. #endif

  73. static int parity(int16_t value){
  74.         int16_t a = 0;
  75.         while(value){
  76.                 a ^= value;
  77.                 value >>= 1;
  78.         }
  79.         return a & 1;
  80. }

  81. void setup(){
  82.         /* add setup code here */
  83.         pinMode(LED, OUTPUT);        // For Test ONLY!!!


  84.         WiiClassicController.init();

  85.         cli();                // Disable Interrupt
  86.         usbInit();        // Start v-usb
  87.         usbDeviceDisconnect();        // Enforce USB re-enumeration, do this while interrupts are disabled!
  88.         delay(250);
  89.         usbDeviceConnect();
  90.         sei();                // Enable Interrupts
  91. }

  92. void loop(){
  93.         /* add main program code here */
  94.         usbPoll();

  95.         WiiClassicController.update();

  96.         WiiClassicController.read(&wiiData);

  97.         digitalWrite(LED, parity(*((int16_t*)&wiiData.buttons)));        // Use on-board LED to see the parity of buttons.

  98. /*
  99.         if(wiiData.buttons.a)Serial.println("A pressed.");
  100.         if(wiiData.buttons.b)Serial.println("B pressed.");
  101.         if(wiiData.buttons.x)Serial.println("X pressed.");
  102.         if(wiiData.buttons.y)Serial.println("Y pressed.");
  103.         if(wiiData.buttons.left)Serial.println("LEFT pressed.");
  104.         if(wiiData.buttons.right)Serial.println("RIGHT pressed.");
  105.         if(wiiData.buttons.up)Serial.println("UP pressed.");
  106.         if(wiiData.buttons.down)Serial.println("DOWN pressed.");
  107.         if(wiiData.buttons.l)Serial.println("L pressed.");
  108.         if(wiiData.buttons.r)Serial.println("R pressed.");
  109.         if(wiiData.buttons.zl)Serial.println("ZL pressed.");
  110.         if(wiiData.buttons.zr)Serial.println("ZR pressed.");
  111.         if(wiiData.buttons.plus)Serial.println("- pressed.");
  112.         if(wiiData.buttons.home)Serial.println("HOME pressed.");
  113.         if(wiiData.buttons.minus)Serial.println("+ pressed.");
  114. */
  115.        
  116.         // Wait until endpoint is ready
  117.         while(!usbInterruptIsReady())usbPoll();

  118.         // Send report
  119.         usbSetInterrupt((unsigned char*)(&wiiData), sizeof(wiiData));
  120. }
复制代码
使用了板载LED作为输入按键的状态显示。如果有奇数个按键按下,LED就亮起来。用来监视手柄工作状态挺不错的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )

GMT+8, 2019-11-14 02:23 , Processed in 0.053443 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表