Skip to content

Commit 6b9bfaa

Browse files
committed
Added Sidewinder Gamepad addon
1 parent 4d41b22 commit 6b9bfaa

File tree

10 files changed

+192
-1
lines changed

10 files changed

+192
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ src/addons/playernum.cpp
123123
src/addons/playerleds.cpp
124124
src/addons/ps4mode.cpp
125125
src/addons/reverse.cpp
126+
src/addons/sidewindergp.cpp
126127
src/addons/turbo.cpp
127128
src/addons/slider_socd.cpp
128129
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
@@ -253,6 +253,37 @@ Classic Controller support includes Classic, Classic Pro, and NES/SNES Mini Cont
253253

254254
Original Classic Controller L & R triggers are analog sensitive, where Pro triggers are not.
255255

256+
### Sidewinder Gamepad
257+
258+
![GP2040 Configurator - Sidewinder Gamepad](assets/images/gpc-add-ons-sidewindergp.png)
259+
260+
Designed to be mapped on DA-15 gameport of the Sidewinder Gamepad.
261+
262+
Connections:
263+
264+
- DA-15 pins 1, 8, 9, 15 to +5V
265+
- DA-15 pins 4, 5, 12 to GND
266+
- DA-15 pin 2 to Clock pin
267+
- DA-15 pin 3 to Trigger pin
268+
- DA-15 pin 7 to Data pin
269+
270+
Mapping is a follows:
271+
272+
| Sidewinder GP | GP2040-CE |
273+
|---------------|-----------|
274+
| D-Pad | Analog |
275+
| A | B1 |
276+
| B | B2 |
277+
| C | L3 |
278+
| X | B3 |
279+
| Y | B4 |
280+
| Z | R3 |
281+
| LT | L1 |
282+
| RT | R1 |
283+
| Start | S2 |
284+
| M | S1 |
285+
286+
256287
## Data Backup and Restoration
257288

258289
![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
@@ -805,6 +805,9 @@ std::string setAddonOptions()
805805
docToPin(addonOptions.wiiExtensionSDAPin, doc, "wiiExtensionSDAPin");
806806
docToPin(addonOptions.wiiExtensionSCLPin, doc, "wiiExtensionSCLPin");
807807
docToValue(addonOptions.wiiExtensionBlock, doc, "wiiExtensionBlock");
808+
docToPin(addonOptions.sidewinderGPPinTrigger, doc, "sidewinderGPPinTrigger");
809+
docToPin(addonOptions.sidewinderGPPinClock, doc, "sidewinderGPPinClock");
810+
docToPin(addonOptions.sidewinderGPPinData, doc, "sidewinderGPPinData");
808811
docToValue(addonOptions.wiiExtensionSpeed, doc, "wiiExtensionSpeed");
809812
docToValue(addonOptions.AnalogInputEnabled, doc, "AnalogInputEnabled");
810813
docToValue(addonOptions.BoardLedAddonEnabled, doc, "BoardLedAddonEnabled");
@@ -820,6 +823,7 @@ std::string setAddonOptions()
820823
docToValue(addonOptions.ReverseInputEnabled, doc, "ReverseInputEnabled");
821824
docToValue(addonOptions.TurboInputEnabled, doc, "TurboInputEnabled");
822825
docToValue(addonOptions.WiiExtensionAddonEnabled, doc, "WiiExtensionAddonEnabled");
826+
docToValue(addonOptions.SidewinderGPEnabled, doc, "SidewinderGPEnabled");
823827

824828
Storage::getInstance().setAddonOptions(addonOptions);
825829

@@ -981,6 +985,9 @@ std::string getAddonOptions()
981985
writeDoc(doc, "wiiExtensionSCLPin", addonOptions.wiiExtensionSCLPin == 0xFF ? -1 : addonOptions.wiiExtensionSCLPin);
982986
writeDoc(doc, "wiiExtensionBlock", addonOptions.wiiExtensionBlock);
983987
writeDoc(doc, "wiiExtensionSpeed", addonOptions.wiiExtensionSpeed);
988+
writeDoc(doc, "sidewinderGPPinTrigger", addonOptions.sidewinderGPPinTrigger == 0xFF ? -1 : addonOptions.sidewinderGPPinTrigger);
989+
writeDoc(doc, "sidewinderGPPinClock", addonOptions.sidewinderGPPinClock == 0xFF ? -1 : addonOptions.sidewinderGPPinClock);
990+
writeDoc(doc, "sidewinderGPPinData", addonOptions.sidewinderGPPinData == 0xFF ? -1 : addonOptions.sidewinderGPPinData);
984991
writeDoc(doc, "AnalogInputEnabled", addonOptions.AnalogInputEnabled);
985992
writeDoc(doc, "BoardLedAddonEnabled", addonOptions.BoardLedAddonEnabled);
986993
writeDoc(doc, "BuzzerSpeakerAddonEnabled", addonOptions.BuzzerSpeakerAddonEnabled);
@@ -995,6 +1002,7 @@ std::string getAddonOptions()
9951002
writeDoc(doc, "ReverseInputEnabled", addonOptions.ReverseInputEnabled);
9961003
writeDoc(doc, "TurboInputEnabled", addonOptions.TurboInputEnabled);
9971004
writeDoc(doc, "WiiExtensionAddonEnabled", addonOptions.WiiExtensionAddonEnabled);
1005+
writeDoc(doc, "SidewinderGPEnabled", addonOptions.SidewinderGPEnabled);
9981006

9991007
addUsedPinsArray(doc);
10001008

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

www

0 commit comments

Comments
 (0)