├── GamecubeBT └── GamecubeBT.ino ├── LICENSE ├── README.md ├── gcbt_box.jpg ├── gcbt_breadboard.jpg ├── gcbt_controllerplug.jpg ├── gcbt_final.jpg ├── gcbt_final2.jpg ├── gcbt_layout.jpg ├── gcbt_usbhost.jpg └── stl ├── README.md ├── box_left.stl └── box_right.stl /GamecubeBT/GamecubeBT.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Gamecube Controller using PS3 Controller. 3 | https://github.com/sirjeannot/GamecubeBT/ 4 | 5 | Based on Nicohood Nintendo library 6 | https://github.com/NicoHood/Nintendo 7 | Based on USBHOST library 8 | https://github.com/felis/USB_Host_Shield_2.0 9 | Interrupt howto 10 | https://www.instructables.com/Arduino-Timer-Interrupts/ 11 | */ 12 | 13 | //timer for gamecube interrupt 14 | #define TIMER1_MAX 70 15 | //scale for analog axis 16 | #define SCALE 0.785 17 | 18 | //Nintendo gamecube bus 19 | #include "Nintendo.h" 20 | //PS3 controller bt 21 | #include 22 | #include 23 | #include 24 | 25 | //Define a Gamecube Controller and a Console 26 | CGamecubeConsole GamecubeConsole1(8); 27 | CGamecubeController GamecubeController1(7); 28 | Gamecube_Data_t d = defaultGamecubeData; 29 | 30 | USB Usb; 31 | USBHub Hub1(&Usb); // Some dongles have a hub inside 32 | BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so 33 | PS3BT PS3(&Btd); // This will just create the instance 34 | //PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x54, 0x00, 0x72); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch 35 | //#define pinLed LED_BUILTIN 36 | 37 | //reset function for failed usb host init 38 | void(* resetFunc) (void) = 0; 39 | 40 | ISR(TIMER1_COMPA_vect) { 41 | GamecubeConsole1.write(d); 42 | } 43 | 44 | void setup() 45 | { 46 | //pinMode(pinLed, OUTPUT); 47 | GamecubeController1.read(); 48 | //Serial.begin(250000); 49 | 50 | while (Usb.Init() == -1) { 51 | Serial.print(F("\r\nOSC did not start")); 52 | delay(500); 53 | resetFunc(); 54 | } 55 | Serial.println(F("\r\nPS3 Bluetooth Library Started")); 56 | 57 | cli(); 58 | //set timer1 interrupt at 1Hz 59 | TCCR1A = 0;// set entire TCCR1A register to 0 60 | TCCR1B = 0;// same for TCCR1B 61 | TCNT1 = 0;//initialize counter value to 0 62 | // set compare match register for 1hz increments 63 | OCR1A = TIMER1_MAX;// = (70*10^6) / (1*1024) - 1 (must be <65536) 64 | // turn on CTC mode 65 | TCCR1B |= (1 << WGM12); 66 | // Set CS10 and CS12 bits for 1024 prescaler 67 | TCCR1B |= (1 << CS12) | (1 << CS10); 68 | // enable timer compare interrupt 69 | TIMSK1 |= (1 << OCIE1A); 70 | sei();//allow interrupts 71 | } 72 | 73 | void loop() 74 | { 75 | Usb.Task(); 76 | if (PS3.PS3Connected || PS3.PS3NavigationConnected) { 77 | //out of deadzone 78 | if (PS3.getAnalogHat(LeftHatX) > 147 || PS3.getAnalogHat(LeftHatX) < 107 || PS3.getAnalogHat(LeftHatY) > 147 || PS3.getAnalogHat(LeftHatY) < 107 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { 79 | d.report.xAxis = PS3.getAnalogHat(LeftHatX) * SCALE + 28; 80 | d.report.yAxis = (255 - PS3.getAnalogHat(LeftHatY) * SCALE) - 27; //yaxis values are inverted 81 | d.report.cxAxis = PS3.getAnalogHat(RightHatX) * SCALE + 28; 82 | d.report.cyAxis = (255 - PS3.getAnalogHat(RightHatY) * SCALE) - 27 ; //yaxis values are inverted 83 | } 84 | //in deadzone 85 | else { 86 | d.report.xAxis = 128; 87 | d.report.yAxis = 128; 88 | d.report.cxAxis = 128; 89 | d.report.cyAxis = 128; 90 | } 91 | d.report.left = PS3.getAnalogButton(L2); 92 | d.report.left > 200 ? d.report.l = 1 : d.report.l = 0 ; 93 | d.report.right = PS3.getAnalogButton(R2); 94 | d.report.right > 200 ? d.report.r = 1 : d.report.r = 0 ; 95 | d.report.x = PS3.getButtonPress(CIRCLE); 96 | d.report.y = PS3.getButtonPress(TRIANGLE); 97 | d.report.a = PS3.getButtonPress(CROSS); 98 | d.report.b = PS3.getButtonPress(SQUARE); 99 | d.report.dup = PS3.getButtonPress(UP); 100 | d.report.dright = PS3.getButtonPress(RIGHT); 101 | d.report.ddown = PS3.getButtonPress(DOWN); 102 | d.report.dleft = PS3.getButtonPress(LEFT); 103 | d.report.z = PS3.getButtonPress(R1); 104 | d.report.start = PS3.getButtonPress(START); 105 | if (PS3.getButtonClick(PS)) 106 | PS3.disconnect(); 107 | } 108 | //GamecubeConsole1.write(d); //disabled, run by timer1 109 | } 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Jeannot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GamecubeBT 2 | 3 | An arduino based bridge to connect a bluetooth PS3 controller to the Gamecube. 4 | Homemade Wavebirds, because the TV is too far from the couch. 5 | 6 | ![done](https://github.com/sirjeannot/GamecubeBT/blob/main/gcbt_final2.jpg?raw=true) 7 | 8 | This is nothing new, this is using two existing libraries : Nicohoods Nintendo to handle controller data sent to the GameCube, and PS3BT to use a PS3 controller. 9 | 10 | ### Current status / Not Working / ToDo 11 | * **working!** 12 | * **stick sensitivity ok!** 13 | * adapt the code for PS4 controller : this is only about using PS4BT functions rather than PS3BT. 14 | * support Powera Gamecube Switch controller 15 | 16 | ### Limitations 17 | * no rumble support 18 | * inputs can be missed in case of mashing of buttons 19 | 20 | ### Bill of material 21 | For this project I used components I had gathering dust : Arduino Nano, BT dongle TBW-107UB. 22 | * 16MHz Arduino (Nintendo library limitation) : 5E 23 | * USB Host Shield : 5E 24 | * USB Bluetooth2.1+EDR dongle or better : 8E (works fine with cheap bluetooth 4.0 dongle) 25 | * 3.3V / 5V level logic level converter : 3E 26 | * Gamecube cable extention : 5E 27 | Prices are rounded up, should be less than 26E. 28 | 29 | ### USB HOST hardware 30 | The cheap knockoff I ordered isn't well documented. I strongly recommend you do a continuity check to find out which pins connect to the MAX3421E : VCC (5V), VL (3.3V), INT, RST, SS, MISO, MOSI, SCLK, GND. The link to the datasheet is in the documentation section. 31 | 32 | Mine looks like this, yours may be different. 33 | This board directly connects VCC to VL. Once trace shall be cut or there will be power supply issues. 34 | 35 | ![usb host pinst](https://github.com/sirjeannot/GamecubeBT/blob/main/gcbt_usbhost.jpg?raw=true) 36 | 37 | ### Wiring 38 | First check which cable matches the following pins on the controller cable (male end). 39 | 40 | ![gamecube plug pins](https://github.com/sirjeannot/GamecubeBT/blob/main/gcbt_controllerplug.jpg?raw=true) (image borrowed from https://hackaday.io/project/162348) 41 | 42 | Wiring of the SS pin of the USB Host may be different depending on the Arduino board used. It is either D10 or D3. 43 | 44 | | Arduino | USB Host | Gamecube | 45 | | --- | --- | --- | 46 | | GND | GND | GND (both) | 47 | | | 3.3V | 3.3V | 48 | | 5V | Vcc | 5V | 49 | | D3 | INT | | 50 | | D8 | | DATA* | 51 | | D10 | SS | | 52 | | D11 | MOSI | | 53 | | D12 | MISO | | 54 | | D13 | SCLK | | 55 | | RST | RST | | 56 | 57 | Data logic on the Gamecube is 3.3V, D8 pin shall be routed through a logic level 5V to 3.3V. 58 | | Logic Level | Arduino | Gamecube | 59 | | --- | --- | --- | 60 | | GND | GND | GND | 61 | | LV | | 3.3V | 62 | | HV | | 5V | 63 | | HV1 | D8 | | 64 | | LV1 | | DATA | 65 | 66 | ### Controller layout 67 | This is the default layout I chose. Feel free to change it : the switch position of the left stick and d-pad is sometimes not the best choice. 68 | 69 | ![layout](https://github.com/sirjeannot/GamecubeBT/blob/main/gcbt_layout.jpg?raw=true) 70 | 71 | ### Enclosure 72 | 73 | The enclosure comes in two parts, located in the stl subfolder. 74 | They should be printed with layers = 0.2mm. Place the outside face on the bed to print without support. 75 | To close the box, use 4xm3 screws, 2.2cm length. 76 | ![model](https://github.com/sirjeannot/GamecubeBT/blob/main/gcbt_box.jpg?raw=true) 77 | 78 | ### Demo 79 | [![youtube video](https://img.youtube.com/vi/wYV4qaWRAow/0.jpg)](https://youtu.be/wYV4qaWRAow) 80 | 81 | ### Documentation / References 82 | * Nico Nintendo Library : https://github.com/NicoHood/Nintendo 83 | * USB HOST v2.0 : https://github.com/felis/USB_Host_Shield_2.0 84 | * MAX3421E : https://datasheets.maximintegrated.com/en/ds/MAX3421E.pdf 85 | * DIY Wireless Gamecube Controller : https://hackaday.io/project/162348 86 | 87 | ### Q&A 88 | * Why let the usb dongle stick out? --> This is part of the pairing process : the controller will need to be connected to the usb plug to get the MAC address of the BT dongle for the PS3 controller. 89 | * Why not use an ESP32 which has integrated bluetooth? --> 1. I didn't have any spare esp32 when I did that project. 2. The Nintendo library from Nicohood has time sensitive routines coded in AVR assembly for 16MHz clocks. I didn't want to review timings as it was supposed to be a simple straightforward project to reuse old arduinos. 90 | * It already exists, BlueRetro does it better! --> Yes it does, it supports more consoles, more controllers and more ports. My intent was to use simple and 'in my inventory' items. Also BlueRetro does it the right way by allocating one core for Bluetooth and one core for Wire. This project does both on a single core with a 10x lower clockspeed (but only one controller, can't do everything!). That may be a lead to support the Powera Gamecube Switch controller which was the initial goal of the project. 91 | 92 | ### Coverage 93 | * Hackaday : https://hackaday.com/2021/03/29/bluetooth-ps3-controllers-modernize-the-nintendo-gamecube/ 94 | -------------------------------------------------------------------------------- /gcbt_box.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_box.jpg -------------------------------------------------------------------------------- /gcbt_breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_breadboard.jpg -------------------------------------------------------------------------------- /gcbt_controllerplug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_controllerplug.jpg -------------------------------------------------------------------------------- /gcbt_final.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_final.jpg -------------------------------------------------------------------------------- /gcbt_final2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_final2.jpg -------------------------------------------------------------------------------- /gcbt_layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_layout.jpg -------------------------------------------------------------------------------- /gcbt_usbhost.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/gcbt_usbhost.jpg -------------------------------------------------------------------------------- /stl/README.md: -------------------------------------------------------------------------------- 1 | STL files 2 | -------------------------------------------------------------------------------- /stl/box_left.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/stl/box_left.stl -------------------------------------------------------------------------------- /stl/box_right.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sirjeannot/GamecubeBT/491717148ba9f2440edd9a19e742e596ada3c973/stl/box_right.stl --------------------------------------------------------------------------------