This repository has been archived by the owner on Jan 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
psx-bluetooth-controller.ino
160 lines (136 loc) · 6 KB
/
psx-bluetooth-controller.ino
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
/**
* Adafruit Feather M0 Bluefruit LE Gamepad implementation
*
* Written by Cosmin Stamate @monovertex, based on the examples at
* https://github.com/adafruit/Adafruit_BluefruitLE_nRF51
*
* This file is an adaptation from https://github.com/adafruit/Adafruit_BluefruitLE_nRF51/blob/master/examples/hidkeyboard/hidkeyboard.ino
*
* Credits:
* - Bill Porter: http://www.billporter.info/2010/06/05/playstation-2-controller-arduino-library-v1-0/
* - Evan Kale: https://www.instructables.com/id/Bluetooth-PS2-Controller/
* - Ruiz Brothers: https://learn.adafruit.com/custom-wireless-bluetooth-cherry-mx-gamepad/software
*
* Their work and code helped me understand how to implement this.
*
* Changelog:
* - v0.1.0 - 2019/03/14
* Initial implementation, basic button support
*/
// LIBRARIES
/*********************************************************************************/
#include "PS2X_lib.h"
#include <SoftwareSerial.h>
/*********************************************************************************/
// CONFIGURATION & CONSTANTS
/*********************************************************************************/
#define PSX_DAT 11
#define PSX_CMD 10
#define PSX_ATT 5
#define PSX_CLK 4
#define BT_RX 2
#define BT_TX 3
#define AXIS_DEADZONE 40
#define AXIS_RANGE_CENTER 128
#define AXIS_NOISE_LIMIT 2
#define GAMEPAD_READ_DELAY 5
#define SERIAL_RATE 9600
#define BT_SERIAL_RATE 9600
#define INITIAL_DELAY 500
// #define DEBUG_TO_SERIAL // Uncomment this to print debug statements.
/*********************************************************************************/
// OBJECT INSTANTIATION
/*********************************************************************************/
PS2X gamepad;
SoftwareSerial BTSerial(BT_RX, BT_TX);
/*********************************************************************************/
// GLOBALS & HELPERS
/*********************************************************************************/
bool isGamepadInitialized = false;
uint32_t previousButtonState = 0;
int8_t previousX1 = 0;
int8_t previousY1 = 0;
int8_t previousX2 = 0;
int8_t previousY2 = 0;
// Error helper function.
void error(const __FlashStringHelper*err) {
Serial.println(err);
while (1);
}
int8_t readAxis(int axisIdentifier) {
int rawValue = gamepad.Analog(axisIdentifier);
int normalizedValue = rawValue - AXIS_RANGE_CENTER;
if (abs(normalizedValue) < AXIS_DEADZONE) { return 0; }
return (int8_t)normalizedValue;
}
bool areAxisValuesEqual(int8_t valueA, int8_t valueB) {
return abs(valueA - valueB) <= AXIS_NOISE_LIMIT;
}
/*********************************************************************************/
// SETUP
/*********************************************************************************/
void setup(void) {
Serial.begin(SERIAL_RATE);
BTSerial.begin(BT_SERIAL_RATE);
delay(INITIAL_DELAY);
uint8_t gamepadError = gamepad.config_gamepad(PSX_CLK, PSX_CMD, PSX_ATT, PSX_DAT, false, false);
if (gamepadError) { return error(F("ERROR: Could not configure gamepad.")); }
isGamepadInitialized = true;
}
/*********************************************************************************/
// LOOP
/*********************************************************************************/
void loop() {
delay(GAMEPAD_READ_DELAY);
if (!isGamepadInitialized) { return; }
gamepad.read_gamepad();
uint32_t currentButtonState = gamepad.ButtonDataByte();
int8_t currentX1 = readAxis(PSS_LX);
int8_t currentY1 = readAxis(PSS_LY);
int8_t currentX2 = readAxis(PSS_RX);
int8_t currentY2 = readAxis(PSS_RY);
if (previousButtonState == currentButtonState &&
areAxisValuesEqual(previousX1, currentX1) &&
areAxisValuesEqual(previousY1, currentY1) &&
areAxisValuesEqual(previousX2, currentX2) &&
areAxisValuesEqual(previousY2, currentY2)) { return; }
#ifdef DEBUG_TO_SERIAL
Serial.println(String("Axis values: LX=") + currentX1 + " LY= " + currentY1 + " RX=" + currentX2 + " RY= " + currentY2);
if (gamepad.Button(PSB_TRIANGLE)) { Serial.println("PSB_TRIANGLE was pressed"); }
if (gamepad.Button(PSB_CIRCLE)) { Serial.println("PSB_CIRCLE was pressed"); }
if (gamepad.Button(PSB_CROSS)) { Serial.println("PSB_CROSS was pressed"); }
if (gamepad.Button(PSB_SQUARE)) { Serial.println("PSB_SQUARE was pressed"); }
if (gamepad.Button(PSB_PAD_UP)) { Serial.println("PSB_PAD_UP was pressed"); }
if (gamepad.Button(PSB_PAD_RIGHT)) { Serial.println("PSB_PAD_RIGHT was pressed"); }
if (gamepad.Button(PSB_PAD_DOWN)) { Serial.println("PSB_PAD_DOWN was pressed"); }
if (gamepad.Button(PSB_PAD_LEFT)) { Serial.println("PSB_PAD_LEFT was pressed"); }
if (gamepad.Button(PSB_L1)) { Serial.println("PSB_L1 was pressed"); }
if (gamepad.Button(PSB_L2)) { Serial.println("PSB_L2 was pressed"); }
if (gamepad.Button(PSB_R1)) { Serial.println("PSB_R1 was pressed"); }
if (gamepad.Button(PSB_R2)) { Serial.println("PSB_R2 was pressed"); }
if (gamepad.Button(PSB_SELECT)) { Serial.println("PSB_SELECT was pressed"); }
if (gamepad.Button(PSB_START)) { Serial.println("PSB_START was pressed"); }
#endif
previousButtonState = currentButtonState;
previousX1 = currentX1;
previousY1 = currentY1;
previousX2 = currentX2;
previousY2 = currentY2;
transmitGamepadStateToBT(currentButtonState, currentX1, currentY1, currentX2, currentY2);
}
/*********************************************************************************/
// TRANSMISSION
/*********************************************************************************/
void transmitGamepadStateToBT(uint32_t buttonState, int8_t x1, int8_t y1, int8_t x2, int8_t y2)
{
BTSerial.write((uint8_t)0xFD);
BTSerial.write((uint8_t)0x06);
BTSerial.write((uint8_t)x1);
BTSerial.write((uint8_t)y1);
BTSerial.write((uint8_t)x2);
BTSerial.write((uint8_t)y2);
uint8_t buttonState1 = buttonState & 0xFF;
uint8_t buttonState2 = (buttonState >> 8) & 0xFF;
BTSerial.write((uint8_t)buttonState1);
BTSerial.write((uint8_t)buttonState2);
}