-
Notifications
You must be signed in to change notification settings - Fork 1
/
gamegirl-joypad.cpp
309 lines (261 loc) · 8.87 KB
/
gamegirl-joypad.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <wiringPi.h>
#include <iostream>
#include <mcp23s17.h>
#define die(str, args...) do { \
perror(str); \
exit(EXIT_FAILURE); \
} while(0)
#define BASE 100 // offset for GPIO expander numbering
using namespace std;
int _SHDN = 25; // GPIO25 - Power switch
/* MCP23S17 PINOUT Pin 1(GPB0) start at GPIO 100 GPB0 = 100 | GPA0 = 108
* LBO | 1 (100) - GPB0 GPA7 - (115) 28 | R1
* SS1 | 2 (101) - GPB1 GPA6 - (114) 27 | Select
* WiFi | 3 (102) - GPB2 GPA5 - (113) 26 | Start
* Left | 4 (103) - GPB3 GPA4 - (112) 25 | Y (West)
* Up | 5 (104) - GPB4 GPA3 - (111) 24 | X (North)
* Right | 6 (105) - GPB5 GPA2 - (110) 23 | A (East)
* Down | 7 (106) - GPB6 GPA1 - (109) 22 | B (South)
* L1 | 8 (107) - GPB7 GPA0 - (108) 21 | AMP
* 3V3 | 9 - VDD INTA - 20 | NC
* GND | 10 - VSS INTB - 19 | NC
* GND | 11 - CS RST - 18 | 3V3
* SCK | 12 - SCK A2 - 17 | GND
* MOSI | 13 - SI A1 - 16 | GND
* MISO | 14 - SO A0 - 15 | GND
*/
int btn_left = 103;
int btn_up = 104;
int btn_right = 105;
int btn_down = 106;
int btn_l1 = 107;
int btn_b = 109;
int btn_a = 110;
int btn_x = 111;
int btn_y = 112;
int btn_start = 113;
int btn_selec = 114;
int btn_r1 = 115;
int _LBO = 100; //Critical Low Battery alert, set as input pulled high
int _SS1 = 101; //SPI Chip Select pin for LCD, pull high
int _WiFi_EN = 102; //Pull high to enable
int _AMP_EN = 108; //Pull high to enable
bool WiFi_status = 1; //Sets to on by default
bool AMP_status = 1; //Sets to on by default
void set_key_bit(int fd, int button) {
if (ioctl(fd, UI_SET_KEYBIT, button) < 0) {
die("error: ioctl");
}
}
void set_button_event(int fd, int button, int value) {
struct input_event ev;
ev.type = EV_KEY;
ev.code = button;
ev.value = value;
if (write(fd, &ev, sizeof(struct input_event)) < 0) {
die("error: write");
}
}
int main() {
unsigned i;
// Initialize GPIO
wiringPiSetupGpio();
// Initialize MCP23S17
mcp23s17Setup(BASE, 1, 0) ;
//Set button input pins on MCP23S17 to INPUT with PullUps enabled
for (i = 2 ; i < 7 ; ++i){ //102 - 107
pinMode(BASE+i, INPUT);
pullUpDnControl(BASE+i,PUD_UP);
}
for (i = 9 ; i < 15 ; ++i){ //109-115
pinMode(BASE+i, INPUT);
pullUpDnControl(BASE+i,PUD_UP);
}
//Power switch setup
pinMode(_SHDN, INPUT);
pullUpDnControl(_SHDN,PUD_UP);
//Sets Chip Select pin of LCD high disabling the SPI connection
pinMode(_SS1,OUTPUT);
pullUpDnControl(_SS1,PUD_UP);
//Enables WiFi by default
pinMode(_WiFi_EN,OUTPUT);
digitalWrite(_WiFi_EN,1);
//Sets up Audio, already on by default
pinMode(_AMP_EN,OUTPUT);
digitalWrite(_AMP_EN,1);
// Initialise udev
struct uinput_user_dev uidev;
struct input_event ev;
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (fd < 0)
die("error: open");
if (ioctl(fd, UI_SET_EVBIT, EV_KEY) < 0)
die("error: ioctl");
if (ioctl(fd, UI_SET_EVBIT, EV_REL) < 0)
die("error: ioctl");
if (ioctl(fd, UI_SET_EVBIT, EV_SYN) < 0)
die("error: ioctl");
set_key_bit(fd, BTN_DPAD_UP);
set_key_bit(fd, BTN_DPAD_DOWN);
set_key_bit(fd, BTN_DPAD_LEFT);
set_key_bit(fd, BTN_DPAD_RIGHT);
set_key_bit(fd, BTN_NORTH);
set_key_bit(fd, BTN_SOUTH);
set_key_bit(fd, BTN_WEST);
set_key_bit(fd, BTN_EAST);
set_key_bit(fd, BTN_START);
set_key_bit(fd, BTN_SELECT);
set_key_bit(fd, BTN_TL);
set_key_bit(fd, BTN_TR);
ioctl(fd, UI_SET_EVBIT, EV_ABS);
ioctl(fd, UI_SET_ABSBIT, ABS_X);
ioctl(fd, UI_SET_ABSBIT, ABS_Y);
uidev.absmin[ABS_X] = 0;
uidev.absmax[ABS_X] = 4;
uidev.absmin[ABS_Y] = 0;
uidev.absmax[ABS_Y] = 4;
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Gamegirl Controller");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 1;
uidev.id.product = 1;
uidev.id.version = 1;
if (write(fd, &uidev, sizeof(uidev)) < 0)
die("error: write");
if (ioctl(fd, UI_DEV_CREATE) < 0)
die("error: ioctl");
int up_button, up_button_old = 1;
int down_button, down_button_old = 1;
int left_button, left_button_old = 1;
int right_button, right_button_old = 1;
int x_button, x_button_old = 1;
int b_button, b_button_old = 1;
int y_button, y_button_old = 1;
int a_button, a_button_old = 1;
int start_button, start_button_old = 1;
int selec_button, selec_button_old = 1;
int l1_button, l1_button_old = 1;
int r1_button, r1_button_old = 1;
int powerswitch = 1;
int LBO = 1;
int toggle_timeout = 0; //Toggle timeout for toggling WiFi or Amp
int shdn_delay = 0; //Delay (debounce) for shutdown switch
int LBO_delay = 0; //Delay for LBO
while (1) {
// Read GPIO
up_button_old = up_button;
down_button_old = down_button;
left_button_old = left_button;
right_button_old = right_button;
x_button_old = x_button;
b_button_old = b_button;
y_button_old = y_button;
a_button_old = a_button;
start_button_old = start_button;
selec_button_old = selec_button;
l1_button_old = l1_button;
r1_button_old = r1_button;
up_button = digitalRead(btn_up); //
down_button = digitalRead(btn_down); //
left_button = digitalRead(btn_left); //
right_button = digitalRead(btn_right); //
x_button = digitalRead(btn_x); //
b_button = digitalRead(btn_b); //
y_button = digitalRead(btn_y); //
a_button = digitalRead(btn_a); //
start_button = digitalRead(btn_start); //
selec_button = digitalRead(btn_selec); //
l1_button = digitalRead(btn_l1); //
r1_button = digitalRead(btn_r1); //
powerswitch = digitalRead(_SHDN); //
LBO = digitalRead(_LBO); //
// Write to udev
if (up_button != up_button_old) {
set_button_event(fd, BTN_DPAD_UP, up_button != 0);
}
if (down_button != down_button_old) {
set_button_event(fd, BTN_DPAD_DOWN, down_button != 0);
}
if (left_button != left_button_old) {
set_button_event(fd, BTN_DPAD_LEFT, left_button != 0);
}
if (right_button != right_button_old) {
set_button_event(fd, BTN_DPAD_RIGHT, right_button != 0);
}
if (x_button != x_button_old) {
set_button_event(fd, BTN_NORTH, x_button != 0);
}
if (b_button != b_button_old) {
set_button_event(fd, BTN_SOUTH, b_button != 0);
}
if (y_button != y_button_old) {
set_button_event(fd, BTN_WEST, y_button != 0);
}
if (a_button != a_button_old) {
set_button_event(fd, BTN_EAST, a_button != 0);
}
if (start_button != start_button_old) {
set_button_event(fd, BTN_START, start_button != 0);
}
if (selec_button == 0 && toggle_timeout > 119){ //mode button | Sel+L1 WiFi toggle | Sel+R1 = Amp toggle |
if (l1_button == 0 ){
WiFi_status = !WiFi_status;
digitalWrite(_WiFi_EN, WiFi_status);
toggle_timeout = 0;
}
else if(r1_button == 0){
AMP_status = !AMP_status;
digitalWrite(_AMP_EN,AMP_status);
toggle_timeout = 0;
}
}
else if(selec_button != selec_button_old)
set_button_event(fd, BTN_SELECT, selec_button != 0);
}
if (l1_button != l1_button_old) {
set_button_event(fd, BTN_TL, l1_button != 0);
}
if (r1_button != r1_button_old) {
set_button_event(fd, BTN_TR, r1_button != 0);
}
if (LBO == 0) {
LBO_delay++;
if(LBO_delay > 59) {
system("echo Critically low battery shutting down now!\n");
system("echo -n \"SHUTDOWN\" | nc -u -w1 127.0.0.1 55355");
}
else
LDO_delay = 0;
if (powerswitch == 0) {
shdn_delay++;
if(shdn_delay > 59) {
system("echo Power button toggled, shutting down now!\n");
system("echo -n \"SHUTDOWN\" | nc -u -w1 127.0.0.1 55355");
}
}
else
shdn_delay = 0;
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
if (write(fd, &ev, sizeof(struct input_event)) < 0)
die("error: write");
delay(1000/120);
if(toggle_timeout < 119)
toggle_timeout++;
}
// Destroy udev
if (ioctl(fd, UI_DEV_DESTROY) < 0)
die("error: ioctl");
close(fd);
return 0;
}