Skip to content

Commit

Permalink
action button pin mapping profiles
Browse files Browse the repository at this point in the history
up to three alternative pin mappings can be defined to profiles 2-4 (1
is the primary setting) which overlay their mappings on top of the
primary settings. this also defines four hotkey actions for switching
between the four profiles.

all pre-profile configuration works the same and affects the same config
objects, etc. as before. a new configuration page and config memory
section is defined for profiles 2-4 (specifically the alternative pin
mappings). profiles 2-4 default to the board mappings, as well, so users
should be fine to ignore this feature entirely if they want --- normal
function should not changed, and they shouldn't even be able to
accidentally enable this, especially not into a broken configuration
  • Loading branch information
bsstephan committed Jul 4, 2023
1 parent d20466e commit 417519e
Show file tree
Hide file tree
Showing 19 changed files with 533 additions and 3 deletions.
1 change: 1 addition & 0 deletions headers/gamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Gamepad {
Gamepad(int debounceMS = 5);

void setup();
void teardown_and_reinit(const uint32_t profileNum);
void process();
void read();
void save();
Expand Down
7 changes: 7 additions & 0 deletions headers/storagemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ class Storage {
LEDOptions& getLedOptions() { return config.ledOptions; }
AddonOptions& getAddonOptions() { return config.addonOptions; }
AnimationOptions_Proto& getAnimationOptions() { return config.animationOptions; }
ProfileOptions& getProfileOptions() { return config.profileOptions; }

bool save();

PinMappings& getProfilePinMappings();

// Perform saves that were enqueued from core1
void performEnqueuedSaves();

Expand All @@ -65,6 +68,9 @@ class Storage {
void ClearFeatureData();
uint8_t * GetFeatureData();

void setProfile(const uint32_t); // profile support for multiple mappings
void setFunctionalPinMappings(const uint32_t);

void ResetSettings(); // EEPROM Reset Feature

private:
Expand All @@ -79,6 +85,7 @@ class Storage {
critical_section_t animationOptionsCs;
uint32_t animationOptionsCrc = 0;
AnimationOptions animationOptionsToSave = {};
PinMappings* functionalPinMappings = nullptr;
};

#endif
21 changes: 21 additions & 0 deletions proto/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ message GamepadOptions
optional bool switchTpShareForDs4 = 6;
optional bool lockHotkeys = 7;
optional bool fourWayMode = 8;
optional uint32 profileNumber = 9;
}

message KeyboardMapping
Expand Down Expand Up @@ -115,6 +116,25 @@ message PinMappings
optional int32 pinButtonFn = 19;
}


message AlternativePinMappings
{
optional int32 pinButtonB1 = 1;
optional int32 pinButtonB2 = 2;
optional int32 pinButtonB3 = 3;
optional int32 pinButtonB4 = 4;
optional int32 pinButtonL1 = 5;
optional int32 pinButtonR1 = 6;
optional int32 pinButtonL2 = 7;
optional int32 pinButtonR2 = 8;
}


message ProfileOptions
{
repeated AlternativePinMappings alternativePinMappings = 1 [(nanopb).max_count = 3];
}

message DisplayOptions
{
optional bool enabled = 1;
Expand Down Expand Up @@ -458,4 +478,5 @@ message Config
optional AnimationOptions_Proto animationOptions = 8;
optional AddonOptions addonOptions = 9;
optional ForcedSetupOptions forcedSetupOptions = 10;
optional ProfileOptions profileOptions = 11;
}
4 changes: 4 additions & 0 deletions proto/enums.proto
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ enum GamepadHotkey
HOTKEY_SOCD_BYPASS = 12;
HOTKEY_TOGGLE_4_WAY_MODE = 13;
HOTKEY_TOGGLE_DDI_4_WAY_MODE = 14;
HOTKEY_LOAD_PROFILE_1 = 15;
HOTKEY_LOAD_PROFILE_2 = 16;
HOTKEY_LOAD_PROFILE_3 = 17;
HOTKEY_LOAD_PROFILE_4 = 18;
}

// This has to be kept in sync with LEDFormat in NeoPico.hpp
Expand Down
1 change: 1 addition & 0 deletions src/config_legacy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ bool ConfigUtils::fromLegacyStorage(Config& config)
}
SET_PROPERTY(gamepadOptions, invertXAxis, legacyGamepadOptions.invertXAxis);
SET_PROPERTY(gamepadOptions, invertYAxis, legacyGamepadOptions.invertYAxis);
SET_PROPERTY(gamepadOptions, profileNumber, 1);

