|
|
|
@ -12,7 +12,7 @@ PIN # USAGE
@@ -12,7 +12,7 @@ PIN # USAGE
|
|
|
|
|
VCC +3.3V ONLY |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#define DATA_PIN 2 |
|
|
|
|
#define DATA_PIN 7 |
|
|
|
|
|
|
|
|
|
// how often to poll, 100? 14? polling must not occur faster than every 20 ms
|
|
|
|
|
#define POLL_DELAY 14 |
|
|
|
@ -23,23 +23,41 @@ PIN # USAGE
@@ -23,23 +23,41 @@ PIN # USAGE
|
|
|
|
|
|
|
|
|
|
//#define DEBUG
|
|
|
|
|
|
|
|
|
|
#ifdef GAMECUBE |
|
|
|
|
#define AXIS_CENTER_IN 135 |
|
|
|
|
#define AXIS_MAX_IN 230 |
|
|
|
|
#define AXIS_MIN_IN 30 |
|
|
|
|
|
|
|
|
|
#define TRIGGER_MAX_IN 236 |
|
|
|
|
#define TRIGGER_MIN_IN 36 |
|
|
|
|
|
|
|
|
|
#else // N64
|
|
|
|
|
#define AXIS_CENTER_IN 0 |
|
|
|
|
#define AXIS_MAX_IN 100 |
|
|
|
|
#define AXIS_MIN_IN -100 |
|
|
|
|
#define AXIS_MAX_IN 80 |
|
|
|
|
#define AXIS_MIN_IN -80 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include "gamepad/Gamepad.h" |
|
|
|
|
#include "util.cpp" |
|
|
|
|
|
|
|
|
|
// Define a N64 Controller
|
|
|
|
|
CN64Controller N64Controller(DATA_PIN); |
|
|
|
|
#ifdef GAMECUBE |
|
|
|
|
typedef CGamecubeController NintendoController; |
|
|
|
|
typedef Gamecube_Report_t ControllerReport; |
|
|
|
|
#else // N64
|
|
|
|
|
typedef CN64Controller NintendoController; |
|
|
|
|
typedef N64_Report_t ControllerReport; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// Define a Controller
|
|
|
|
|
NintendoController controller(DATA_PIN); |
|
|
|
|
|
|
|
|
|
#define REPORT_SIZE 4 |
|
|
|
|
uint8_t oldReport[REPORT_SIZE]; |
|
|
|
|
#define NINTENDO_REPORT_SIZE 4 |
|
|
|
|
uint8_t oldReport[NINTENDO_REPORT_SIZE]; |
|
|
|
|
|
|
|
|
|
GAMEPAD_CLASS gamepad; |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
void print_n64_report(N64_Report_t &controller, N64_Status_t &n64_status) { |
|
|
|
|
void print_report(ControllerReport &controller) { |
|
|
|
|
Serial.print("buttons: "); |
|
|
|
|
Serial.print(controller.a ? "A" : "-"); |
|
|
|
|
Serial.print(controller.b ? "B" : "-"); |
|
|
|
@ -47,56 +65,61 @@ void print_n64_report(N64_Report_t &controller, N64_Status_t &n64_status) {
@@ -47,56 +65,61 @@ void print_n64_report(N64_Report_t &controller, N64_Status_t &n64_status) {
|
|
|
|
|
Serial.print(controller.l ? "L" : "-"); |
|
|
|
|
Serial.print(controller.r ? "R" : "-"); |
|
|
|
|
Serial.print(controller.start ? "S" : "-"); |
|
|
|
|
#ifdef GAMECUBE |
|
|
|
|
Serial.print(controller.y ? "Y" : "-"); |
|
|
|
|
Serial.print(controller.x ? "X" : "-"); |
|
|
|
|
#endif |
|
|
|
|
Serial.print(" DPAD: "); |
|
|
|
|
Serial.print(controller.dup ? "U" : "-"); |
|
|
|
|
Serial.print(controller.ddown ? "D" : "-"); |
|
|
|
|
Serial.print(controller.dleft ? "L" : "-"); |
|
|
|
|
Serial.print(controller.dright ? "R" : "-"); |
|
|
|
|
Serial.print(" C: "); |
|
|
|
|
Serial.print(controller.cup ? "U" : "-"); |
|
|
|
|
Serial.print(controller.cdown ? "D" : "-"); |
|
|
|
|
Serial.print(controller.cleft ? "L" : "-"); |
|
|
|
|
Serial.print(controller.cright ? "R" : "-"); |
|
|
|
|
Serial.print(" Y: "); |
|
|
|
|
Serial.print(controller.yAxis); |
|
|
|
|
Serial.print(" YT: "); |
|
|
|
|
Serial.print(translateAxis(-controller.yAxis)); |
|
|
|
|
Serial.print(-translateAxis(controller.yAxis)); |
|
|
|
|
Serial.print(" X: "); |
|
|
|
|
Serial.print(controller.xAxis); |
|
|
|
|
Serial.print(" XT: "); |
|
|
|
|
Serial.print(translateAxis(controller.xAxis)); |
|
|
|
|
#ifdef GAMECUBE |
|
|
|
|
Serial.print(" CY: "); |
|
|
|
|
Serial.print(controller.cyAxis); |
|
|
|
|
Serial.print(" CYT: "); |
|
|
|
|
Serial.print(-translateAxis(controller.cyAxis)); |
|
|
|
|
Serial.print(" CX: "); |
|
|
|
|
Serial.print(controller.cxAxis); |
|
|
|
|
Serial.print(" CXT: "); |
|
|
|
|
Serial.print(translateAxis(controller.cxAxis)); |
|
|
|
|
Serial.print(" LEFT: "); |
|
|
|
|
Serial.print(controller.left); |
|
|
|
|
Serial.print(" TLEFT: "); |
|
|
|
|
Serial.print(translateTrigger(controller.left)); |
|
|
|
|
Serial.print(" RIGHT: "); |
|
|
|
|
Serial.print(controller.right); |
|
|
|
|
Serial.print(" TRIGHT: "); |
|
|
|
|
Serial.print(translateTrigger(controller.right)); |
|
|
|
|
#else // N64
|
|
|
|
|
Serial.print(" C: "); |
|
|
|
|
Serial.print(controller.cup ? "U" : "-"); |
|
|
|
|
Serial.print(controller.cdown ? "D" : "-"); |
|
|
|
|
Serial.print(controller.cleft ? "L" : "-"); |
|
|
|
|
Serial.print(controller.cright ? "R" : "-"); |
|
|
|
|
#endif |
|
|
|
|
Serial.println(); |
|
|
|
|
/*
|
|
|
|
|
// Print device information
|
|
|
|
|
Serial.print(F("Device: ")); |
|
|
|
|
switch (n64_status.device) { |
|
|
|
|
case NINTENDO_DEVICE_N64_NONE: |
|
|
|
|
Serial.println(F("No N64 Controller found!")); |
|
|
|
|
return; |
|
|
|
|
break; |
|
|
|
|
case NINTENDO_DEVICE_N64_WIRED: |
|
|
|
|
Serial.println(F("Original Nintendo N64 Controller")); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
Serial.print(F("Unknown ")); |
|
|
|
|
Serial.println(n64_status.device, HEX); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
void setup() { |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.begin(115200); |
|
|
|
|
if (N64Controller.begin()) { |
|
|
|
|
Serial.println(F("N64 begin() success.")); |
|
|
|
|
if (controller.begin()) { |
|
|
|
|
Serial.println(F("controller.begin() success.")); |
|
|
|
|
} else { |
|
|
|
|
Serial.println(F("N64 begin() fail.")); |
|
|
|
|
Serial.println(F("controller.begin() fail.")); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
N64Controller.begin(); |
|
|
|
|
controller.begin(); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
gamepad.begin(); |
|
|
|
@ -105,25 +128,24 @@ void setup() {
@@ -105,25 +128,24 @@ void setup() {
|
|
|
|
|
void loop() { |
|
|
|
|
delay(POLL_DELAY); |
|
|
|
|
// Try to read the controller data
|
|
|
|
|
if (N64Controller.read()) { |
|
|
|
|
if (controller.read()) { |
|
|
|
|
// Print Controller information
|
|
|
|
|
auto controller = N64Controller.getReport(); |
|
|
|
|
auto report = controller.getReport(); |
|
|
|
|
|
|
|
|
|
if (memcmp(oldReport, controller.raw8, REPORT_SIZE)) { |
|
|
|
|
memcpy(oldReport, controller.raw8, REPORT_SIZE); |
|
|
|
|
if (memcmp(oldReport, report.raw8, NINTENDO_REPORT_SIZE)) { |
|
|
|
|
memcpy(oldReport, report.raw8, NINTENDO_REPORT_SIZE); |
|
|
|
|
} else { |
|
|
|
|
// nothing changed
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
auto status = N64Controller.getStatus(); |
|
|
|
|
print_n64_report(controller, status); |
|
|
|
|
print_report(report); |
|
|
|
|
#endif |
|
|
|
|
uint8_t c = 0; // for now just do 1 pad
|
|
|
|
|
gamepad.buttons(c, 0); |
|
|
|
|
if (controller.start) { |
|
|
|
|
if (controller.ddown) { |
|
|
|
|
if (report.start) { |
|
|
|
|
if (report.ddown) { |
|
|
|
|
// then only send menu, nothing else
|
|
|
|
|
gamepad.press(c, BUTTON_MENU); |
|
|
|
|
gamepad.setHatSync(c, DPAD_CENTER); |
|
|
|
@ -131,36 +153,53 @@ void loop() {
@@ -131,36 +153,53 @@ void loop() {
|
|
|
|
|
} |
|
|
|
|
gamepad.press(c, BUTTON_START); |
|
|
|
|
} |
|
|
|
|
if (controller.a) { |
|
|
|
|
if (report.a) { |
|
|
|
|
gamepad.press(c, BUTTON_A); |
|
|
|
|
} |
|
|
|
|
if (controller.b) { |
|
|
|
|
if (report.b) { |
|
|
|
|
gamepad.press(c, BUTTON_B); |
|
|
|
|
} |
|
|
|
|
if (controller.z) { |
|
|
|
|
if (report.z) { |
|
|
|
|
gamepad.press(c, BUTTON_TR); |
|
|
|
|
} |
|
|
|
|
if (controller.l) { |
|
|
|
|
if (report.l) { |
|
|
|
|
gamepad.press(c, BUTTON_L); |
|
|
|
|
} |
|
|
|
|
if (controller.r) { |
|
|
|
|
if (report.r) { |
|
|
|
|
gamepad.press(c, BUTTON_R); |
|
|
|
|
} |
|
|
|
|
auto hat = calculateDpadDirection(controller.dup, controller.ddown, controller.dleft, controller.dright); |
|
|
|
|
auto cHat = dpadToAxis(calculateDpadDirection(controller.cup, controller.cdown, controller.cleft, controller.cright)); |
|
|
|
|
gamepad.setAxis(c, translateAxis(controller.xAxis), translateAxis(-controller.yAxis), cHat.x, cHat.y, 0, 0, hat); |
|
|
|
|
auto hat = calculateDpadDirection(report.dup, report.ddown, report.dleft, report.dright); |
|
|
|
|
#ifdef GAMECUBE |
|
|
|
|
if (report.y) { |
|
|
|
|
gamepad.press(c, BUTTON_Y); |
|
|
|
|
} |
|
|
|
|
if (report.x) { |
|
|
|
|
gamepad.press(c, BUTTON_X); |
|
|
|
|
} |
|
|
|
|
gamepad.setAxis(c, |
|
|
|
|
translateAxis(report.xAxis), |
|
|
|
|
-translateAxis(report.yAxis), |
|
|
|
|
translateAxis(report.cxAxis), |
|
|
|
|
-translateAxis(report.cyAxis), |
|
|
|
|
translateTrigger(report.left), |
|
|
|
|
translateTrigger(report.right), |
|
|
|
|
hat); |
|
|
|
|
#else // N64
|
|
|
|
|
auto cHat = dpadToAxis(calculateDpadDirection(report.cup, report.cdown, report.cleft, report.cright)); |
|
|
|
|
gamepad.setAxis(c, translateAxis(report.xAxis), -translateAxis(report.yAxis), cHat.x, cHat.y, 0, 0, hat); |
|
|
|
|
#endif |
|
|
|
|
} else { |
|
|
|
|
// Add debounce if reading failed
|
|
|
|
|
delay(5000); |
|
|
|
|
delay(100); |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
Serial.println(F("Error reading N64 controller.")); |
|
|
|
|
if (N64Controller.begin()) { |
|
|
|
|
Serial.println(F("N64 begin() success.")); |
|
|
|
|
Serial.println(F("Error reading controller.")); |
|
|
|
|
if (controller.begin()) { |
|
|
|
|
Serial.println(F("controller.begin() success.")); |
|
|
|
|
} else { |
|
|
|
|
Serial.println(F("N64 begin() fail.")); |
|
|
|
|
Serial.println(F("controller.begin() fail.")); |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
N64Controller.begin(); |
|
|
|
|
controller.begin(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|