Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadeReogen committed Mar 22, 2024
2 parents 198a747 + a5d9cd4 commit 94c8908
Showing 1 changed file with 165 additions and 98 deletions.
263 changes: 165 additions & 98 deletions pico_w/src/picontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <pico/cyw43_arch.h>
#include <uni.h>
#include "math.h"

#include "hardware/gpio.h"
#include "pico/stdlib.h"
Expand All @@ -15,14 +16,19 @@
#error "Pico W must use BLUEPAD32_PLATFORM_CUSTOM"
#endif

// Joystick Analog dead zone
#define DEAD_ZONE 150

#define UP_BTN 0
#define DOWN_BTN 1
#define LEFT_BTN 2
#define RIGHT_BTN 3
#define FIRE_BTN 4
#define INPUT_A 5 // Paddle A /Touch Tablet < --- No idea how tf these work. Can't test them
#define INPUT_B 6 // Paddle B /Touch Tablet < --- I just know that the extra inputs are mapped to this.

// Declarations
static void trigger_event_on_gamepad(uni_hid_device_t *d);
static void update_gamepad(uni_hid_device_t *d);

//
// Platform Overrides
Expand Down Expand Up @@ -58,6 +64,18 @@ static void picontrol_on_init_complete(void)
gpio_init(RIGHT_BTN);
gpio_init(FIRE_BTN);

/*
TODO:
Inactivce as I have no clue how to implement these.
What do they do? --> Need Paddle /Tablet
gpio_init(INPUT_A);
gpio_init(INPUT_B);
gpio_set_dir(INPUT_A, GPIO_OUT);
gpio_set_dir(INPUT_B, GPIO_OUT);
*/

gpio_set_dir(UP_BTN, GPIO_OUT);
gpio_set_dir(DOWN_BTN, GPIO_OUT);
gpio_set_dir(LEFT_BTN, GPIO_OUT);
Expand Down Expand Up @@ -102,146 +120,194 @@ static void picontrol_on_controller_data(uni_hid_device_t *d, uni_controller_t *
}
prev = *ctl;
// PRINT FULL DEBUG LOG
// logi("(%p) id=%d ", d, uni_hid_device_get_idx_for_instance(d));
// uni_controller_dump(ctl);
/* logi("(%p) id=%d ", d, uni_hid_device_get_idx_for_instance(d));
uni_controller_dump(ctl); */

