Library to use Arduino USB host shield on mbed

Dependents:   USBHOST_PS5

ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。

Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です https://os.mbed.com/media/uploads/kotakku/dffgfddswa.png

シールドについて

3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください

接続例

https://os.mbed.com/media/uploads/kotakku/esgsvfvhjrekldkcjxvb.png

使い方

Arduinoのコードと違うのはUSBのインスタンスの宣言部分のみです。
ピンを自分で指定できるようにしたので使いやすくなりました。

仕様

  • Arduinoのmillis関数、micros関数の移植のために内部でTimerクラスを使用しています。

main.cpp

#include "mbed.h"
#include <PS3BT.h>
#include <usbhub.h>

Serial pc(USBTX, USBRX, 115200);

//Nucleo f303k8用
USB Usb(A6, A5, A4, A3, A2); // mosi, miso, sclk, ssel, intr
BTD Btd(&Usb);
PS3BT PS3(&Btd);

int main()
{
    bool printAngle = false;

    if (Usb.Init() == -1)
    {
        pc.printf("\r\nOSC did not start");
        while (1); // Halt
    }
    pc.printf("\r\nPS3 USB Library Started");

    while (1)
    {
        Usb.Task();
        
        if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
            if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117)
            {
                pc.printf("\r\nLeftHatX: %d", PS3.getAnalogHat(LeftHatX));
                pc.printf("\tLeftHatY: %d", PS3.getAnalogHat(LeftHatY));
                if (PS3.PS3Connected)
                { // The Navigation controller only have one joystick
                    pc.printf("\tRightHatX: %d", PS3.getAnalogHat(RightHatX));
                    pc.printf("\tRightHatY: %d", PS3.getAnalogHat(RightHatY));
                }
            }
            // Analog button values can be read from almost all buttons
            if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2))
            {
                pc.printf("\r\nL2: %d", PS3.getAnalogButton(L2));
                if (!PS3.PS3NavigationConnected)
                {
                    pc.printf("\tR2: %d", PS3.getAnalogButton(R2));
                }
            }
            if (PS3.getButtonClick(PS))
            {
                PS3.disconnect();
                pc.printf("\r\nPS");
            }
    
            if (PS3.getButtonClick(TRIANGLE))
                pc.printf("\r\nTriangle");
            if (PS3.getButtonClick(CIRCLE))
                pc.printf("\r\nCircle");
            if (PS3.getButtonClick(CROSS))
                pc.printf("\r\nCross");
            if (PS3.getButtonClick(SQUARE))
                pc.printf("\r\nSquare");
    
            if (PS3.getButtonClick(UP))
            {
                pc.printf("\r\nUp");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED4);
            }
            if (PS3.getButtonClick(RIGHT))
            {
                pc.printf("\r\nRight");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED1);
            }
            if (PS3.getButtonClick(DOWN))
            {
                pc.printf("\r\nDown");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED2);
            }
            if (PS3.getButtonClick(LEFT))
            {
                pc.printf("\r\nLeft");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED3);
            }
    
            if (PS3.getButtonClick(L1))
                pc.printf("\r\nL1");
            if (PS3.getButtonClick(L3))
                pc.printf("\r\nL3");
            if (PS3.getButtonClick(R1))
                pc.printf("\r\nR1");
            if (PS3.getButtonClick(R3))
                pc.printf("\r\nR3");
    
            if (PS3.getButtonClick(SELECT))
            {
                pc.printf("\r\nSelect - ");
                PS3.printStatusString();
            }
            if (PS3.getButtonClick(START))
            {
                pc.printf("\r\nStart");
                printAngle = !printAngle;
            }
            if (printAngle)
            {
                pc.printf("\r\nPitch: %.3lf", PS3.getAngle(Pitch));
                pc.printf("\tRoll: %.3lf", PS3.getAngle(Roll));
            }
        }
        else
        {
            pc.printf("not connect\n");
        }
    }
}
Committer:
kotakku
Date:
Sat Jan 18 15:06:35 2020 +0000
Revision:
0:b1ce54272580
1.0.0 first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kotakku 0:b1ce54272580 1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
kotakku 0:b1ce54272580 2
kotakku 0:b1ce54272580 3 This software may be distributed and modified under the terms of the GNU
kotakku 0:b1ce54272580 4 General Public License version 2 (GPL2) as published by the Free Software
kotakku 0:b1ce54272580 5 Foundation and appearing in the file GPL2.TXT included in the packaging of
kotakku 0:b1ce54272580 6 this file. Please note that GPL2 Section 2[b] requires that all works based
kotakku 0:b1ce54272580 7 on this software must also be made publicly available under the terms of
kotakku 0:b1ce54272580 8 the GPL2 ("Copyleft").
kotakku 0:b1ce54272580 9
kotakku 0:b1ce54272580 10 Contact information
kotakku 0:b1ce54272580 11 -------------------
kotakku 0:b1ce54272580 12
kotakku 0:b1ce54272580 13 Kristian Lauszus, TKJ Electronics
kotakku 0:b1ce54272580 14 Web : http://www.tkjelectronics.com
kotakku 0:b1ce54272580 15 e-mail : kristianl@tkjelectronics.com
kotakku 0:b1ce54272580 16
kotakku 0:b1ce54272580 17 IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus
kotakku 0:b1ce54272580 18 */
kotakku 0:b1ce54272580 19
kotakku 0:b1ce54272580 20 #include "Wii.h"
kotakku 0:b1ce54272580 21 // To enable serial debugging see "settings.h"
kotakku 0:b1ce54272580 22 //#define EXTRADEBUG // Uncomment to get even more debugging data
kotakku 0:b1ce54272580 23 //#define PRINTREPORT // Uncomment to print the report send by the Wii controllers
kotakku 0:b1ce54272580 24
kotakku 0:b1ce54272580 25 const uint8_t WII_LEDS[] PROGMEM = {
kotakku 0:b1ce54272580 26 0x00, // OFF
kotakku 0:b1ce54272580 27 0x10, // LED1
kotakku 0:b1ce54272580 28 0x20, // LED2
kotakku 0:b1ce54272580 29 0x40, // LED3
kotakku 0:b1ce54272580 30 0x80, // LED4
kotakku 0:b1ce54272580 31
kotakku 0:b1ce54272580 32 0x90, // LED5
kotakku 0:b1ce54272580 33 0xA0, // LED6
kotakku 0:b1ce54272580 34 0xC0, // LED7
kotakku 0:b1ce54272580 35 0xD0, // LED8
kotakku 0:b1ce54272580 36 0xE0, // LED9
kotakku 0:b1ce54272580 37 0xF0, // LED10
kotakku 0:b1ce54272580 38 };
kotakku 0:b1ce54272580 39
kotakku 0:b1ce54272580 40 const uint32_t WII_BUTTONS[] PROGMEM = {
kotakku 0:b1ce54272580 41 0x00008, // UP
kotakku 0:b1ce54272580 42 0x00002, // RIGHT
kotakku 0:b1ce54272580 43 0x00004, // DOWN
kotakku 0:b1ce54272580 44 0x00001, // LEFT
kotakku 0:b1ce54272580 45
kotakku 0:b1ce54272580 46 0, // Skip
kotakku 0:b1ce54272580 47 0x00010, // PLUS
kotakku 0:b1ce54272580 48 0x00100, // TWO
kotakku 0:b1ce54272580 49 0x00200, // ONE
kotakku 0:b1ce54272580 50
kotakku 0:b1ce54272580 51 0x01000, // MINUS
kotakku 0:b1ce54272580 52 0x08000, // HOME
kotakku 0:b1ce54272580 53 0x10000, // Z
kotakku 0:b1ce54272580 54 0x20000, // C
kotakku 0:b1ce54272580 55
kotakku 0:b1ce54272580 56 0x00400, // B
kotakku 0:b1ce54272580 57 0x00800, // A
kotakku 0:b1ce54272580 58 };
kotakku 0:b1ce54272580 59 const uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = {
kotakku 0:b1ce54272580 60 0x00100, // UP
kotakku 0:b1ce54272580 61 0x00080, // RIGHT
kotakku 0:b1ce54272580 62 0x00040, // DOWN
kotakku 0:b1ce54272580 63 0x00200, // LEFT
kotakku 0:b1ce54272580 64
kotakku 0:b1ce54272580 65 0, // Skip
kotakku 0:b1ce54272580 66 0x00004, // PLUS
kotakku 0:b1ce54272580 67 0x20000, // L3
kotakku 0:b1ce54272580 68 0x10000, // R3
kotakku 0:b1ce54272580 69
kotakku 0:b1ce54272580 70 0x00010, // MINUS
kotakku 0:b1ce54272580 71 0x00008, // HOME
kotakku 0:b1ce54272580 72 0, 0, // Skip
kotakku 0:b1ce54272580 73
kotakku 0:b1ce54272580 74 0x04000, // B
kotakku 0:b1ce54272580 75 0x01000, // A
kotakku 0:b1ce54272580 76 0x00800, // X
kotakku 0:b1ce54272580 77 0x02000, // Y
kotakku 0:b1ce54272580 78
kotakku 0:b1ce54272580 79 0x00020, // L
kotakku 0:b1ce54272580 80 0x00002, // R
kotakku 0:b1ce54272580 81 0x08000, // ZL
kotakku 0:b1ce54272580 82 0x00400, // ZR
kotakku 0:b1ce54272580 83 };
kotakku 0:b1ce54272580 84
kotakku 0:b1ce54272580 85 WII::WII(BTD *p, bool pair) :
kotakku 0:b1ce54272580 86 BluetoothService(p) // Pointer to USB class instance - mandatory
kotakku 0:b1ce54272580 87 {
kotakku 0:b1ce54272580 88 pBtd->pairWithWii = pair;
kotakku 0:b1ce54272580 89
kotakku 0:b1ce54272580 90 HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 91
kotakku 0:b1ce54272580 92 /* Set device cid for the control and intterrupt channelse - LSB */
kotakku 0:b1ce54272580 93 control_dcid[0] = 0x60; // 0x0060
kotakku 0:b1ce54272580 94 control_dcid[1] = 0x00;
kotakku 0:b1ce54272580 95 interrupt_dcid[0] = 0x61; // 0x0061
kotakku 0:b1ce54272580 96 interrupt_dcid[1] = 0x00;
kotakku 0:b1ce54272580 97
kotakku 0:b1ce54272580 98 Reset();
kotakku 0:b1ce54272580 99 }
kotakku 0:b1ce54272580 100
kotakku 0:b1ce54272580 101 void WII::Reset() {
kotakku 0:b1ce54272580 102 wiimoteConnected = false;
kotakku 0:b1ce54272580 103 nunchuckConnected = false;
kotakku 0:b1ce54272580 104 motionPlusConnected = false;
kotakku 0:b1ce54272580 105 activateNunchuck = false;
kotakku 0:b1ce54272580 106 motionValuesReset = false;
kotakku 0:b1ce54272580 107 activeConnection = false;
kotakku 0:b1ce54272580 108 motionPlusInside = false;
kotakku 0:b1ce54272580 109 pBtd->wiiUProController = false;
kotakku 0:b1ce54272580 110 wiiUProControllerConnected = false;
kotakku 0:b1ce54272580 111 wiiBalanceBoardConnected = false;
kotakku 0:b1ce54272580 112 l2cap_event_flag = 0; // Reset flags
kotakku 0:b1ce54272580 113 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 114 }
kotakku 0:b1ce54272580 115
kotakku 0:b1ce54272580 116 void WII::disconnect() { // Use this void to disconnect any of the controllers
kotakku 0:b1ce54272580 117 if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect
kotakku 0:b1ce54272580 118 if(motionPlusConnected) {
kotakku 0:b1ce54272580 119 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 120 Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80);
kotakku 0:b1ce54272580 121 #endif
kotakku 0:b1ce54272580 122 initExtension1(); // This will disable the Motion Plus extension
kotakku 0:b1ce54272580 123 }
kotakku 0:b1ce54272580 124 timer = (uint32_t)millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated
kotakku 0:b1ce54272580 125 } else
kotakku 0:b1ce54272580 126 timer = (uint32_t)millis(); // Don't wait
kotakku 0:b1ce54272580 127 // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
kotakku 0:b1ce54272580 128 pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
kotakku 0:b1ce54272580 129 Reset();
kotakku 0:b1ce54272580 130 l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
kotakku 0:b1ce54272580 131 }
kotakku 0:b1ce54272580 132
kotakku 0:b1ce54272580 133 void WII::ACLData(uint8_t* l2capinbuf) {
kotakku 0:b1ce54272580 134 if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) {
kotakku 0:b1ce54272580 135 if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
kotakku 0:b1ce54272580 136 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
kotakku 0:b1ce54272580 137 motionPlusInside = pBtd->motionPlusInside;
kotakku 0:b1ce54272580 138 pBtd->incomingWii = false;
kotakku 0:b1ce54272580 139 pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
kotakku 0:b1ce54272580 140 activeConnection = true;
kotakku 0:b1ce54272580 141 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
kotakku 0:b1ce54272580 142 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 143 }
kotakku 0:b1ce54272580 144 }
kotakku 0:b1ce54272580 145 }
kotakku 0:b1ce54272580 146
kotakku 0:b1ce54272580 147 if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
kotakku 0:b1ce54272580 148 if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
kotakku 0:b1ce54272580 149 if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
kotakku 0:b1ce54272580 150 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 151 Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
kotakku 0:b1ce54272580 152 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 153 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 154 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
kotakku 0:b1ce54272580 155 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 156 D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
kotakku 0:b1ce54272580 157 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 158 D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
kotakku 0:b1ce54272580 159 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 160 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
kotakku 0:b1ce54272580 161 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 162 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 163 #endif
kotakku 0:b1ce54272580 164 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
kotakku 0:b1ce54272580 165 if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
kotakku 0:b1ce54272580 166 if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
kotakku 0:b1ce54272580 167 //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
kotakku 0:b1ce54272580 168 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 169 control_scid[0] = l2capinbuf[12];
kotakku 0:b1ce54272580 170 control_scid[1] = l2capinbuf[13];
kotakku 0:b1ce54272580 171 l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);
kotakku 0:b1ce54272580 172 } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 173 //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
kotakku 0:b1ce54272580 174 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 175 interrupt_scid[0] = l2capinbuf[12];
kotakku 0:b1ce54272580 176 interrupt_scid[1] = l2capinbuf[13];
kotakku 0:b1ce54272580 177 l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);
kotakku 0:b1ce54272580 178 }
kotakku 0:b1ce54272580 179 }
kotakku 0:b1ce54272580 180 } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
kotakku 0:b1ce54272580 181 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 182 Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
kotakku 0:b1ce54272580 183 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 184 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 185 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
kotakku 0:b1ce54272580 186 Notify(PSTR(" SCID: "), 0x80);
kotakku 0:b1ce54272580 187 D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
kotakku 0:b1ce54272580 188 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 189 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 190 Notify(PSTR(" Identifier: "), 0x80);
kotakku 0:b1ce54272580 191 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
kotakku 0:b1ce54272580 192 #endif
kotakku 0:b1ce54272580 193 if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
kotakku 0:b1ce54272580 194 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 195 control_scid[0] = l2capinbuf[14];
kotakku 0:b1ce54272580 196 control_scid[1] = l2capinbuf[15];
kotakku 0:b1ce54272580 197 l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
kotakku 0:b1ce54272580 198 } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
kotakku 0:b1ce54272580 199 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 200 interrupt_scid[0] = l2capinbuf[14];
kotakku 0:b1ce54272580 201 interrupt_scid[1] = l2capinbuf[15];
kotakku 0:b1ce54272580 202 l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
kotakku 0:b1ce54272580 203 }
kotakku 0:b1ce54272580 204 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
kotakku 0:b1ce54272580 205 if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
kotakku 0:b1ce54272580 206 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 207 //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
kotakku 0:b1ce54272580 208 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 209 l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
kotakku 0:b1ce54272580 210 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 211 //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
kotakku 0:b1ce54272580 212 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 213 l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
kotakku 0:b1ce54272580 214 }
kotakku 0:b1ce54272580 215 }
kotakku 0:b1ce54272580 216 } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
kotakku 0:b1ce54272580 217 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 218 //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
kotakku 0:b1ce54272580 219 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
kotakku 0:b1ce54272580 220 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 221 //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
kotakku 0:b1ce54272580 222 pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
kotakku 0:b1ce54272580 223 }
kotakku 0:b1ce54272580 224 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
kotakku 0:b1ce54272580 225 if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
kotakku 0:b1ce54272580 226 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 227 Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
kotakku 0:b1ce54272580 228 #endif
kotakku 0:b1ce54272580 229 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 230 pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
kotakku 0:b1ce54272580 231 Reset();
kotakku 0:b1ce54272580 232 } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
kotakku 0:b1ce54272580 233 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 234 Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 235 #endif
kotakku 0:b1ce54272580 236 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 237 pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
kotakku 0:b1ce54272580 238 Reset();
kotakku 0:b1ce54272580 239 }
kotakku 0:b1ce54272580 240 } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
kotakku 0:b1ce54272580 241 if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
kotakku 0:b1ce54272580 242 //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
kotakku 0:b1ce54272580 243 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 244 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
kotakku 0:b1ce54272580 245 } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
kotakku 0:b1ce54272580 246 //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 247 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 248 l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
kotakku 0:b1ce54272580 249 }
kotakku 0:b1ce54272580 250 }
kotakku 0:b1ce54272580 251 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 252 else {
kotakku 0:b1ce54272580 253 identifier = l2capinbuf[9];
kotakku 0:b1ce54272580 254 Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
kotakku 0:b1ce54272580 255 D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
kotakku 0:b1ce54272580 256 }
kotakku 0:b1ce54272580 257 #endif
kotakku 0:b1ce54272580 258 } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
kotakku 0:b1ce54272580 259 //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
kotakku 0:b1ce54272580 260 if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
kotakku 0:b1ce54272580 261 if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons
kotakku 0:b1ce54272580 262 if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes
kotakku 0:b1ce54272580 263 ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
kotakku 0:b1ce54272580 264 else if(wiiUProControllerConnected)
kotakku 0:b1ce54272580 265 ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));
kotakku 0:b1ce54272580 266 else if(motionPlusConnected) {
kotakku 0:b1ce54272580 267 if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus
kotakku 0:b1ce54272580 268 ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));
kotakku 0:b1ce54272580 269 else if(nunchuckConnected) // Update if it's a report from the Nunchuck
kotakku 0:b1ce54272580 270 ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));
kotakku 0:b1ce54272580 271 //else if(classicControllerConnected) // Update if it's a report from the Classic Controller
kotakku 0:b1ce54272580 272 } else if(nunchuckConnected) // The Nunchuck is directly connected
kotakku 0:b1ce54272580 273 ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16));
kotakku 0:b1ce54272580 274 //else if(classicControllerConnected) // The Classic Controller is directly connected
kotakku 0:b1ce54272580 275 else if(!unknownExtensionConnected)
kotakku 0:b1ce54272580 276 ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
kotakku 0:b1ce54272580 277 #ifdef PRINTREPORT
kotakku 0:b1ce54272580 278 Notify(PSTR("ButtonState: "), 0x80);
kotakku 0:b1ce54272580 279 D_PrintHex<uint32_t > (ButtonState, 0x80);
kotakku 0:b1ce54272580 280 Notify(PSTR("\r\n"), 0x80);
kotakku 0:b1ce54272580 281 #endif
kotakku 0:b1ce54272580 282 if(ButtonState != OldButtonState) {
kotakku 0:b1ce54272580 283 ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
kotakku 0:b1ce54272580 284 OldButtonState = ButtonState;
kotakku 0:b1ce54272580 285 }
kotakku 0:b1ce54272580 286 }
kotakku 0:b1ce54272580 287 if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer
kotakku 0:b1ce54272580 288 accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500;
kotakku 0:b1ce54272580 289 accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500;
kotakku 0:b1ce54272580 290 accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500;
kotakku 0:b1ce54272580 291 }
kotakku 0:b1ce54272580 292 switch(l2capinbuf[9]) {
kotakku 0:b1ce54272580 293 case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV
kotakku 0:b1ce54272580 294 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 295 Notify(PSTR("\r\nStatus report was received"), 0x80);
kotakku 0:b1ce54272580 296 #endif
kotakku 0:b1ce54272580 297 wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
kotakku 0:b1ce54272580 298 batteryLevel = l2capinbuf[15]; // Update battery level
kotakku 0:b1ce54272580 299
kotakku 0:b1ce54272580 300 if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel()
kotakku 0:b1ce54272580 301 if(l2capinbuf[12] & 0x02) { // Check if a extension is connected
kotakku 0:b1ce54272580 302 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 303 if(!unknownExtensionConnected)
kotakku 0:b1ce54272580 304 Notify(PSTR("\r\nExtension connected"), 0x80);
kotakku 0:b1ce54272580 305 #endif
kotakku 0:b1ce54272580 306 unknownExtensionConnected = true;
kotakku 0:b1ce54272580 307 #ifdef WIICAMERA
kotakku 0:b1ce54272580 308 if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
kotakku 0:b1ce54272580 309 #endif
kotakku 0:b1ce54272580 310 setReportMode(false, 0x35); // Also read the extension
kotakku 0:b1ce54272580 311 } else {
kotakku 0:b1ce54272580 312 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 313 Notify(PSTR("\r\nExtension disconnected"), 0x80);
kotakku 0:b1ce54272580 314 #endif
kotakku 0:b1ce54272580 315 if(motionPlusConnected) {
kotakku 0:b1ce54272580 316 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 317 Notify(PSTR(" - from Motion Plus"), 0x80);
kotakku 0:b1ce54272580 318 #endif
kotakku 0:b1ce54272580 319 wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
kotakku 0:b1ce54272580 320 if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false
kotakku 0:b1ce54272580 321 nunchuckConnected = false;
kotakku 0:b1ce54272580 322 //else if(classicControllerConnected)
kotakku 0:b1ce54272580 323 } else if(nunchuckConnected) {
kotakku 0:b1ce54272580 324 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 325 Notify(PSTR(" - Nunchuck"), 0x80);
kotakku 0:b1ce54272580 326 #endif
kotakku 0:b1ce54272580 327 nunchuckConnected = false; // It must be the Nunchuck controller then
kotakku 0:b1ce54272580 328 wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
kotakku 0:b1ce54272580 329 onInit();
kotakku 0:b1ce54272580 330 #ifdef WIICAMERA
kotakku 0:b1ce54272580 331 if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
kotakku 0:b1ce54272580 332 #endif
kotakku 0:b1ce54272580 333 setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
kotakku 0:b1ce54272580 334 } else {
kotakku 0:b1ce54272580 335 #ifdef WIICAMERA
kotakku 0:b1ce54272580 336 if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
kotakku 0:b1ce54272580 337 #endif
kotakku 0:b1ce54272580 338 setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
kotakku 0:b1ce54272580 339 }
kotakku 0:b1ce54272580 340 }
kotakku 0:b1ce54272580 341 }
kotakku 0:b1ce54272580 342 else {
kotakku 0:b1ce54272580 343 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 344 Notify(PSTR("\r\nChecking battery level"), 0x80);
kotakku 0:b1ce54272580 345 #endif
kotakku 0:b1ce54272580 346 checkBatteryLevel = false; // Check for extensions by default
kotakku 0:b1ce54272580 347 }
kotakku 0:b1ce54272580 348 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 349 if(l2capinbuf[12] & 0x01)
kotakku 0:b1ce54272580 350 Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
kotakku 0:b1ce54272580 351 #endif
kotakku 0:b1ce54272580 352
kotakku 0:b1ce54272580 353 break;
kotakku 0:b1ce54272580 354 case 0x21: // Read Memory Data
kotakku 0:b1ce54272580 355 if((l2capinbuf[12] & 0x0F) == 0) { // No error
kotakku 0:b1ce54272580 356 uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1
kotakku 0:b1ce54272580 357 // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
kotakku 0:b1ce54272580 358 if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {
kotakku 0:b1ce54272580 359 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 360 Notify(PSTR("\r\nNunchuck connected"), 0x80);
kotakku 0:b1ce54272580 361 #endif
kotakku 0:b1ce54272580 362 wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED);
kotakku 0:b1ce54272580 363 } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) {
kotakku 0:b1ce54272580 364 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 365 Notify(PSTR("\r\nMotion Plus connected"), 0x80);
kotakku 0:b1ce54272580 366 #endif
kotakku 0:b1ce54272580 367 wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED);
kotakku 0:b1ce54272580 368 } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) {
kotakku 0:b1ce54272580 369 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 370 Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80);
kotakku 0:b1ce54272580 371 #endif
kotakku 0:b1ce54272580 372 motionPlusConnected = true;
kotakku 0:b1ce54272580 373 #ifdef WIICAMERA
kotakku 0:b1ce54272580 374 if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
kotakku 0:b1ce54272580 375 #endif
kotakku 0:b1ce54272580 376 setReportMode(false, 0x35); // Also read the extension
kotakku 0:b1ce54272580 377 } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) {
kotakku 0:b1ce54272580 378 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 379 Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80);
kotakku 0:b1ce54272580 380 #endif
kotakku 0:b1ce54272580 381 activateNunchuck = false;
kotakku 0:b1ce54272580 382 motionPlusConnected = true;
kotakku 0:b1ce54272580 383 nunchuckConnected = true;
kotakku 0:b1ce54272580 384 #ifdef WIICAMERA
kotakku 0:b1ce54272580 385 if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
kotakku 0:b1ce54272580 386 #endif
kotakku 0:b1ce54272580 387 setReportMode(false, 0x35); // Also read the extension
kotakku 0:b1ce54272580 388 } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) {
kotakku 0:b1ce54272580 389 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 390 Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80);
kotakku 0:b1ce54272580 391 Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80);
kotakku 0:b1ce54272580 392 #endif
kotakku 0:b1ce54272580 393 stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE"
kotakku 0:b1ce54272580 394 } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) {
kotakku 0:b1ce54272580 395 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 396 Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
kotakku 0:b1ce54272580 397 #endif
kotakku 0:b1ce54272580 398 wiiUProControllerConnected = true;
kotakku 0:b1ce54272580 399 } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) {
kotakku 0:b1ce54272580 400 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 401 Notify(PSTR("\r\nWii Balance Board connected"), 0x80);
kotakku 0:b1ce54272580 402 #endif
kotakku 0:b1ce54272580 403 setReportMode(false, 0x32); // Read the Wii Balance Board extension
kotakku 0:b1ce54272580 404 wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
kotakku 0:b1ce54272580 405 }
kotakku 0:b1ce54272580 406 // Wii Balance Board calibration reports (24 bits in total)
kotakku 0:b1ce54272580 407 else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit
kotakku 0:b1ce54272580 408 for(uint8_t i = 0; i < 2; i++) {
kotakku 0:b1ce54272580 409 for(uint8_t j = 0; j < 4; j++)
kotakku 0:b1ce54272580 410 wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8;
kotakku 0:b1ce54272580 411 }
kotakku 0:b1ce54272580 412 } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit
kotakku 0:b1ce54272580 413 for(uint8_t j = 0; j < 4; j++)
kotakku 0:b1ce54272580 414 wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8;
kotakku 0:b1ce54272580 415 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 416 Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80);
kotakku 0:b1ce54272580 417 #endif
kotakku 0:b1ce54272580 418 wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
kotakku 0:b1ce54272580 419 wiiBalanceBoardConnected = true;
kotakku 0:b1ce54272580 420 }
kotakku 0:b1ce54272580 421 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 422 else {
kotakku 0:b1ce54272580 423 Notify(PSTR("\r\nUnknown Device: "), 0x80);
kotakku 0:b1ce54272580 424 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 425 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 426 Notify(PSTR("\r\nData: "), 0x80);
kotakku 0:b1ce54272580 427 for(uint8_t i = 0; i < reportLength; i++) {
kotakku 0:b1ce54272580 428 D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);
kotakku 0:b1ce54272580 429 Notify(PSTR(" "), 0x80);
kotakku 0:b1ce54272580 430 }
kotakku 0:b1ce54272580 431 }
kotakku 0:b1ce54272580 432 #endif
kotakku 0:b1ce54272580 433 }
kotakku 0:b1ce54272580 434 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 435 else {
kotakku 0:b1ce54272580 436 Notify(PSTR("\r\nReport Error: "), 0x80);
kotakku 0:b1ce54272580 437 D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
kotakku 0:b1ce54272580 438 D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
kotakku 0:b1ce54272580 439 }
kotakku 0:b1ce54272580 440 #endif
kotakku 0:b1ce54272580 441 break;
kotakku 0:b1ce54272580 442 case 0x22: // Acknowledge output report, return function result
kotakku 0:b1ce54272580 443 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 444 if(l2capinbuf[13] != 0x00) { // Check if there is an error
kotakku 0:b1ce54272580 445 Notify(PSTR("\r\nCommand failed: "), 0x80);
kotakku 0:b1ce54272580 446 D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
kotakku 0:b1ce54272580 447 }
kotakku 0:b1ce54272580 448 #endif
kotakku 0:b1ce54272580 449 break;
kotakku 0:b1ce54272580 450 case 0x30: // Core buttons - (a1) 30 BB BB
kotakku 0:b1ce54272580 451 break;
kotakku 0:b1ce54272580 452 case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
kotakku 0:b1ce54272580 453 break;
kotakku 0:b1ce54272580 454 case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
kotakku 0:b1ce54272580 455 // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format
kotakku 0:b1ce54272580 456 wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right
kotakku 0:b1ce54272580 457 wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right
kotakku 0:b1ce54272580 458 wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left
kotakku 0:b1ce54272580 459 wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left
kotakku 0:b1ce54272580 460 break;
kotakku 0:b1ce54272580 461 case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II
kotakku 0:b1ce54272580 462 #ifdef WIICAMERA
kotakku 0:b1ce54272580 463 // Read the IR data
kotakku 0:b1ce54272580 464 IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position
kotakku 0:b1ce54272580 465 IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position
kotakku 0:b1ce54272580 466 IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15
kotakku 0:b1ce54272580 467
kotakku 0:b1ce54272580 468 IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4));
kotakku 0:b1ce54272580 469 IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2));
kotakku 0:b1ce54272580 470 IR_object_s2 = (l2capinbuf[20] & 0x0F);
kotakku 0:b1ce54272580 471
kotakku 0:b1ce54272580 472 IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4));
kotakku 0:b1ce54272580 473 IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2));
kotakku 0:b1ce54272580 474 IR_object_s3 = (l2capinbuf[23] & 0x0F);
kotakku 0:b1ce54272580 475
kotakku 0:b1ce54272580 476 IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4));
kotakku 0:b1ce54272580 477 IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2));
kotakku 0:b1ce54272580 478 IR_object_s4 = (l2capinbuf[26] & 0x0F);
kotakku 0:b1ce54272580 479 #endif
kotakku 0:b1ce54272580 480 break;
kotakku 0:b1ce54272580 481 case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
kotakku 0:b1ce54272580 482 break;
kotakku 0:b1ce54272580 483 /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */
kotakku 0:b1ce54272580 484 case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes
kotakku 0:b1ce54272580 485 // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II
kotakku 0:b1ce54272580 486 // corresponds to output report mode 0x3e
kotakku 0:b1ce54272580 487
kotakku 0:b1ce54272580 488 /**** for reading in full mode: DOES NOT WORK YET ****/
kotakku 0:b1ce54272580 489 /* When it works it will also have intensity and bounding box data */
kotakku 0:b1ce54272580 490 /*
kotakku 0:b1ce54272580 491 IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
kotakku 0:b1ce54272580 492 IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
kotakku 0:b1ce54272580 493 IR_object_s1 = (l2capinbuf[15] & 0x0F);
kotakku 0:b1ce54272580 494 */
kotakku 0:b1ce54272580 495 break;
kotakku 0:b1ce54272580 496 case 0x3F:
kotakku 0:b1ce54272580 497 /*
kotakku 0:b1ce54272580 498 IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
kotakku 0:b1ce54272580 499 IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
kotakku 0:b1ce54272580 500 IR_object_s1 = (l2capinbuf[15] & 0x0F);
kotakku 0:b1ce54272580 501 */
kotakku 0:b1ce54272580 502 break;
kotakku 0:b1ce54272580 503 case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes
kotakku 0:b1ce54272580 504 // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
kotakku 0:b1ce54272580 505 #if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot!
kotakku 0:b1ce54272580 506 if(motionPlusConnected) {
kotakku 0:b1ce54272580 507 if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension
kotakku 0:b1ce54272580 508 if(motionValuesReset) { // We will only use the values when the gyro value has been set
kotakku 0:b1ce54272580 509 gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero);
kotakku 0:b1ce54272580 510 gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);
kotakku 0:b1ce54272580 511 gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);
kotakku 0:b1ce54272580 512
kotakku 0:b1ce54272580 513 yawGyroSpeed = (float)gyroYawRaw / ((float)gyroYawZero / yawGyroScale);
kotakku 0:b1ce54272580 514 rollGyroSpeed = -(float)gyroRollRaw / ((float)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values
kotakku 0:b1ce54272580 515 pitchGyroSpeed = (float)gyroPitchRaw / ((float)gyroPitchZero / pitchGyroScale);
kotakku 0:b1ce54272580 516
kotakku 0:b1ce54272580 517 /* The onboard gyro has two ranges for slow and fast mode */
kotakku 0:b1ce54272580 518 if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used
kotakku 0:b1ce54272580 519 yawGyroSpeed *= 4.545;
kotakku 0:b1ce54272580 520 if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used
kotakku 0:b1ce54272580 521 pitchGyroSpeed *= 4.545;
kotakku 0:b1ce54272580 522 if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used
kotakku 0:b1ce54272580 523 rollGyroSpeed *= 4.545;
kotakku 0:b1ce54272580 524
kotakku 0:b1ce54272580 525 compPitch = (0.93f * (compPitch + (pitchGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimotePitch()); // Use a complimentary filter to calculate the angle
kotakku 0:b1ce54272580 526 compRoll = (0.93f * (compRoll + (rollGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimoteRoll());
kotakku 0:b1ce54272580 527
kotakku 0:b1ce54272580 528 gyroYaw += (yawGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
kotakku 0:b1ce54272580 529 gyroRoll += (rollGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
kotakku 0:b1ce54272580 530 gyroPitch += (pitchGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
kotakku 0:b1ce54272580 531 timer = (uint32_t)micros();
kotakku 0:b1ce54272580 532 /*
kotakku 0:b1ce54272580 533 // Uncomment these lines to tune the gyro scale variabels
kotakku 0:b1ce54272580 534 Notify(PSTR("\r\ngyroYaw: "), 0x80);
kotakku 0:b1ce54272580 535 Notify(gyroYaw, 0x80);
kotakku 0:b1ce54272580 536 Notify(PSTR("\tgyroRoll: "), 0x80);
kotakku 0:b1ce54272580 537 Notify(gyroRoll, 0x80);
kotakku 0:b1ce54272580 538 Notify(PSTR("\tgyroPitch: "), 0x80);
kotakku 0:b1ce54272580 539 Notify(gyroPitch, 0x80);
kotakku 0:b1ce54272580 540 */
kotakku 0:b1ce54272580 541 /*
kotakku 0:b1ce54272580 542 Notify(PSTR("\twiimoteRoll: "), 0x80);
kotakku 0:b1ce54272580 543 Notify(wiimoteRoll, 0x80);
kotakku 0:b1ce54272580 544 Notify(PSTR("\twiimotePitch: "), 0x80);
kotakku 0:b1ce54272580 545 Notify(wiimotePitch, 0x80);
kotakku 0:b1ce54272580 546 */
kotakku 0:b1ce54272580 547 } else {
kotakku 0:b1ce54272580 548 if((int32_t)((uint32_t)micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
kotakku 0:b1ce54272580 549 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 550 Notify(PSTR("\r\nThe gyro values has been reset"), 0x80);
kotakku 0:b1ce54272580 551 #endif
kotakku 0:b1ce54272580 552 gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6));
kotakku 0:b1ce54272580 553 gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6));
kotakku 0:b1ce54272580 554 gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6));
kotakku 0:b1ce54272580 555
kotakku 0:b1ce54272580 556 rollGyroScale = 500; // You might need to adjust these
kotakku 0:b1ce54272580 557 pitchGyroScale = 400;
kotakku 0:b1ce54272580 558 yawGyroScale = 415;
kotakku 0:b1ce54272580 559
kotakku 0:b1ce54272580 560 gyroYaw = 0;
kotakku 0:b1ce54272580 561 gyroRoll = 0;
kotakku 0:b1ce54272580 562 gyroPitch = 0;
kotakku 0:b1ce54272580 563
kotakku 0:b1ce54272580 564 motionValuesReset = true;
kotakku 0:b1ce54272580 565 timer = (uint32_t)micros();
kotakku 0:b1ce54272580 566 }
kotakku 0:b1ce54272580 567 }
kotakku 0:b1ce54272580 568 } else {
kotakku 0:b1ce54272580 569 if(nunchuckConnected) {
kotakku 0:b1ce54272580 570 hatValues[HatX] = l2capinbuf[15];
kotakku 0:b1ce54272580 571 hatValues[HatY] = l2capinbuf[16];
kotakku 0:b1ce54272580 572 accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416;
kotakku 0:b1ce54272580 573 accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416;
kotakku 0:b1ce54272580 574 accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416;
kotakku 0:b1ce54272580 575 }
kotakku 0:b1ce54272580 576 //else if(classicControllerConnected) { }
kotakku 0:b1ce54272580 577 }
kotakku 0:b1ce54272580 578 if(l2capinbuf[19] & 0x01) {
kotakku 0:b1ce54272580 579 if(!extensionConnected) {
kotakku 0:b1ce54272580 580 extensionConnected = true;
kotakku 0:b1ce54272580 581 unknownExtensionConnected = true;
kotakku 0:b1ce54272580 582 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 583 Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80);
kotakku 0:b1ce54272580 584 #endif
kotakku 0:b1ce54272580 585 }
kotakku 0:b1ce54272580 586 } else {
kotakku 0:b1ce54272580 587 if(extensionConnected && !unknownExtensionConnected) {
kotakku 0:b1ce54272580 588 extensionConnected = false;
kotakku 0:b1ce54272580 589 unknownExtensionConnected = true;
kotakku 0:b1ce54272580 590 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 591 Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80);
kotakku 0:b1ce54272580 592 #endif
kotakku 0:b1ce54272580 593 nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent
kotakku 0:b1ce54272580 594 }
kotakku 0:b1ce54272580 595 }
kotakku 0:b1ce54272580 596
kotakku 0:b1ce54272580 597 } else if(nunchuckConnected) {
kotakku 0:b1ce54272580 598 hatValues[HatX] = l2capinbuf[15];
kotakku 0:b1ce54272580 599 hatValues[HatY] = l2capinbuf[16];
kotakku 0:b1ce54272580 600 accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416;
kotakku 0:b1ce54272580 601 accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416;
kotakku 0:b1ce54272580 602 accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416;
kotakku 0:b1ce54272580 603 } else if(wiiUProControllerConnected) {
kotakku 0:b1ce54272580 604 hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);
kotakku 0:b1ce54272580 605 hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);
kotakku 0:b1ce54272580 606 hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);
kotakku 0:b1ce54272580 607 hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8);
kotakku 0:b1ce54272580 608 }
kotakku 0:b1ce54272580 609 #endif
kotakku 0:b1ce54272580 610 break;
kotakku 0:b1ce54272580 611 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 612 default:
kotakku 0:b1ce54272580 613 Notify(PSTR("\r\nUnknown Report type: "), 0x80);
kotakku 0:b1ce54272580 614 D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
kotakku 0:b1ce54272580 615 break;
kotakku 0:b1ce54272580 616 #endif
kotakku 0:b1ce54272580 617 }
kotakku 0:b1ce54272580 618 }
kotakku 0:b1ce54272580 619 }
kotakku 0:b1ce54272580 620 L2CAP_task();
kotakku 0:b1ce54272580 621 }
kotakku 0:b1ce54272580 622 }
kotakku 0:b1ce54272580 623
kotakku 0:b1ce54272580 624 void WII::L2CAP_task() {
kotakku 0:b1ce54272580 625 switch(l2cap_state) {
kotakku 0:b1ce54272580 626 /* These states are used if the Wiimote is the host */
kotakku 0:b1ce54272580 627 case L2CAP_CONTROL_SUCCESS:
kotakku 0:b1ce54272580 628 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
kotakku 0:b1ce54272580 629 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 630 Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
kotakku 0:b1ce54272580 631 #endif
kotakku 0:b1ce54272580 632 l2cap_state = L2CAP_INTERRUPT_SETUP;
kotakku 0:b1ce54272580 633 }
kotakku 0:b1ce54272580 634 break;
kotakku 0:b1ce54272580 635
kotakku 0:b1ce54272580 636 case L2CAP_INTERRUPT_SETUP:
kotakku 0:b1ce54272580 637 if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
kotakku 0:b1ce54272580 638 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 639 Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 640 #endif
kotakku 0:b1ce54272580 641 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
kotakku 0:b1ce54272580 642 delay(1);
kotakku 0:b1ce54272580 643 pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
kotakku 0:b1ce54272580 644 identifier++;
kotakku 0:b1ce54272580 645 delay(1);
kotakku 0:b1ce54272580 646 pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
kotakku 0:b1ce54272580 647
kotakku 0:b1ce54272580 648 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
kotakku 0:b1ce54272580 649 }
kotakku 0:b1ce54272580 650 break;
kotakku 0:b1ce54272580 651
kotakku 0:b1ce54272580 652 /* These states are used if the Arduino is the host */
kotakku 0:b1ce54272580 653 case L2CAP_CONTROL_CONNECT_REQUEST:
kotakku 0:b1ce54272580 654 if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {
kotakku 0:b1ce54272580 655 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 656 Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
kotakku 0:b1ce54272580 657 #endif
kotakku 0:b1ce54272580 658 identifier++;
kotakku 0:b1ce54272580 659 pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
kotakku 0:b1ce54272580 660 l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
kotakku 0:b1ce54272580 661 }
kotakku 0:b1ce54272580 662 break;
kotakku 0:b1ce54272580 663
kotakku 0:b1ce54272580 664 case L2CAP_CONTROL_CONFIG_REQUEST:
kotakku 0:b1ce54272580 665 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
kotakku 0:b1ce54272580 666 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 667 Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
kotakku 0:b1ce54272580 668 #endif
kotakku 0:b1ce54272580 669 identifier++;
kotakku 0:b1ce54272580 670 pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM);
kotakku 0:b1ce54272580 671 l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
kotakku 0:b1ce54272580 672 }
kotakku 0:b1ce54272580 673 break;
kotakku 0:b1ce54272580 674
kotakku 0:b1ce54272580 675 case L2CAP_INTERRUPT_CONNECT_REQUEST:
kotakku 0:b1ce54272580 676 if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {
kotakku 0:b1ce54272580 677 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 678 Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
kotakku 0:b1ce54272580 679 #endif
kotakku 0:b1ce54272580 680 identifier++;
kotakku 0:b1ce54272580 681 pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
kotakku 0:b1ce54272580 682 l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
kotakku 0:b1ce54272580 683 }
kotakku 0:b1ce54272580 684 break;
kotakku 0:b1ce54272580 685
kotakku 0:b1ce54272580 686 case L2CAP_INTERRUPT_CONFIG_REQUEST:
kotakku 0:b1ce54272580 687 if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
kotakku 0:b1ce54272580 688 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 689 Notify(PSTR("\r\nHID Channels Established"), 0x80);
kotakku 0:b1ce54272580 690 #endif
kotakku 0:b1ce54272580 691 pBtd->connectToWii = false;
kotakku 0:b1ce54272580 692 pBtd->pairWithWii = false;
kotakku 0:b1ce54272580 693 stateCounter = 0;
kotakku 0:b1ce54272580 694 l2cap_state = WII_CHECK_MOTION_PLUS_STATE;
kotakku 0:b1ce54272580 695 }
kotakku 0:b1ce54272580 696 break;
kotakku 0:b1ce54272580 697
kotakku 0:b1ce54272580 698 /* The next states are in run() */
kotakku 0:b1ce54272580 699
kotakku 0:b1ce54272580 700 case L2CAP_INTERRUPT_DISCONNECT:
kotakku 0:b1ce54272580 701 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((int32_t)((uint32_t)millis() - timer) >= 0L)) {
kotakku 0:b1ce54272580 702 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 703 Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
kotakku 0:b1ce54272580 704 #endif
kotakku 0:b1ce54272580 705 identifier++;
kotakku 0:b1ce54272580 706 pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
kotakku 0:b1ce54272580 707 l2cap_state = L2CAP_CONTROL_DISCONNECT;
kotakku 0:b1ce54272580 708 }
kotakku 0:b1ce54272580 709 break;
kotakku 0:b1ce54272580 710
kotakku 0:b1ce54272580 711 case L2CAP_CONTROL_DISCONNECT:
kotakku 0:b1ce54272580 712 if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
kotakku 0:b1ce54272580 713 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 714 Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
kotakku 0:b1ce54272580 715 #endif
kotakku 0:b1ce54272580 716 pBtd->hci_disconnect(hci_handle);
kotakku 0:b1ce54272580 717 hci_handle = -1; // Reset handle
kotakku 0:b1ce54272580 718 l2cap_event_flag = 0; // Reset flags
kotakku 0:b1ce54272580 719 l2cap_state = L2CAP_WAIT;
kotakku 0:b1ce54272580 720 }
kotakku 0:b1ce54272580 721 break;
kotakku 0:b1ce54272580 722 }
kotakku 0:b1ce54272580 723 }
kotakku 0:b1ce54272580 724
kotakku 0:b1ce54272580 725 void WII::Run() {
kotakku 0:b1ce54272580 726 if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((int32_t)((uint32_t)millis() - timer) >= 0L))
kotakku 0:b1ce54272580 727 L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough
kotakku 0:b1ce54272580 728
kotakku 0:b1ce54272580 729 switch(l2cap_state) {
kotakku 0:b1ce54272580 730 case L2CAP_WAIT:
kotakku 0:b1ce54272580 731 if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) {
kotakku 0:b1ce54272580 732 pBtd->l2capConnectionClaimed = true;
kotakku 0:b1ce54272580 733 activeConnection = true;
kotakku 0:b1ce54272580 734 motionPlusInside = pBtd->motionPlusInside;
kotakku 0:b1ce54272580 735 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 736 Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
kotakku 0:b1ce54272580 737 #endif
kotakku 0:b1ce54272580 738 hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
kotakku 0:b1ce54272580 739 l2cap_event_flag = 0; // Reset flags
kotakku 0:b1ce54272580 740 identifier = 0;
kotakku 0:b1ce54272580 741 pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);
kotakku 0:b1ce54272580 742 l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
kotakku 0:b1ce54272580 743 } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
kotakku 0:b1ce54272580 744 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 745 Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
kotakku 0:b1ce54272580 746 #endif
kotakku 0:b1ce54272580 747 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
kotakku 0:b1ce54272580 748 delay(1);
kotakku 0:b1ce54272580 749 pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
kotakku 0:b1ce54272580 750 identifier++;
kotakku 0:b1ce54272580 751 delay(1);
kotakku 0:b1ce54272580 752 pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
kotakku 0:b1ce54272580 753 l2cap_state = L2CAP_CONTROL_SUCCESS;
kotakku 0:b1ce54272580 754 }
kotakku 0:b1ce54272580 755 break;
kotakku 0:b1ce54272580 756
kotakku 0:b1ce54272580 757 case WII_CHECK_MOTION_PLUS_STATE:
kotakku 0:b1ce54272580 758 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 759 if(stateCounter == 0) // Only print onnce
kotakku 0:b1ce54272580 760 Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80);
kotakku 0:b1ce54272580 761 #endif
kotakku 0:b1ce54272580 762 stateCounter++;
kotakku 0:b1ce54272580 763 if(stateCounter % 200 == 0)
kotakku 0:b1ce54272580 764 checkMotionPresent(); // Check if there is a motion plus connected
kotakku 0:b1ce54272580 765 if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) {
kotakku 0:b1ce54272580 766 stateCounter = 0;
kotakku 0:b1ce54272580 767 l2cap_state = WII_INIT_MOTION_PLUS_STATE;
kotakku 0:b1ce54272580 768 timer = (uint32_t)micros();
kotakku 0:b1ce54272580 769
kotakku 0:b1ce54272580 770 if(unknownExtensionConnected) {
kotakku 0:b1ce54272580 771 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 772 Notify(PSTR("\r\nA extension is also connected"), 0x80);
kotakku 0:b1ce54272580 773 #endif
kotakku 0:b1ce54272580 774 activateNunchuck = true; // For we will just set this to true as this the only extension supported so far
kotakku 0:b1ce54272580 775 }
kotakku 0:b1ce54272580 776
kotakku 0:b1ce54272580 777 } else if(stateCounter == 601) { // We will try three times to check for the motion plus
kotakku 0:b1ce54272580 778 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 779 Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80);
kotakku 0:b1ce54272580 780 #endif
kotakku 0:b1ce54272580 781 stateCounter = 0;
kotakku 0:b1ce54272580 782 l2cap_state = WII_CHECK_EXTENSION_STATE;
kotakku 0:b1ce54272580 783 }
kotakku 0:b1ce54272580 784 break;
kotakku 0:b1ce54272580 785
kotakku 0:b1ce54272580 786 case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port
kotakku 0:b1ce54272580 787 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 788 if(stateCounter == 0) // Only print onnce
kotakku 0:b1ce54272580 789 Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80);
kotakku 0:b1ce54272580 790 #endif
kotakku 0:b1ce54272580 791 stateCounter++; // We use this counter as there has to be a short delay between the commands
kotakku 0:b1ce54272580 792 if(stateCounter == 1)
kotakku 0:b1ce54272580 793 statusRequest(); // See if a new device has connected
kotakku 0:b1ce54272580 794 if(stateCounter == 100) {
kotakku 0:b1ce54272580 795 if(unknownExtensionConnected) // Check if there is a extension is connected to the port
kotakku 0:b1ce54272580 796 initExtension1();
kotakku 0:b1ce54272580 797 else
kotakku 0:b1ce54272580 798 stateCounter = 499;
kotakku 0:b1ce54272580 799 } else if(stateCounter == 200)
kotakku 0:b1ce54272580 800 initExtension2();
kotakku 0:b1ce54272580 801 else if(stateCounter == 300) {
kotakku 0:b1ce54272580 802 readExtensionType();
kotakku 0:b1ce54272580 803 unknownExtensionConnected = false;
kotakku 0:b1ce54272580 804 } else if(stateCounter == 400) {
kotakku 0:b1ce54272580 805 if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) {
kotakku 0:b1ce54272580 806 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 807 Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80);
kotakku 0:b1ce54272580 808 #endif
kotakku 0:b1ce54272580 809 readWiiBalanceBoardCalibration();
kotakku 0:b1ce54272580 810 } else
kotakku 0:b1ce54272580 811 stateCounter = 499;
kotakku 0:b1ce54272580 812 } else if(stateCounter == 500) {
kotakku 0:b1ce54272580 813 stateCounter = 0;
kotakku 0:b1ce54272580 814 l2cap_state = TURN_ON_LED;
kotakku 0:b1ce54272580 815 }
kotakku 0:b1ce54272580 816 break;
kotakku 0:b1ce54272580 817
kotakku 0:b1ce54272580 818 case WII_INIT_MOTION_PLUS_STATE:
kotakku 0:b1ce54272580 819 stateCounter++;
kotakku 0:b1ce54272580 820 if(stateCounter == 1)
kotakku 0:b1ce54272580 821 initMotionPlus();
kotakku 0:b1ce54272580 822 else if(stateCounter == 100)
kotakku 0:b1ce54272580 823 activateMotionPlus();
kotakku 0:b1ce54272580 824 else if(stateCounter == 200)
kotakku 0:b1ce54272580 825 readExtensionType(); // Check if it has been activated
kotakku 0:b1ce54272580 826 else if(stateCounter == 300) {
kotakku 0:b1ce54272580 827 stateCounter = 0;
kotakku 0:b1ce54272580 828 unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus
kotakku 0:b1ce54272580 829 l2cap_state = TURN_ON_LED;
kotakku 0:b1ce54272580 830 }
kotakku 0:b1ce54272580 831 break;
kotakku 0:b1ce54272580 832
kotakku 0:b1ce54272580 833 case TURN_ON_LED:
kotakku 0:b1ce54272580 834 if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED))
kotakku 0:b1ce54272580 835 nunchuckConnected = true;
kotakku 0:b1ce54272580 836 wiimoteConnected = true;
kotakku 0:b1ce54272580 837 onInit();
kotakku 0:b1ce54272580 838 l2cap_state = L2CAP_DONE;
kotakku 0:b1ce54272580 839 break;
kotakku 0:b1ce54272580 840
kotakku 0:b1ce54272580 841 case L2CAP_DONE:
kotakku 0:b1ce54272580 842 if(unknownExtensionConnected) {
kotakku 0:b1ce54272580 843 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 844 if(stateCounter == 0) // Only print once
kotakku 0:b1ce54272580 845 Notify(PSTR("\r\nChecking extension port"), 0x80);
kotakku 0:b1ce54272580 846 #endif
kotakku 0:b1ce54272580 847 stateCounter++; // We will use this counter as there has to be a short delay between the commands
kotakku 0:b1ce54272580 848 if(stateCounter == 50)
kotakku 0:b1ce54272580 849 statusRequest();
kotakku 0:b1ce54272580 850 else if(stateCounter == 100)
kotakku 0:b1ce54272580 851 initExtension1();
kotakku 0:b1ce54272580 852 else if(stateCounter == 150)
kotakku 0:b1ce54272580 853 if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected))
kotakku 0:b1ce54272580 854 initExtension2();
kotakku 0:b1ce54272580 855 else
kotakku 0:b1ce54272580 856 stateCounter = 299; // There is no extension connected
kotakku 0:b1ce54272580 857 else if(stateCounter == 200)
kotakku 0:b1ce54272580 858 readExtensionType();
kotakku 0:b1ce54272580 859 else if(stateCounter == 250) {
kotakku 0:b1ce54272580 860 if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) {
kotakku 0:b1ce54272580 861 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 862 Notify(PSTR("\r\nNunchuck was reconnected"), 0x80);
kotakku 0:b1ce54272580 863 #endif
kotakku 0:b1ce54272580 864 activateNunchuck = true;
kotakku 0:b1ce54272580 865 nunchuckConnected = true;
kotakku 0:b1ce54272580 866 }
kotakku 0:b1ce54272580 867 if(!motionPlusConnected)
kotakku 0:b1ce54272580 868 stateCounter = 449;
kotakku 0:b1ce54272580 869 } else if(stateCounter == 300) {
kotakku 0:b1ce54272580 870 if(motionPlusConnected) {
kotakku 0:b1ce54272580 871 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 872 Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80);
kotakku 0:b1ce54272580 873 #endif
kotakku 0:b1ce54272580 874 initMotionPlus();
kotakku 0:b1ce54272580 875 } else
kotakku 0:b1ce54272580 876 stateCounter = 449;
kotakku 0:b1ce54272580 877 } else if(stateCounter == 350)
kotakku 0:b1ce54272580 878 activateMotionPlus();
kotakku 0:b1ce54272580 879 else if(stateCounter == 400)
kotakku 0:b1ce54272580 880 readExtensionType(); // Check if it has been activated
kotakku 0:b1ce54272580 881 else if(stateCounter == 450) {
kotakku 0:b1ce54272580 882 onInit();
kotakku 0:b1ce54272580 883 stateCounter = 0;
kotakku 0:b1ce54272580 884 unknownExtensionConnected = false;
kotakku 0:b1ce54272580 885 }
kotakku 0:b1ce54272580 886 } else
kotakku 0:b1ce54272580 887 stateCounter = 0;
kotakku 0:b1ce54272580 888 break;
kotakku 0:b1ce54272580 889 }
kotakku 0:b1ce54272580 890 }
kotakku 0:b1ce54272580 891
kotakku 0:b1ce54272580 892 /************************************************************/
kotakku 0:b1ce54272580 893 /* HID Commands */
kotakku 0:b1ce54272580 894 /************************************************************/
kotakku 0:b1ce54272580 895
kotakku 0:b1ce54272580 896 void WII::HID_Command(uint8_t* data, uint8_t nbytes) {
kotakku 0:b1ce54272580 897 if(motionPlusInside)
kotakku 0:b1ce54272580 898 pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller
kotakku 0:b1ce54272580 899 else
kotakku 0:b1ce54272580 900 pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
kotakku 0:b1ce54272580 901 }
kotakku 0:b1ce54272580 902
kotakku 0:b1ce54272580 903 void WII::setAllOff() {
kotakku 0:b1ce54272580 904 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 905 HIDBuffer[2] = 0x00;
kotakku 0:b1ce54272580 906 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 907 }
kotakku 0:b1ce54272580 908
kotakku 0:b1ce54272580 909 void WII::setRumbleOff() {
kotakku 0:b1ce54272580 910 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 911 HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble
kotakku 0:b1ce54272580 912 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 913 }
kotakku 0:b1ce54272580 914
kotakku 0:b1ce54272580 915 void WII::setRumbleOn() {
kotakku 0:b1ce54272580 916 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 917 HIDBuffer[2] |= 0x01; // Bit 0 control the rumble
kotakku 0:b1ce54272580 918 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 919 }
kotakku 0:b1ce54272580 920
kotakku 0:b1ce54272580 921 void WII::setRumbleToggle() {
kotakku 0:b1ce54272580 922 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 923 HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble
kotakku 0:b1ce54272580 924 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 925 }
kotakku 0:b1ce54272580 926
kotakku 0:b1ce54272580 927 void WII::setLedRaw(uint8_t value) {
kotakku 0:b1ce54272580 928 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 929 HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit
kotakku 0:b1ce54272580 930 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 931 }
kotakku 0:b1ce54272580 932
kotakku 0:b1ce54272580 933 void WII::setLedOff(LEDEnum a) {
kotakku 0:b1ce54272580 934 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 935 HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a]));
kotakku 0:b1ce54272580 936 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 937 }
kotakku 0:b1ce54272580 938
kotakku 0:b1ce54272580 939 void WII::setLedOn(LEDEnum a) {
kotakku 0:b1ce54272580 940 if(a == OFF)
kotakku 0:b1ce54272580 941 setLedRaw(0);
kotakku 0:b1ce54272580 942 else {
kotakku 0:b1ce54272580 943 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 944 HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
kotakku 0:b1ce54272580 945 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 946 }
kotakku 0:b1ce54272580 947 }
kotakku 0:b1ce54272580 948
kotakku 0:b1ce54272580 949 void WII::setLedToggle(LEDEnum a) {
kotakku 0:b1ce54272580 950 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 951 HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
kotakku 0:b1ce54272580 952 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 953 }
kotakku 0:b1ce54272580 954
kotakku 0:b1ce54272580 955 void WII::setLedStatus() {
kotakku 0:b1ce54272580 956 HIDBuffer[1] = 0x11;
kotakku 0:b1ce54272580 957 HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
kotakku 0:b1ce54272580 958 if(wiimoteConnected)
kotakku 0:b1ce54272580 959 HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up
kotakku 0:b1ce54272580 960 if(motionPlusConnected)
kotakku 0:b1ce54272580 961 HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up
kotakku 0:b1ce54272580 962 if(nunchuckConnected)
kotakku 0:b1ce54272580 963 HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up
kotakku 0:b1ce54272580 964
kotakku 0:b1ce54272580 965 HID_Command(HIDBuffer, 3);
kotakku 0:b1ce54272580 966 }
kotakku 0:b1ce54272580 967
kotakku 0:b1ce54272580 968 uint8_t WII::getBatteryLevel() {
kotakku 0:b1ce54272580 969 checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function
kotakku 0:b1ce54272580 970 statusRequest(); // This will update the battery level
kotakku 0:b1ce54272580 971 return batteryLevel;
kotakku 0:b1ce54272580 972 };
kotakku 0:b1ce54272580 973
kotakku 0:b1ce54272580 974 void WII::setReportMode(bool continuous, uint8_t mode) {
kotakku 0:b1ce54272580 975 #ifdef EXTRADEBUG
kotakku 0:b1ce54272580 976 Notify(PSTR("\r\nReport mode was changed to: "), 0x80);
kotakku 0:b1ce54272580 977 D_PrintHex<uint8_t > (mode, 0x80);
kotakku 0:b1ce54272580 978 #endif
kotakku 0:b1ce54272580 979 uint8_t cmd_buf[4];
kotakku 0:b1ce54272580 980 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 981 cmd_buf[1] = 0x12;
kotakku 0:b1ce54272580 982 if(continuous)
kotakku 0:b1ce54272580 983 cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
kotakku 0:b1ce54272580 984 else
kotakku 0:b1ce54272580 985 cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
kotakku 0:b1ce54272580 986 cmd_buf[3] = mode;
kotakku 0:b1ce54272580 987 HID_Command(cmd_buf, 4);
kotakku 0:b1ce54272580 988 }
kotakku 0:b1ce54272580 989
kotakku 0:b1ce54272580 990 void WII::statusRequest() {
kotakku 0:b1ce54272580 991 uint8_t cmd_buf[3];
kotakku 0:b1ce54272580 992 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 993 cmd_buf[1] = 0x15;
kotakku 0:b1ce54272580 994 cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
kotakku 0:b1ce54272580 995 HID_Command(cmd_buf, 3);
kotakku 0:b1ce54272580 996 }
kotakku 0:b1ce54272580 997
kotakku 0:b1ce54272580 998 /************************************************************/
kotakku 0:b1ce54272580 999 /* Memmory Commands */
kotakku 0:b1ce54272580 1000 /************************************************************/
kotakku 0:b1ce54272580 1001
kotakku 0:b1ce54272580 1002 void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {
kotakku 0:b1ce54272580 1003 uint8_t cmd_buf[23];
kotakku 0:b1ce54272580 1004 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 1005 cmd_buf[1] = 0x16; // Write data
kotakku 0:b1ce54272580 1006 cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM
kotakku 0:b1ce54272580 1007 cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
kotakku 0:b1ce54272580 1008 cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
kotakku 0:b1ce54272580 1009 cmd_buf[5] = (uint8_t)(offset & 0xFF);
kotakku 0:b1ce54272580 1010 cmd_buf[6] = size;
kotakku 0:b1ce54272580 1011 uint8_t i = 0;
kotakku 0:b1ce54272580 1012 for(; i < size; i++)
kotakku 0:b1ce54272580 1013 cmd_buf[7 + i] = data[i];
kotakku 0:b1ce54272580 1014 for(; i < 16; i++) // Set the rest to zero
kotakku 0:b1ce54272580 1015 cmd_buf[7 + i] = 0x00;
kotakku 0:b1ce54272580 1016 HID_Command(cmd_buf, 23);
kotakku 0:b1ce54272580 1017 }
kotakku 0:b1ce54272580 1018
kotakku 0:b1ce54272580 1019 void WII::initExtension1() {
kotakku 0:b1ce54272580 1020 uint8_t buf[1];
kotakku 0:b1ce54272580 1021 buf[0] = 0x55;
kotakku 0:b1ce54272580 1022 writeData(0xA400F0, 1, buf);
kotakku 0:b1ce54272580 1023 }
kotakku 0:b1ce54272580 1024
kotakku 0:b1ce54272580 1025 void WII::initExtension2() {
kotakku 0:b1ce54272580 1026 uint8_t buf[1];
kotakku 0:b1ce54272580 1027 buf[0] = 0x00;
kotakku 0:b1ce54272580 1028 writeData(0xA400FB, 1, buf);
kotakku 0:b1ce54272580 1029 }
kotakku 0:b1ce54272580 1030
kotakku 0:b1ce54272580 1031 void WII::initMotionPlus() {
kotakku 0:b1ce54272580 1032 uint8_t buf[1];
kotakku 0:b1ce54272580 1033 buf[0] = 0x55;
kotakku 0:b1ce54272580 1034 writeData(0xA600F0, 1, buf);
kotakku 0:b1ce54272580 1035 }
kotakku 0:b1ce54272580 1036
kotakku 0:b1ce54272580 1037 void WII::activateMotionPlus() {
kotakku 0:b1ce54272580 1038 uint8_t buf[1];
kotakku 0:b1ce54272580 1039 if(pBtd->wiiUProController) {
kotakku 0:b1ce54272580 1040 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1041 Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80);
kotakku 0:b1ce54272580 1042 #endif
kotakku 0:b1ce54272580 1043 buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07
kotakku 0:b1ce54272580 1044 } else if(activateNunchuck) {
kotakku 0:b1ce54272580 1045 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1046 Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80);
kotakku 0:b1ce54272580 1047 #endif
kotakku 0:b1ce54272580 1048 buf[0] = 0x05; // Activate nunchuck pass-through mode
kotakku 0:b1ce54272580 1049 }//else if(classicControllerConnected && extensionConnected)
kotakku 0:b1ce54272580 1050 //buf[0] = 0x07;
kotakku 0:b1ce54272580 1051 else {
kotakku 0:b1ce54272580 1052 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1053 Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80);
kotakku 0:b1ce54272580 1054 #endif
kotakku 0:b1ce54272580 1055 buf[0] = 0x04; // Don't use any extension
kotakku 0:b1ce54272580 1056 }
kotakku 0:b1ce54272580 1057 writeData(0xA600FE, 1, buf);
kotakku 0:b1ce54272580 1058 }
kotakku 0:b1ce54272580 1059
kotakku 0:b1ce54272580 1060 void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) {
kotakku 0:b1ce54272580 1061 uint8_t cmd_buf[8];
kotakku 0:b1ce54272580 1062 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 1063 cmd_buf[1] = 0x17; // Read data
kotakku 0:b1ce54272580 1064 if(EEPROM)
kotakku 0:b1ce54272580 1065 cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM
kotakku 0:b1ce54272580 1066 else
kotakku 0:b1ce54272580 1067 cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory
kotakku 0:b1ce54272580 1068 cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
kotakku 0:b1ce54272580 1069 cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
kotakku 0:b1ce54272580 1070 cmd_buf[5] = (uint8_t)(offset & 0xFF);
kotakku 0:b1ce54272580 1071 cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8);
kotakku 0:b1ce54272580 1072 cmd_buf[7] = (uint8_t)(size & 0xFF);
kotakku 0:b1ce54272580 1073
kotakku 0:b1ce54272580 1074 HID_Command(cmd_buf, 8);
kotakku 0:b1ce54272580 1075 }
kotakku 0:b1ce54272580 1076
kotakku 0:b1ce54272580 1077 void WII::readExtensionType() {
kotakku 0:b1ce54272580 1078 readData(0xA400FA, 6, false);
kotakku 0:b1ce54272580 1079 }
kotakku 0:b1ce54272580 1080
kotakku 0:b1ce54272580 1081 void WII::readCalData() {
kotakku 0:b1ce54272580 1082 readData(0x0016, 8, true);
kotakku 0:b1ce54272580 1083 }
kotakku 0:b1ce54272580 1084
kotakku 0:b1ce54272580 1085 void WII::checkMotionPresent() {
kotakku 0:b1ce54272580 1086 readData(0xA600FA, 6, false);
kotakku 0:b1ce54272580 1087 }
kotakku 0:b1ce54272580 1088
kotakku 0:b1ce54272580 1089 void WII::readWiiBalanceBoardCalibration() {
kotakku 0:b1ce54272580 1090 readData(0xA40024, 24, false);
kotakku 0:b1ce54272580 1091 }
kotakku 0:b1ce54272580 1092
kotakku 0:b1ce54272580 1093 /************************************************************/
kotakku 0:b1ce54272580 1094 /* WII Commands */
kotakku 0:b1ce54272580 1095 /************************************************************/
kotakku 0:b1ce54272580 1096
kotakku 0:b1ce54272580 1097 bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed
kotakku 0:b1ce54272580 1098 if(wiiUProControllerConnected)
kotakku 0:b1ce54272580 1099 return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]));
kotakku 0:b1ce54272580 1100 else
kotakku 0:b1ce54272580 1101 return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b]));
kotakku 0:b1ce54272580 1102 }
kotakku 0:b1ce54272580 1103
kotakku 0:b1ce54272580 1104 bool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked
kotakku 0:b1ce54272580 1105 uint32_t button;
kotakku 0:b1ce54272580 1106 if(wiiUProControllerConnected)
kotakku 0:b1ce54272580 1107 button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]);
kotakku 0:b1ce54272580 1108 else
kotakku 0:b1ce54272580 1109 button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]);
kotakku 0:b1ce54272580 1110 bool click = (ButtonClickState & button);
kotakku 0:b1ce54272580 1111 ButtonClickState &= ~button; // clear "click" event
kotakku 0:b1ce54272580 1112 return click;
kotakku 0:b1ce54272580 1113 }
kotakku 0:b1ce54272580 1114
kotakku 0:b1ce54272580 1115 uint8_t WII::getAnalogHat(HatEnum a) {
kotakku 0:b1ce54272580 1116 if(!nunchuckConnected)
kotakku 0:b1ce54272580 1117 return 127; // Return center position
kotakku 0:b1ce54272580 1118 else {
kotakku 0:b1ce54272580 1119 uint8_t output = hatValues[(uint8_t)a];
kotakku 0:b1ce54272580 1120 if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position
kotakku 0:b1ce54272580 1121 return 127;
kotakku 0:b1ce54272580 1122 else
kotakku 0:b1ce54272580 1123 return output;
kotakku 0:b1ce54272580 1124 }
kotakku 0:b1ce54272580 1125 }
kotakku 0:b1ce54272580 1126
kotakku 0:b1ce54272580 1127 uint16_t WII::getAnalogHat(AnalogHatEnum a) {
kotakku 0:b1ce54272580 1128 if(!wiiUProControllerConnected)
kotakku 0:b1ce54272580 1129 return 2000;
kotakku 0:b1ce54272580 1130 else {
kotakku 0:b1ce54272580 1131 uint16_t output = hatValues[(uint8_t)a];
kotakku 0:b1ce54272580 1132 if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position
kotakku 0:b1ce54272580 1133 return 2000;
kotakku 0:b1ce54272580 1134 else
kotakku 0:b1ce54272580 1135 return output;
kotakku 0:b1ce54272580 1136 }
kotakku 0:b1ce54272580 1137 }
kotakku 0:b1ce54272580 1138
kotakku 0:b1ce54272580 1139 void WII::onInit() {
kotakku 0:b1ce54272580 1140 if(pFuncOnInit)
kotakku 0:b1ce54272580 1141 pFuncOnInit(); // Call the user function
kotakku 0:b1ce54272580 1142 else
kotakku 0:b1ce54272580 1143 setLedStatus();
kotakku 0:b1ce54272580 1144 }
kotakku 0:b1ce54272580 1145
kotakku 0:b1ce54272580 1146 /************************************************************/
kotakku 0:b1ce54272580 1147 /* Wii Balance Board Commands */
kotakku 0:b1ce54272580 1148 /************************************************************/
kotakku 0:b1ce54272580 1149
kotakku 0:b1ce54272580 1150 float WII::getWeight(BalanceBoardEnum pos) {
kotakku 0:b1ce54272580 1151 // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py
kotakku 0:b1ce54272580 1152 // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg
kotakku 0:b1ce54272580 1153 // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg
kotakku 0:b1ce54272580 1154 // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg
kotakku 0:b1ce54272580 1155 if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos])
kotakku 0:b1ce54272580 1156 return 0.0f; // Below 0 kg
kotakku 0:b1ce54272580 1157 else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg
kotakku 0:b1ce54272580 1158 return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]);
kotakku 0:b1ce54272580 1159 else // More than 17 kg
kotakku 0:b1ce54272580 1160 return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]);
kotakku 0:b1ce54272580 1161 };
kotakku 0:b1ce54272580 1162
kotakku 0:b1ce54272580 1163 float WII::getTotalWeight() {
kotakku 0:b1ce54272580 1164 return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft);
kotakku 0:b1ce54272580 1165 };
kotakku 0:b1ce54272580 1166
kotakku 0:b1ce54272580 1167 /************************************************************/
kotakku 0:b1ce54272580 1168 /* The following functions are for the IR camera */
kotakku 0:b1ce54272580 1169 /************************************************************/
kotakku 0:b1ce54272580 1170
kotakku 0:b1ce54272580 1171 #ifdef WIICAMERA
kotakku 0:b1ce54272580 1172
kotakku 0:b1ce54272580 1173 void WII::IRinitialize() { // Turns on and initialises the IR camera
kotakku 0:b1ce54272580 1174
kotakku 0:b1ce54272580 1175 enableIRCamera1();
kotakku 0:b1ce54272580 1176 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1177 Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80);
kotakku 0:b1ce54272580 1178 #endif
kotakku 0:b1ce54272580 1179 delay(80);
kotakku 0:b1ce54272580 1180
kotakku 0:b1ce54272580 1181 enableIRCamera2();
kotakku 0:b1ce54272580 1182 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1183 Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80);
kotakku 0:b1ce54272580 1184 #endif
kotakku 0:b1ce54272580 1185 delay(80);
kotakku 0:b1ce54272580 1186
kotakku 0:b1ce54272580 1187 write0x08Value();
kotakku 0:b1ce54272580 1188 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1189 Notify(PSTR("\r\nWrote hex number 0x08"), 0x80);
kotakku 0:b1ce54272580 1190 #endif
kotakku 0:b1ce54272580 1191 delay(80);
kotakku 0:b1ce54272580 1192
kotakku 0:b1ce54272580 1193 writeSensitivityBlock1();
kotakku 0:b1ce54272580 1194 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1195 Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80);
kotakku 0:b1ce54272580 1196 #endif
kotakku 0:b1ce54272580 1197 delay(80);
kotakku 0:b1ce54272580 1198
kotakku 0:b1ce54272580 1199 writeSensitivityBlock2();
kotakku 0:b1ce54272580 1200 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1201 Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80);
kotakku 0:b1ce54272580 1202 #endif
kotakku 0:b1ce54272580 1203 delay(80);
kotakku 0:b1ce54272580 1204
kotakku 0:b1ce54272580 1205 uint8_t mode_num = 0x03;
kotakku 0:b1ce54272580 1206 setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05
kotakku 0:b1ce54272580 1207 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1208 Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80);
kotakku 0:b1ce54272580 1209 D_PrintHex<uint8_t > (mode_num, 0x80);
kotakku 0:b1ce54272580 1210 #endif
kotakku 0:b1ce54272580 1211 delay(80);
kotakku 0:b1ce54272580 1212
kotakku 0:b1ce54272580 1213 write0x08Value();
kotakku 0:b1ce54272580 1214 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1215 Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80);
kotakku 0:b1ce54272580 1216 #endif
kotakku 0:b1ce54272580 1217 delay(80);
kotakku 0:b1ce54272580 1218
kotakku 0:b1ce54272580 1219 setReportMode(false, 0x33);
kotakku 0:b1ce54272580 1220 //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet
kotakku 0:b1ce54272580 1221 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1222 Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80);
kotakku 0:b1ce54272580 1223 #endif
kotakku 0:b1ce54272580 1224 delay(80);
kotakku 0:b1ce54272580 1225
kotakku 0:b1ce54272580 1226 statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked
kotakku 0:b1ce54272580 1227 #ifdef DEBUG_USB_HOST
kotakku 0:b1ce54272580 1228 Notify(PSTR("\r\nIR Initialized"), 0x80);
kotakku 0:b1ce54272580 1229 #endif
kotakku 0:b1ce54272580 1230 }
kotakku 0:b1ce54272580 1231
kotakku 0:b1ce54272580 1232 void WII::enableIRCamera1() {
kotakku 0:b1ce54272580 1233 uint8_t cmd_buf[3];
kotakku 0:b1ce54272580 1234 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 1235 cmd_buf[1] = 0x13; // Output report 13
kotakku 0:b1ce54272580 1236 cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
kotakku 0:b1ce54272580 1237 HID_Command(cmd_buf, 3);
kotakku 0:b1ce54272580 1238 }
kotakku 0:b1ce54272580 1239
kotakku 0:b1ce54272580 1240 void WII::enableIRCamera2() {
kotakku 0:b1ce54272580 1241 uint8_t cmd_buf[3];
kotakku 0:b1ce54272580 1242 cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
kotakku 0:b1ce54272580 1243 cmd_buf[1] = 0x1A; // Output report 1A
kotakku 0:b1ce54272580 1244 cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
kotakku 0:b1ce54272580 1245 HID_Command(cmd_buf, 3);
kotakku 0:b1ce54272580 1246 }
kotakku 0:b1ce54272580 1247
kotakku 0:b1ce54272580 1248 void WII::writeSensitivityBlock1() {
kotakku 0:b1ce54272580 1249 uint8_t buf[9];
kotakku 0:b1ce54272580 1250 buf[0] = 0x00;
kotakku 0:b1ce54272580 1251 buf[1] = 0x00;
kotakku 0:b1ce54272580 1252 buf[2] = 0x00;
kotakku 0:b1ce54272580 1253 buf[3] = 0x00;
kotakku 0:b1ce54272580 1254 buf[4] = 0x00;
kotakku 0:b1ce54272580 1255 buf[5] = 0x00;
kotakku 0:b1ce54272580 1256 buf[6] = 0x90;
kotakku 0:b1ce54272580 1257 buf[7] = 0x00;
kotakku 0:b1ce54272580 1258 buf[8] = 0x41;
kotakku 0:b1ce54272580 1259
kotakku 0:b1ce54272580 1260 writeData(0xB00000, 9, buf);
kotakku 0:b1ce54272580 1261 }
kotakku 0:b1ce54272580 1262
kotakku 0:b1ce54272580 1263 void WII::writeSensitivityBlock2() {
kotakku 0:b1ce54272580 1264 uint8_t buf[2];
kotakku 0:b1ce54272580 1265 buf[0] = 0x40;
kotakku 0:b1ce54272580 1266 buf[1] = 0x00;
kotakku 0:b1ce54272580 1267
kotakku 0:b1ce54272580 1268 writeData(0xB0001A, 2, buf);
kotakku 0:b1ce54272580 1269 }
kotakku 0:b1ce54272580 1270
kotakku 0:b1ce54272580 1271 void WII::write0x08Value() {
kotakku 0:b1ce54272580 1272 uint8_t cmd = 0x08;
kotakku 0:b1ce54272580 1273 writeData(0xb00030, 1, &cmd);
kotakku 0:b1ce54272580 1274 }
kotakku 0:b1ce54272580 1275
kotakku 0:b1ce54272580 1276 void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode
kotakku 0:b1ce54272580 1277 writeData(0xb00033, 1, &mode_number);
kotakku 0:b1ce54272580 1278 }
kotakku 0:b1ce54272580 1279 #endif
kotakku 0:b1ce54272580 1280