KeyboardMapping& keyboardMapping = config.keyboardMapping;
config.has_keyboardMapping = true;
Expand Down
28 changes: 28 additions & 0 deletions src/config_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
INIT_UNSET_PROPERTY(config.gamepadOptions, switchTpShareForDs4, false);
INIT_UNSET_PROPERTY(config.gamepadOptions, lockHotkeys, DEFAULT_LOCK_HOTKEYS);
INIT_UNSET_PROPERTY(config.gamepadOptions, fourWayMode, false);
INIT_UNSET_PROPERTY(config.gamepadOptions, profileNumber, 1);

// hotkeyOptions
HotkeyOptions& hotkeyOptions = config.hotkeyOptions;
Expand Down Expand Up @@ -227,6 +228,33 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
INIT_UNSET_PROPERTY(config.displayOptions, invert, !!DISPLAY_INVERT);
INIT_UNSET_PROPERTY(config.displayOptions, displaySaverTimeout, DISPLAY_SAVER_TIMEOUT);

// alternate pin mappings
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonB1, PIN_BUTTON_B1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonB2, PIN_BUTTON_B2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonB3, PIN_BUTTON_B3);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonB4, PIN_BUTTON_B4);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonL1, PIN_BUTTON_L1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonR1, PIN_BUTTON_R1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonL2, PIN_BUTTON_L2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[0], pinButtonR2, PIN_BUTTON_R2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonB1, PIN_BUTTON_B1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonB2, PIN_BUTTON_B2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonB3, PIN_BUTTON_B3);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonB4, PIN_BUTTON_B4);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonL1, PIN_BUTTON_L1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonR1, PIN_BUTTON_R1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonL2, PIN_BUTTON_L2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[1], pinButtonR2, PIN_BUTTON_R2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonB1, PIN_BUTTON_B1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonB2, PIN_BUTTON_B2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonB3, PIN_BUTTON_B3);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonB4, PIN_BUTTON_B4);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonL1, PIN_BUTTON_L1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonR1, PIN_BUTTON_R1);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonL2, PIN_BUTTON_L2);
INIT_UNSET_PROPERTY(config.profileOptions.alternativePinMappings[2], pinButtonR2, PIN_BUTTON_R2);
config.profileOptions.alternativePinMappings_count = 3;

// ledOptions
INIT_UNSET_PROPERTY(config.ledOptions, dataPin, BOARD_LEDS_PIN);
INIT_UNSET_PROPERTY(config.ledOptions, ledFormat, static_cast<LEDFormat_Proto>(LED_FORMAT));
Expand Down
51 changes: 51 additions & 0 deletions src/configs/webconfig.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "configs/webconfig.h"
#include "config.pb.h"
#include "configs/base64.h"

#include "storagemanager.h"
Expand Down Expand Up @@ -500,6 +501,52 @@ std::string setSplashImage()
return serialize_json(doc);
}