switch (ctl->klass)
{
case UNI_CONTROLLER_CLASS_GAMEPAD:
{
gp = &ctl->gamepad;
bool up = true, down = true, left = true, right = true;

if (gp->dpad == 0)
{
gpio_put(UP_BTN, true);
gpio_put(DOWN_BTN, true);
gpio_put(LEFT_BTN, true);
gpio_put(RIGHT_BTN, true);
gpio_put(UP_BTN, up);
gpio_put(DOWN_BTN, down);
gpio_put(LEFT_BTN, left);
gpio_put(RIGHT_BTN, right);
}

int x = gp->axis_x;
int y = gp->axis_y;

// DEBUG: Print Left stick Axis
//logi("Axis z: %d, Axis y: %d\n", x, y);

if (gp->dpad != 0 || x > 50 || y > 50 || x < -50 || y < -50)
/*
* I set the Dpad to have a higher priority than the analog stick
*
* Why?
* It is improbable that a user wants to input direction with both at the same time, so
* since accidental stick movement is more likely to happen compared to accidental dpad
* presses, the dpad input is prioritized.
* Feel free to change this and recompile or open an issue to discuss this.
*
* NdP: This if-else-hell approach is chosen mindfully, to reduce input lag.
*/
if (gp->dpad != 0)
{
if (gp->dpad == 5 || (x > 250 && y < -250))
if (gp->dpad == 5)
{
gpio_put(RIGHT_BTN, false);
gpio_put(UP_BTN, false);
gpio_put(DOWN_BTN, true);
gpio_put(LEFT_BTN, true);

right = false;
up = false;
logi("Diagonal URX\n");
}

else if (gp->dpad == 9 || (x < -250 && y < -250))
else if (gp->dpad == 9)
{
gpio_put(RIGHT_BTN, true);
gpio_put(UP_BTN, false);
gpio_put(DOWN_BTN, true);
gpio_put(LEFT_BTN, false);

left = false;
up = false;
logi("Diagonal ULX\n");
}
else if (gp->dpad == 6 || (x > 250 && y > 250))
else if (gp->dpad == 6)
{
gpio_put(RIGHT_BTN, false);
gpio_put(UP_BTN, true);
gpio_put(DOWN_BTN, false);
gpio_put(LEFT_BTN, true);

right = false;
down = false;
logi("Diagonal DRX\n");
}

if (gp->dpad == 10 || (x < -250 && y > 250))
else if (gp->dpad == 10)
{
gpio_put(RIGHT_BTN, true);
gpio_put(UP_BTN, true);
gpio_put(DOWN_BTN, false);
gpio_put(LEFT_BTN, false);

left = false;
down = false;
logi("Diagonal DLX\n");
}
if (gp->dpad == 1 || y < -480)
else if (gp->dpad == 1)
{
gpio_put(UP_BTN, false);
gpio_put(DOWN_BTN, true);
gpio_put(LEFT_BTN, true);
gpio_put(RIGHT_BTN, true);

up = false;
down = true;
left = true;
right = true;
logi("UP\n");
}
if (gp->dpad == 2 || y > 480)
else if (gp->dpad == 2)
{
gpio_put(DOWN_BTN, false);
gpio_put(UP_BTN, true);
gpio_put(LEFT_BTN, true);
gpio_put(RIGHT_BTN, true);

down = false;
up = true;
left = true;
right = true;
logi("DOWN\n");
}
if (gp->dpad == 8 || x < (-480))
else if (gp->dpad == 8)
{
gpio_put(LEFT_BTN, false);
gpio_put(UP_BTN, true);
gpio_put(DOWN_BTN, true);
gpio_put(RIGHT_BTN, true);

left = false;
up = true;
down = true;
right = true;
logi("LEFT\n");
}
if (gp->dpad == 4 || x > 480)
else if (gp->dpad == 4)
{
gpio_put(RIGHT_BTN, false);
gpio_put(UP_BTN, true);
gpio_put(DOWN_BTN, true);
gpio_put(LEFT_BTN, true);

right = false;
up = true;
down = true;
left = true;
logi("RIGHT\n");
}
}
// IGNORE ALL BUTTONS EXCEPT RTrigger and LCRS <- (Lower Cross - X PS, B NIN, A XBX)
if (gp->buttons != 1 && (gp->buttons != 128))

else if (!(fabs(x) < DEAD_ZONE && fabs(y) < DEAD_ZONE))
{
/*
* Cool nerdy math function to nail every analog position correctly 😎
*/
double angle = atan2(y, x) * (180.0 / M_PI);

// Adjust angle to be positive
if (angle < 0)
{
angle += 360.0;
}

if (angle >= 22.5 && angle < 67.5)
{
right = false;
down = false;
logi("Down-Right\n");
}
else if (angle >= 67.5 && angle < 112.5)
{
down = false;
up = true;
left = true;
right = true;
logi("Down\n");
}
else if (angle >= 112.5 && angle < 157.5)
{
left = false;
down = false;
logi("Down-Left\n");
}
else if (angle >= 157.5 && angle < 202.5)
{
left = false;
up = true;
down = true;
right = true;
logi("Left\n");
}
else if (angle >= 202.5 && angle < 247.5)
{
left = false;
up = false;
logi("Up-Left\n");
}
else if (angle >= 247.5 && angle < 292.5)
{
up = false;
down = true;
left = true;
right = true;
logi("Up\n");
}
else if (angle >= 292.5 && angle < 337.5)
{
right = false;
up = false;
logi("Up-Right\n");
}
else
{
right = false;
up = true;
down = true;
left = true;
logi("Right\n");
}
}

// Handle button presses
if (gp->buttons == 0)
{
gpio_put(FIRE_BTN, true);
}

if (gp->buttons == 2)
{
up = false;
logi("UP\n");
}

if ((gp->buttons == 128 && gp->throttle > 100) || gp->buttons == 1)
{
gpio_put(FIRE_BTN, false);
logi("FIRE\n");
}

// Debugging
// Axis ry: control rumble
/* if ((gp->buttons & BUTTON_A) && d->report_parser.set_rumble != NULL) {
d->report_parser.set_rumble(d, 128, 128);
}
// Buttons: Control LEDs On/Off
if ((gp->buttons & BUTTON_B) && d->report_parser.set_player_leds != NULL) {
d->report_parser.set_player_leds(d, leds++ & 0x0f);
}
// Axis: control RGB color
if ((gp->buttons & BUTTON_X) && d->report_parser.set_lightbar_color != NULL) {
uint8_t r = (gp->axis_x * 256) / 512;
uint8_t g = (gp->axis_y * 256) / 512;
uint8_t b = (gp->axis_rx * 256) / 512;
d->report_parser.set_lightbar_color(d, r, g, b);
} */

// Toggle Bluetooth connections
/* if ((gp->buttons & BUTTON_SHOULDER_L) && enabled) {
logi("*** Disabling Bluetooth connections\n");
uni_bt_enable_new_connections_safe(false);
enabled = false;
}
if ((gp->buttons & BUTTON_SHOULDER_R) && !enabled) {
logi("*** Enabling Bluetooth connections\n");
uni_bt_enable_new_connections_safe(true);
enabled = true;
} */
break;
// Set GPIOs based on direction
gpio_put(UP_BTN, up);
gpio_put(DOWN_BTN, down);
gpio_put(LEFT_BTN, left);
gpio_put(RIGHT_BTN, right);
}
break;
default:
loge("Unsupported controller class: %d\n", ctl->klass);
break;
Expand All @@ -260,8 +326,8 @@ static void picontrol_on_oob_event(uni_platform_oob_event_t event, void *data)
switch (event)
{
case UNI_PLATFORM_OOB_GAMEPAD_SYSTEM_BUTTON:
// Optional: do something when "system" button gets pressed.
trigger_event_on_gamepad((uni_hid_device_t *)data);
// CHANGE CONSOLE ON SYSTEM BUTTON PRESS
update_gamepad((uni_hid_device_t *)data);
break;

case UNI_PLATFORM_OOB_BLUETOOTH_ENABLED:
Expand All @@ -278,11 +344,12 @@ static void picontrol_on_oob_event(uni_platform_oob_event_t event, void *data)
//
// Helpers
//
static void trigger_event_on_gamepad(uni_hid_device_t *d)
static void update_gamepad(uni_hid_device_t *d)
{
// if (d->report_parser.set_rumble != NULL) {
// d->report_parser.set_rumble(d, 0x80 /* value */, 15 /* duration */);
//}
if (d->report_parser.set_rumble != NULL)
{
d->report_parser.set_rumble(d, 0xF0 /* value */, 15 /* duration */);
}

if (d->report_parser.set_player_leds != NULL)
{
Expand Down

0 comments on commit 94c8908

Please sign in to comment.