Skip to content

Commit 798d702

Browse files
committed
Added Sidewinder Gamepad addon
1 parent dc9e9a4 commit 798d702

File tree

9 files changed

+191
-0
lines changed

9 files changed

+191
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ src/addons/playernum.cpp
121121
src/addons/playerleds.cpp
122122
src/addons/ps4mode.cpp
123123
src/addons/reverse.cpp
124+
src/addons/sidewindergp.cpp
124125
src/addons/turbo.cpp
125126
src/addons/slider_socd.cpp
126127
src/addons/wiiext.cpp
15.8 KB
Loading

docs/web-configurator.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,37 @@ Classic Controller support includes Classic, Classic Pro, and NES/SNES Mini Cont
287287

288288
Original Classic Controller L & R triggers are analog sensitive, where Pro triggers are not.
289289

290+
### Sidewinder Gamepad
291+
292+
![GP2040 Configurator - Sidewinder Gamepad](assets/images/gpc-add-ons-sidewindergp.png)
293+
294+
Designed to be mapped on DA-15 gameport of the Sidewinder Gamepad.
295+
296+
Connections:
297+
298+
- DA-15 pins 1, 8, 9, 15 to +5V
299+
- DA-15 pins 4, 5, 12 to GND
300+
- DA-15 pin 2 to Clock pin
301+
- DA-15 pin 3 to Trigger pin
302+
- DA-15 pin 7 to Data pin
303+
304+
Mapping is a follows:
305+
306+
| Sidewinder GP | GP2040-CE |
307+
|---------------|-----------|
308+
| D-Pad | Analog |
309+
| A | B1 |
310+
| B | B2 |
311+
| C | L3 |
312+
| X | B3 |
313+
| Y | B4 |
314+
| Z | R3 |
315+
| LT | L1 |
316+
| RT | R1 |
317+
| Start | S2 |
318+
| M | S1 |
319+
320+
290321
## Data Backup and Restoration
291322

292323
![GP2040-CE Configurator - Add-Ons Backup and Restore](assets/images/gpc-backup-and-restore.png)

headers/addons/sidewindergp.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef _SidewinderGP_H
2+
#define _SidewinderGP_H
3+
4+
#include "gpaddon.h"
5+
6+
#include "GamepadEnums.h"
7+
8+
#include "BoardConfig.h"
9+
10+
#ifndef SIDEWINDERGP_INPUT_ENABLED
11+
#define SIDEWINDERGP_INPUT_ENABLED 0
12+
#endif
13+
14+
#ifndef SIDEWINDERGP_PIN_TRIGGER
15+
#define SIDEWINDERGP_PIN_TRIGGER -1
16+
#endif
17+
18+
#ifndef SIDEWINDERGP_PIN_CLOCK
19+
#define SIDEWINDERGP_PIN_CLOCK -1
20+
#endif
21+
22+
#ifndef SIDEWINDERGP_PIN_DATA
23+
#define SIDEWINDERGP_PIN_DATA -1
24+
#endif
25+
26+
27+
// SidewinderGP Module Name
28+
#define SideWinderGPName "Sidewinder Gamepad"
29+
30+
class SidewinderGPInput : public GPAddon {
31+
public:
32+
virtual bool available();
33+
virtual void setup(); // Setup
34+
virtual void process(); // Process
35+
virtual void preprocess() {}
36+
virtual std::string name() { return SideWinderGPName; }
37+
private:
38+
uint8_t sidewinderGPPinTrigger;
39+
uint8_t sidewinderGPPinClock;
40+
uint8_t sidewinderGPPinData;
41+
};
42+
43+
#endif // _SidewinderGP_H_