std::string setProfileOptions()
{
DynamicJsonDocument doc = get_post_data();

ProfileOptions& profileOptions = Storage::getInstance().getProfileOptions();
JsonObject options = doc.as<JsonObject>();
JsonArray alts = options["alternativePinMappings"];
int altsIndex = 0;
for (JsonObject alt : alts) {
profileOptions.alternativePinMappings[altsIndex].pinButtonB1 = alt["B1"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonB2 = alt["B2"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonB3 = alt["B3"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonB4 = alt["B4"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonL1 = alt["L1"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonR1 = alt["R1"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonL2 = alt["L2"].as<int>();
profileOptions.alternativePinMappings[altsIndex].pinButtonR2 = alt["R2"].as<int>();
profileOptions.alternativePinMappings_count = ++altsIndex;
if (altsIndex > 2) break;
}

Storage::getInstance().save();
return serialize_json(doc);
}

std::string getProfileOptions()
{
DynamicJsonDocument doc(LWIP_HTTPD_POST_MAX_PAYLOAD_LEN);

ProfileOptions& profileOptions = Storage::getInstance().getProfileOptions();
JsonArray alts = doc.createNestedArray("alternativePinMappings");
for (int i = 0; i < profileOptions.alternativePinMappings_count; i++) {
JsonObject altMappings = alts.createNestedObject();
altMappings["B1"] = profileOptions.alternativePinMappings[i].pinButtonB1;
altMappings["B2"] = profileOptions.alternativePinMappings[i].pinButtonB2;
altMappings["B3"] = profileOptions.alternativePinMappings[i].pinButtonB3;
altMappings["B4"] = profileOptions.alternativePinMappings[i].pinButtonB4;
altMappings["L1"] = profileOptions.alternativePinMappings[i].pinButtonL1;
altMappings["R1"] = profileOptions.alternativePinMappings[i].pinButtonR1;
altMappings["L2"] = profileOptions.alternativePinMappings[i].pinButtonL2;
altMappings["R2"] = profileOptions.alternativePinMappings[i].pinButtonR2;
}

return serialize_json(doc);
}

std::string setGamepadOptions()
{
DynamicJsonDocument doc = get_post_data();
Expand All @@ -511,6 +558,7 @@ std::string setGamepadOptions()
readDoc(gamepadOptions.switchTpShareForDs4, doc, "switchTpShareForDs4");
readDoc(gamepadOptions.lockHotkeys, doc, "lockHotkeys");
readDoc(gamepadOptions.fourWayMode, doc, "fourWayMode");
readDoc(gamepadOptions.profileNumber, doc, "profileNumber");

HotkeyOptions& hotkeyOptions = Storage::getInstance().getHotkeyOptions();
save_hotkey(&hotkeyOptions.hotkey01, doc, "hotkey01");
Expand Down Expand Up @@ -545,6 +593,7 @@ std::string getGamepadOptions()
writeDoc(doc, "switchTpShareForDs4", gamepadOptions.switchTpShareForDs4 ? 1 : 0);
writeDoc(doc, "lockHotkeys", gamepadOptions.lockHotkeys ? 1 : 0);
writeDoc(doc, "fourWayMode", gamepadOptions.fourWayMode ? 1 : 0);
writeDoc(doc, "profileNumber", gamepadOptions.profileNumber);

const PinMappings& pinMappings = Storage::getInstance().getPinMappings();
writeDoc(doc, "fnButtonPin", pinMappings.pinButtonFn);
Expand Down Expand Up @@ -1385,6 +1434,7 @@ static const std::pair<const char*, HandlerFuncPtr> handlerFuncs[] =
{ "/api/setCustomTheme", setCustomTheme },
{ "/api/getCustomTheme", getCustomTheme },
{ "/api/setPinMappings", setPinMappings },
{ "/api/setProfileOptions", setProfileOptions },
{ "/api/setKeyMappings", setKeyMappings },
{ "/api/setAddonsOptions", setAddonOptions },
{ "/api/setPS4Options", setPS4Options },
Expand All @@ -1394,6 +1444,7 @@ static const std::pair<const char*, HandlerFuncPtr> handlerFuncs[] =
{ "/api/getGamepadOptions", getGamepadOptions },
{ "/api/getLedOptions", getLedOptions },
{ "/api/getPinMappings", getPinMappings },
{ "/api/getProfileOptions", getProfileOptions },
{ "/api/getKeyMappings", getKeyMappings },
{ "/api/getAddonsOptions", getAddonOptions },
{ "/api/resetSettings", resetSettings },
Expand Down
54 changes: 51 additions & 3 deletions src/gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Gamepad::Gamepad(int debounceMS) :
void Gamepad::setup()
{
// Configure pin mapping
const PinMappings& pinMappings = Storage::getInstance().getPinMappings();
const PinMappings& pinMappings = Storage::getInstance().getProfilePinMappings();

const auto convertPin = [](int32_t pin) -> uint8_t { return isValidPin(pin) ? pin : 0xff; };
mapDpadUp = new GamepadButtonMapping(convertPin(pinMappings.pinDpadUp), GAMEPAD_MASK_UP);
Expand Down Expand Up @@ -143,6 +143,31 @@ void Gamepad::setup()
}
}

/**
* @brief Undo setup().
*/
void Gamepad::teardown_and_reinit(const uint32_t profileNum)
{
const PinMappings& pinMappings = Storage::getInstance().getProfilePinMappings();
// deinitialize the GPIO pins so we don't have orphans
for (int i = 0; i < GAMEPAD_DIGITAL_INPUT_COUNT; i++)
{
if (gamepadMappings[i]->isAssigned())
{
gpio_deinit(gamepadMappings[i]->pin);
}
}
if (isValidPin(pinMappings.pinButtonFn)) {
gpio_deinit(pinMappings.pinButtonFn);
}

// set to new profile
Storage::getInstance().setProfile(profileNum);

// reinitialize pin mappings
this->setup();
}

void Gamepad::process()
{
memcpy(&rawState, &state, sizeof(GamepadState));
Expand Down Expand Up @@ -212,8 +237,7 @@ void Gamepad::process()

void Gamepad::read()
{
const PinMappings& pinMappings = Storage::getInstance().getPinMappings();

const PinMappings& pinMappings = Storage::getInstance().getProfilePinMappings();
// Need to invert since we're using pullups
uint32_t values = ~gpio_get_all();

Expand Down Expand Up @@ -327,6 +351,30 @@ void Gamepad::processHotkeyIfNewAction(GamepadHotkey action)
reqSave = true;
}
break;
case HOTKEY_LOAD_PROFILE_1:
if (action != lastAction) {
this->teardown_and_reinit(1);
reqSave = true;
}
break;
case HOTKEY_LOAD_PROFILE_2:
if (action != lastAction) {
this->teardown_and_reinit(2);
reqSave = true;
}
break;
case HOTKEY_LOAD_PROFILE_3:
if (action != lastAction) {
this->teardown_and_reinit(3);
reqSave = true;
}
break;
case HOTKEY_LOAD_PROFILE_4:
if (action != lastAction) {
this->teardown_and_reinit(4);
reqSave = true;
}
break;
}

// only save if we did something different (except NONE because NONE doesn't get here)
Expand Down
30 changes: 30 additions & 0 deletions src/storagemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "AnimationStorage.hpp"
#include "Effects/StaticColor.hpp"
#include "FlashPROM.h"
#include "config.pb.h"
#include "hardware/watchdog.h"
#include "Animation.hpp"
#include "CRC32.h"
Expand Down Expand Up @@ -132,6 +133,35 @@ void Storage::ResetSettings()
watchdog_reboot(0, SRAM_END, 2000);
}

PinMappings& Storage::getProfilePinMappings() {
if (functionalPinMappings == nullptr) {
functionalPinMappings = (PinMappings*)malloc(sizeof(PinMappings));
setFunctionalPinMappings(config.gamepadOptions.profileNumber);
}
return *functionalPinMappings;
}

void Storage::setProfile(const uint32_t profileNum)
{
setFunctionalPinMappings(profileNum);
}

void Storage::setFunctionalPinMappings(const uint32_t profileNum)
{
memcpy(functionalPinMappings, &config.pinMappings, sizeof(PinMappings));
if (profileNum < 2 || profileNum > 4) return;

AlternativePinMappings alts = this->config.profileOptions.alternativePinMappings[profileNum-2];
if (isValidPin(alts.pinButtonB1)) functionalPinMappings->pinButtonB1 = alts.pinButtonB1;
if (isValidPin(alts.pinButtonB2)) functionalPinMappings->pinButtonB2 = alts.pinButtonB2;
if (isValidPin(alts.pinButtonB3)) functionalPinMappings->pinButtonB3 = alts.pinButtonB3;
if (isValidPin(alts.pinButtonB4)) functionalPinMappings->pinButtonB4 = alts.pinButtonB4;
if (isValidPin(alts.pinButtonL1)) functionalPinMappings->pinButtonL1 = alts.pinButtonL1;
if (isValidPin(alts.pinButtonR1)) functionalPinMappings->pinButtonR1 = alts.pinButtonR1;
if (isValidPin(alts.pinButtonL2)) functionalPinMappings->pinButtonL2 = alts.pinButtonL2;
if (isValidPin(alts.pinButtonR2)) functionalPinMappings->pinButtonR2 = alts.pinButtonR2;
}

void Storage::SetConfigMode(bool mode) { // hack for config mode
CONFIG_MODE = mode;
previewDisplayOptions = config.displayOptions;
Expand Down
Loading

0 comments on commit 417519e

Please sign in to comment.