headers/storagemanager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ struct AddonOptions {
144144
uint8_t wiiExtensionSCLPin;
145145
int wiiExtensionBlock;
146146
uint32_t wiiExtensionSpeed;
147+
uint8_t sidewinderGPPinTrigger;
148+
uint8_t sidewinderGPPinClock;
149+
uint8_t sidewinderGPPinData;
147150
uint8_t AnalogInputEnabled;
148151
uint8_t BoardLedAddonEnabled;
149152
uint8_t BootselButtonAddonEnabled;
@@ -161,6 +164,7 @@ struct AddonOptions {
161164
uint8_t TurboInputEnabled;
162165
uint8_t SliderSOCDInputEnabled;
163166
uint8_t WiiExtensionAddonEnabled;
167+
uint8_t SidewinderGPEnabled;
164168
uint32_t checksum;
165169
};
166170

src/addons/sidewindergp.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include "addons/sidewindergp.h"
2+
#include "storagemanager.h"
3+
4+
5+
uint32_t SidewinderGPInputMapping[14] = {
6+
GAMEPAD_MASK_DU,
7+
GAMEPAD_MASK_DD,
8+
GAMEPAD_MASK_DR,
9+
GAMEPAD_MASK_DL,
10+
GAMEPAD_MASK_B1,
11+
GAMEPAD_MASK_B2,
12+
GAMEPAD_MASK_L3,
13+
GAMEPAD_MASK_B3,
14+
GAMEPAD_MASK_B4,
15+
GAMEPAD_MASK_R3,
16+
GAMEPAD_MASK_L1,
17+
GAMEPAD_MASK_R1,
18+
GAMEPAD_MASK_S2,
19+
GAMEPAD_MASK_S1
20+
};
21+
22+
bool SidewinderGPInput::available() {
23+
const AddonOptions& options = Storage::getInstance().getAddonOptions();
24+
sidewinderGPPinTrigger = Storage::getInstance().getAddonOptions().sidewinderGPPinTrigger;
25+
sidewinderGPPinClock = Storage::getInstance().getAddonOptions().sidewinderGPPinClock;
26+
sidewinderGPPinData = Storage::getInstance().getAddonOptions().sidewinderGPPinData;
27+
return options.SidewinderGPEnabled;
28+
}
29+
30+
void SidewinderGPInput::setup() {
31+
gpio_init(sidewinderGPPinTrigger);
32+
gpio_set_dir(sidewinderGPPinTrigger, GPIO_OUT);
33+
gpio_put(sidewinderGPPinTrigger, 1);
34+
35+
gpio_init(sidewinderGPPinClock);
36+
gpio_set_dir(sidewinderGPPinClock, GPIO_IN);
37+
gpio_pull_up(sidewinderGPPinClock);
38+
39+
gpio_init(sidewinderGPPinData);
40+
gpio_set_dir(sidewinderGPPinData, GPIO_IN);
41+
gpio_pull_up(sidewinderGPPinData);
42+
}
43+
44+
void SidewinderGPInput::process()
45+
{
46+
Gamepad * gamepad = Storage::getInstance().GetGamepad();
47+
48+
gpio_put(sidewinderGPPinTrigger, 0);
49+
sleep_us(225);
50+
gpio_put(sidewinderGPPinTrigger, 1);
51+
52+
bool btns[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
53+
bool checksum = 0;
54+
bool ok = 0;
55+
56+
for (int i=0; i < 15; i++) {
57+
// Wait for clock falling edge
58+
uint16_t timeout = 10000;
59+
while (timeout-- && !gpio_get(sidewinderGPPinClock)) {}
60+
while (timeout-- && gpio_get(sidewinderGPPinClock)) {}
61+
if (!timeout)
62+
break;
63+
if (i < 14) {
64+
btns[i] = !gpio_get(sidewinderGPPinData);
65+
checksum ^= btns[i];
66+
} else {
67+
ok = (checksum == gpio_get(sidewinderGPPinData));
68+
}
69+
}
70+
if (!ok)
71+
return;
72+
73+
gamepad->state.lx = 0x8000;
74+
gamepad->state.ly = 0x8000;
75+
for (int i=0; i < 14; i++) {
76+
if (!btns[i])
77+
continue;
78+
uint32_t btnMap = SidewinderGPInputMapping[i];
79+
if (btnMap > (GAMEPAD_MASK_A2)) {
80+
switch (btnMap) {
81+
case (GAMEPAD_MASK_DU):
82+
gamepad->state.ly = 0x0;
83+
break;
84+
case (GAMEPAD_MASK_DD):
85+
gamepad->state.ly = 0xffff;
86+
break;
87+
case (GAMEPAD_MASK_DL):
88+
gamepad->state.lx = 0x0;
89+
break;
90+
case (GAMEPAD_MASK_DR):
91+
gamepad->state.lx = 0xffff;
92+
break;
93+
}
94+
}
95+
else gamepad->state.buttons |= btnMap;
96+
}
97+
}

src/configs/webconfig.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,9 @@ std::string setAddonOptions()
826826
docToPin(addonOptions.wiiExtensionSDAPin, doc, "wiiExtensionSDAPin");
827827
docToPin(addonOptions.wiiExtensionSCLPin, doc, "wiiExtensionSCLPin");
828828
docToValue(addonOptions.wiiExtensionBlock, doc, "wiiExtensionBlock");
829+
docToPin(addonOptions.sidewinderGPPinTrigger, doc, "sidewinderGPPinTrigger");
830+
docToPin(addonOptions.sidewinderGPPinClock, doc, "sidewinderGPPinClock");
831+
docToPin(addonOptions.sidewinderGPPinData, doc, "sidewinderGPPinData");
829832
docToValue(addonOptions.wiiExtensionSpeed, doc, "wiiExtensionSpeed");
830833
docToValue(addonOptions.AnalogInputEnabled, doc, "AnalogInputEnabled");
831834
docToValue(addonOptions.BoardLedAddonEnabled, doc, "BoardLedAddonEnabled");
@@ -841,6 +844,7 @@ std::string setAddonOptions()
841844
docToValue(addonOptions.ReverseInputEnabled, doc, "ReverseInputEnabled");
842845
docToValue(addonOptions.TurboInputEnabled, doc, "TurboInputEnabled");
843846
docToValue(addonOptions.WiiExtensionAddonEnabled, doc, "WiiExtensionAddonEnabled");
847+
docToValue(addonOptions.SidewinderGPEnabled, doc, "SidewinderGPEnabled");
844848

845849
Storage::getInstance().setAddonOptions(addonOptions);
846850

@@ -1002,6 +1006,9 @@ std::string getAddonOptions()
10021006
writeDoc(doc, "wiiExtensionSCLPin", addonOptions.wiiExtensionSCLPin == 0xFF ? -1 : addonOptions.wiiExtensionSCLPin);
10031007
writeDoc(doc, "wiiExtensionBlock", addonOptions.wiiExtensionBlock);
10041008
writeDoc(doc, "wiiExtensionSpeed", addonOptions.wiiExtensionSpeed);
1009+
writeDoc(doc, "sidewinderGPPinTrigger", addonOptions.sidewinderGPPinTrigger == 0xFF ? -1 : addonOptions.sidewinderGPPinTrigger);
1010+
writeDoc(doc, "sidewinderGPPinClock", addonOptions.sidewinderGPPinClock == 0xFF ? -1 : addonOptions.sidewinderGPPinClock);
1011+
writeDoc(doc, "sidewinderGPPinData", addonOptions.sidewinderGPPinData == 0xFF ? -1 : addonOptions.sidewinderGPPinData);
10051012
writeDoc(doc, "AnalogInputEnabled", addonOptions.AnalogInputEnabled);
10061013
writeDoc(doc, "BoardLedAddonEnabled", addonOptions.BoardLedAddonEnabled);
10071014
writeDoc(doc, "BuzzerSpeakerAddonEnabled", addonOptions.BuzzerSpeakerAddonEnabled);
@@ -1016,6 +1023,7 @@ std::string getAddonOptions()
10161023
writeDoc(doc, "ReverseInputEnabled", addonOptions.ReverseInputEnabled);
10171024
writeDoc(doc, "TurboInputEnabled", addonOptions.TurboInputEnabled);
10181025
writeDoc(doc, "WiiExtensionAddonEnabled", addonOptions.WiiExtensionAddonEnabled);
1026+
writeDoc(doc, "SidewinderGPEnabled", addonOptions.SidewinderGPEnabled);
10191027

10201028
return serialize_json(doc);
10211029
}

src/gp2040.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "addons/turbo.h"
1919
#include "addons/slider_socd.h"
2020
#include "addons/wiiext.h"
21+
#include "addons/sidewindergp.h"
2122

2223
// Pico includes
2324
#include "pico/bootrom.h"
@@ -108,6 +109,7 @@ void GP2040::setup() {
108109
addons.LoadAddon(new WiiExtensionInput(), CORE0_INPUT);
109110
addons.LoadAddon(new PlayerNumAddon(), CORE0_USBREPORT);
110111
addons.LoadAddon(new SliderSOCDInput(), CORE0_INPUT);
112+
addons.LoadAddon(new SidewinderGPInput(), CORE0_INPUT);
111113
}
112114

113115
void GP2040::run() {

src/storagemanager.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "addons/pleds.h"
3030
#include "addons/reverse.h"
3131
#include "addons/turbo.h"
32+
#include "addons/sidewindergp.h"
3233
#include "addons/slider_socd.h"
3334
#include "addons/wiiext.h"
3435

@@ -200,6 +201,9 @@ void Storage::setDefaultAddonOptions()
200201
addonOptions.wiiExtensionSCLPin = WII_EXTENSION_I2C_SCL_PIN;
201202
addonOptions.wiiExtensionBlock = (WII_EXTENSION_I2C_BLOCK == i2c0) ? 0 : 1;
202203
addonOptions.wiiExtensionSpeed = WII_EXTENSION_I2C_SPEED;
204+
addonOptions.sidewinderGPPinTrigger = SIDEWINDERGP_PIN_TRIGGER;
205+
addonOptions.sidewinderGPPinClock = SIDEWINDERGP_PIN_CLOCK;
206+
addonOptions.sidewinderGPPinData = SIDEWINDERGP_PIN_DATA;
203207
addonOptions.AnalogInputEnabled = ANALOG_INPUT_ENABLED;
204208
addonOptions.BoardLedAddonEnabled = BOARD_LED_ENABLED;
205209
addonOptions.BootselButtonAddonEnabled = BOOTSEL_BUTTON_ENABLED;
@@ -214,6 +218,7 @@ void Storage::setDefaultAddonOptions()
214218
addonOptions.ReverseInputEnabled = REVERSE_ENABLED;
215219
addonOptions.TurboInputEnabled = TURBO_ENABLED;
216220
addonOptions.WiiExtensionAddonEnabled = WII_EXTENSION_ENABLED;
221+
addonOptions.SidewinderGPEnabled = SIDEWINDERGP_INPUT_ENABLED;
217222
setAddonOptions(addonOptions);
218223
}
219224

0 commit comments

Comments
 (0)