From 23399f56ea8550f81ccc9299228c85743158783b Mon Sep 17 00:00:00 2001 From: NickGuyver Date: Fri, 9 Jun 2023 17:46:15 -0700 Subject: [PATCH 1/4] Add forced circularity option and minor fix to analog.cpp Add an analog configuration option to force perfect circularity on analog joystick. This video does a good job of showing why it should be an option - (https://www.youtube.com/watch?v=1P1mItHTKJw) Nest the deadzone if statements inside the statements where their respective axis is validated. --- headers/addons/analog.h | 5 +++++ proto/config.proto | 1 + src/addons/analog.cpp | 25 +++++++++++++++++++++---- src/config_legacy.cpp | 2 ++ src/config_utils.cpp | 1 + src/configs/webconfig.cpp | 3 +++ www/server/app.js | 1 + www/src/Pages/AddonsConfigPage.js | 13 +++++++++++++ 8 files changed, 47 insertions(+), 4 deletions(-) diff --git a/headers/addons/analog.h b/headers/addons/analog.h index 84d18027b..99489df51 100644 --- a/headers/addons/analog.h +++ b/headers/addons/analog.h @@ -19,6 +19,10 @@ #define ANALOG_ADC_VRY -1 #endif +#ifndef FORCED_CIRCULARITY_ENABLED +#define FORCED_CIRCULARITY_ENABLED 0 +#endif + // Analog Module Name #define AnalogName "Analog" @@ -32,6 +36,7 @@ class AnalogInput : public GPAddon { private: uint8_t analogAdcPinX; uint8_t analogAdcPinY; + bool forced_circularity; }; #endif // _Analog_H_ \ No newline at end of file diff --git a/proto/config.proto b/proto/config.proto index 86b56f101..45d11f588 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -237,6 +237,7 @@ message AnalogOptions optional int32 analogAdcPinX = 2; optional int32 analogAdcPinY = 3; + optional bool forced_circularity = 4; } message TurboOptions diff --git a/src/addons/analog.cpp b/src/addons/analog.cpp index 8097f5fab..ec9f3c84e 100644 --- a/src/addons/analog.cpp +++ b/src/addons/analog.cpp @@ -5,6 +5,8 @@ #include "hardware/adc.h" +#include + #define ADC_MAX ((1 << 12) - 1) #define ANALOG_CENTER 0.5f // 0.5f is center #define ANALOG_DEADZONE 0.05f // move to config (future release) @@ -17,6 +19,7 @@ void AnalogInput::setup() { const AnalogOptions& options = Storage::getInstance().getAddonOptions().analogOptions; analogAdcPinX = options.analogAdcPinX; analogAdcPinY = options.analogAdcPinY; + forced_circularity = options.forced_circularity; // Make sure GPIO is high-impedance, no pullups etc if ( isValidPin(analogAdcPinX) ) @@ -33,15 +36,29 @@ void AnalogInput::process() if ( isValidPin(analogAdcPinX) ) { adc_select_input(analogAdcPinX-26); // ANALOG-X adc_x = ((float)adc_read())/ADC_MAX; + + if ( abs(adc_x - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones + adc_x = ANALOG_CENTER; } if ( isValidPin(analogAdcPinY) ) { adc_select_input(analogAdcPinY-26); // ANALOG-Y adc_y = ((float)adc_read())/ADC_MAX; + + if ( abs(adc_y - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones + adc_y = ANALOG_CENTER; + } + + // Alter coordinates to force perfect circularity + if (forced_circularity){ + float adc_x_magnitude = adc_x-(ANALOG_CENTER); + float adc_y_magnitude = adc_y-(ANALOG_CENTER); + float adc_magnitude = sqrt((adc_x_magnitude * adc_x_magnitude) + (adc_y_magnitude * adc_y_magnitude)); + + if ( adc_magnitude > ANALOG_CENTER) { + adc_x = ((adc_x_magnitude / adc_magnitude) * ANALOG_CENTER + ANALOG_CENTER); + adc_y = ((adc_y_magnitude / adc_magnitude) * ANALOG_CENTER + ANALOG_CENTER); + } } - if ( abs(adc_x - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones - adc_x = ANALOG_CENTER; - if ( abs(adc_y - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones - adc_y = ANALOG_CENTER; // Convert to 16-bit value gamepad->state.lx = (uint16_t)(65535.0f*adc_x); diff --git a/src/config_legacy.cpp b/src/config_legacy.cpp index 5831bb090..059d9d57a 100644 --- a/src/config_legacy.cpp +++ b/src/config_legacy.cpp @@ -242,6 +242,7 @@ namespace ConfigLegacy OnBoardLedMode onBoardLedMode; uint8_t analogAdcPinX; uint8_t analogAdcPinY; + uint8_t forced_circularity; uint16_t bootselButtonMap; uint8_t extraButtonPin; uint32_t extraButtonMap; @@ -929,6 +930,7 @@ bool ConfigUtils::fromLegacyStorage(Config& config) SET_PROPERTY(analogOptions, enabled, legacyAddonOptions.AnalogInputEnabled); SET_PROPERTY(analogOptions, analogAdcPinX, bytePinToIntPin(legacyAddonOptions.analogAdcPinX)); SET_PROPERTY(analogOptions, analogAdcPinY, bytePinToIntPin(legacyAddonOptions.analogAdcPinY)); + SET_PROPERTY(analogOptions, forced_circularity, bytePinToIntPin(legacyAddonOptions.forced_circularity)); BootselButtonOptions& bootselButtonOptions = config.addonOptions.bootselButtonOptions; config.addonOptions.has_bootselButtonOptions = true; diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 60cf33153..7450a0c06 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -279,6 +279,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, enabled, !!ANALOG_INPUT_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, analogAdcPinX, ANALOG_ADC_VRX); INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, analogAdcPinY, ANALOG_ADC_VRY); + INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, enabled, !!FORCED_CIRCULARITY_ENABLED); // addonOptions.turboOptions INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, enabled, !!TURBO_ENABLED); diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 57e93ae7a..cb8c44532 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -844,6 +844,7 @@ std::string setAddonOptions() AnalogOptions& analogOptions = Storage::getInstance().getAddonOptions().analogOptions; docToPin(analogOptions.analogAdcPinX, doc, "analogAdcPinX"); docToPin(analogOptions.analogAdcPinY, doc, "analogAdcPinY"); + docToValue(analogOptions.forced_circularity, doc, "forced_circularity"); docToValue(analogOptions.enabled, doc, "AnalogInputEnabled"); BootselButtonOptions& bootselButtonOptions = Storage::getInstance().getAddonOptions().bootselButtonOptions; @@ -1053,6 +1054,7 @@ std::string getAddonOptions() const AnalogOptions& analogOptions = Storage::getInstance().getAddonOptions().analogOptions; writeDoc(doc, "analogAdcPinX", cleanPin(analogOptions.analogAdcPinX)); writeDoc(doc, "analogAdcPinY", cleanPin(analogOptions.analogAdcPinY)); + writeDoc(doc, "forced_circularity", analogOptions.forced_circularity); writeDoc(doc, "AnalogInputEnabled", analogOptions.enabled); const BootselButtonOptions& bootselButtonOptions = Storage::getInstance().getAddonOptions().bootselButtonOptions; @@ -1269,6 +1271,7 @@ static const std::pair handlerFuncs[] = { "/api/getFirmwareVersion", getFirmwareVersion }, { "/api/getMemoryReport", getMemoryReport }, { "/api/getUsedPins", getUsedPins }, + { "/api/getConfig", getConfig }, #if !defined(NDEBUG) { "/api/echo", echo }, #endif diff --git a/www/server/app.js b/www/server/app.js index d8fedc508..4a6e0c00f 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -197,6 +197,7 @@ app.get("/api/getAddonsOptions", (req, res) => { dualDirCombineMode: 0, analogAdcPinX: -1, analogAdcPinY: -1, + forced_circularity: 0, bootselButtonMap: 0, buzzerPin: -1, buzzerVolume: 100, diff --git a/www/src/Pages/AddonsConfigPage.js b/www/src/Pages/AddonsConfigPage.js index a6718252a..e5d88eecf 100644 --- a/www/src/Pages/AddonsConfigPage.js +++ b/www/src/Pages/AddonsConfigPage.js @@ -263,6 +263,7 @@ const schema = yup.object().shape({ AnalogInputEnabled: yup.number().required().label('Analog Input Enabled'), analogAdcPinX: yup.number().label('Analog Stick Pin X').validatePinWhenValue('AnalogInputEnabled'), analogAdcPinY: yup.number().label('Analog Stick Pin Y').validatePinWhenValue('AnalogInputEnabled'), + forced_circularity: yup.number().label('Force Circularity').validateRangeWhenValue('AnalogInputEnabled', 0, 1), BoardLedAddonEnabled: yup.number().required().label('Board LED Add-On Enabled'), onBoardLedMode: yup.number().label('On-Board LED Mode').validateSelectionWhenValue('BoardLedAddonEnabled', ON_BOARD_LED_MODES), @@ -357,6 +358,7 @@ const defaultValues = { dualDirCombineMode: 0, analogAdcPinX : -1, analogAdcPinY : -1, + forced_circularity : 0, bootselButtonMap: 0, buzzerPin: -1, buzzerVolume: 100, @@ -478,6 +480,8 @@ const sanitizeData = (values) => { values.analogAdcPinX = parseInt(values.analogAdcPinX); if (!!values.analogAdcPinY) values.analogAdcPinY = parseInt(values.analogAdcPinY); + if (!!values.forced_circularity) + values.forced_circularity = parseInt(values.forced_circularity); if (!!values.bootselButtonMap) values.bootselButtonMap = parseInt(values.bootselButtonMap); if (!!values.buzzerPin) @@ -718,6 +722,15 @@ export default function AddonsConfigPage() { > {ANALOG_PIN_OPTIONS} + {handleCheckbox("forced_circularity", values); handleChange(e);}} + /> Date: Mon, 12 Jun 2023 14:40:35 -0700 Subject: [PATCH 2/4] add analog deadzone to webconfig, fix shotcount Add webconfig option to adjust deadzone for analog joystick Fix minimum value for adjustable shotcount on webpage to match validated range --- headers/addons/analog.h | 5 +++++ proto/config.proto | 1 + src/addons/analog.cpp | 13 +++++++++---- src/config_legacy.cpp | 2 ++ src/config_utils.cpp | 1 + src/configs/webconfig.cpp | 2 ++ www/server/app.js | 1 + www/src/Pages/AddonsConfigPage.js | 20 ++++++++++++++++++-- 8 files changed, 39 insertions(+), 6 deletions(-) diff --git a/headers/addons/analog.h b/headers/addons/analog.h index 99489df51..cae73061e 100644 --- a/headers/addons/analog.h +++ b/headers/addons/analog.h @@ -23,6 +23,10 @@ #define FORCED_CIRCULARITY_ENABLED 0 #endif +#ifndef DEFAULT_ANALOG_DEADZONE +#define DEFAULT_ANALOG_DEADZONE 5 +#endif // DEFAULT_SHOT_PER_SEC + // Analog Module Name #define AnalogName "Analog" @@ -37,6 +41,7 @@ class AnalogInput : public GPAddon { uint8_t analogAdcPinX; uint8_t analogAdcPinY; bool forced_circularity; + uint8_t analog_deadzone; }; #endif // _Analog_H_ \ No newline at end of file diff --git a/proto/config.proto b/proto/config.proto index 6ec8bc9f4..cfe6babc7 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -238,6 +238,7 @@ message AnalogOptions optional int32 analogAdcPinX = 2; optional int32 analogAdcPinY = 3; optional bool forced_circularity = 4; + optional uint32 analog_deadzone = 5; } message TurboOptions diff --git a/src/addons/analog.cpp b/src/addons/analog.cpp index ec9f3c84e..2d96553f5 100644 --- a/src/addons/analog.cpp +++ b/src/addons/analog.cpp @@ -9,7 +9,6 @@ #define ADC_MAX ((1 << 12) - 1) #define ANALOG_CENTER 0.5f // 0.5f is center -#define ANALOG_DEADZONE 0.05f // move to config (future release) bool AnalogInput::available() { return Storage::getInstance().getAddonOptions().analogOptions.enabled; @@ -19,7 +18,8 @@ void AnalogInput::setup() { const AnalogOptions& options = Storage::getInstance().getAddonOptions().analogOptions; analogAdcPinX = options.analogAdcPinX; analogAdcPinY = options.analogAdcPinY; - forced_circularity = options.forced_circularity; + forced_circularity = options.forced_circularity; + analog_deadzone = options.analog_deadzone; // Make sure GPIO is high-impedance, no pullups etc if ( isValidPin(analogAdcPinX) ) @@ -33,20 +33,25 @@ void AnalogInput::process() Gamepad * gamepad = Storage::getInstance().GetGamepad(); float adc_x = ANALOG_CENTER; float adc_y = ANALOG_CENTER; + float deadzone = analog_deadzone / 200.0f; + if ( isValidPin(analogAdcPinX) ) { adc_select_input(analogAdcPinX-26); // ANALOG-X adc_x = ((float)adc_read())/ADC_MAX; - if ( abs(adc_x - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones + if ( abs(adc_x - ANALOG_CENTER) < deadzone ) // deadzones adc_x = ANALOG_CENTER; } if ( isValidPin(analogAdcPinY) ) { adc_select_input(analogAdcPinY-26); // ANALOG-Y adc_y = ((float)adc_read())/ADC_MAX; - if ( abs(adc_y - ANALOG_CENTER) < ANALOG_DEADZONE ) // deadzones + if ( abs(adc_y - ANALOG_CENTER) < deadzone ) // deadzones adc_y = ANALOG_CENTER; } + + printf("deadzone - %f\n", deadzone); + printf("analog_deadzone - %f\n", analog_deadzone); // Alter coordinates to force perfect circularity if (forced_circularity){ diff --git a/src/config_legacy.cpp b/src/config_legacy.cpp index 059d9d57a..839602bff 100644 --- a/src/config_legacy.cpp +++ b/src/config_legacy.cpp @@ -243,6 +243,7 @@ namespace ConfigLegacy uint8_t analogAdcPinX; uint8_t analogAdcPinY; uint8_t forced_circularity; + uint8_t analog_deadzone; uint16_t bootselButtonMap; uint8_t extraButtonPin; uint32_t extraButtonMap; @@ -931,6 +932,7 @@ bool ConfigUtils::fromLegacyStorage(Config& config) SET_PROPERTY(analogOptions, analogAdcPinX, bytePinToIntPin(legacyAddonOptions.analogAdcPinX)); SET_PROPERTY(analogOptions, analogAdcPinY, bytePinToIntPin(legacyAddonOptions.analogAdcPinY)); SET_PROPERTY(analogOptions, forced_circularity, bytePinToIntPin(legacyAddonOptions.forced_circularity)); + SET_PROPERTY(analogOptions, analog_deadzone, legacyAddonOptions.analog_deadzone); BootselButtonOptions& bootselButtonOptions = config.addonOptions.bootselButtonOptions; config.addonOptions.has_bootselButtonOptions = true; diff --git a/src/config_utils.cpp b/src/config_utils.cpp index e0d3154e5..d0af8dd79 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -280,6 +280,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, analogAdcPinX, ANALOG_ADC_VRX); INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, analogAdcPinY, ANALOG_ADC_VRY); INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, enabled, !!FORCED_CIRCULARITY_ENABLED); + INIT_UNSET_PROPERTY(config.addonOptions.analogOptions, analog_deadzone, DEFAULT_ANALOG_DEADZONE); // addonOptions.turboOptions INIT_UNSET_PROPERTY(config.addonOptions.turboOptions, enabled, !!TURBO_ENABLED); diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index cb8c44532..460ed21ac 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -845,6 +845,7 @@ std::string setAddonOptions() docToPin(analogOptions.analogAdcPinX, doc, "analogAdcPinX"); docToPin(analogOptions.analogAdcPinY, doc, "analogAdcPinY"); docToValue(analogOptions.forced_circularity, doc, "forced_circularity"); + docToValue(analogOptions.analog_deadzone, doc, "analog_deadzone"); docToValue(analogOptions.enabled, doc, "AnalogInputEnabled"); BootselButtonOptions& bootselButtonOptions = Storage::getInstance().getAddonOptions().bootselButtonOptions; @@ -1055,6 +1056,7 @@ std::string getAddonOptions() writeDoc(doc, "analogAdcPinX", cleanPin(analogOptions.analogAdcPinX)); writeDoc(doc, "analogAdcPinY", cleanPin(analogOptions.analogAdcPinY)); writeDoc(doc, "forced_circularity", analogOptions.forced_circularity); + writeDoc(doc, "analog_deadzone", analogOptions.analog_deadzone); writeDoc(doc, "AnalogInputEnabled", analogOptions.enabled); const BootselButtonOptions& bootselButtonOptions = Storage::getInstance().getAddonOptions().bootselButtonOptions; diff --git a/www/server/app.js b/www/server/app.js index 4a6e0c00f..4b17f461d 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -198,6 +198,7 @@ app.get("/api/getAddonsOptions", (req, res) => { analogAdcPinX: -1, analogAdcPinY: -1, forced_circularity: 0, + analog_deadzone: 5, bootselButtonMap: 0, buzzerPin: -1, buzzerVolume: 100, diff --git a/www/src/Pages/AddonsConfigPage.js b/www/src/Pages/AddonsConfigPage.js index e5d88eecf..15b7fce77 100644 --- a/www/src/Pages/AddonsConfigPage.js +++ b/www/src/Pages/AddonsConfigPage.js @@ -263,7 +263,8 @@ const schema = yup.object().shape({ AnalogInputEnabled: yup.number().required().label('Analog Input Enabled'), analogAdcPinX: yup.number().label('Analog Stick Pin X').validatePinWhenValue('AnalogInputEnabled'), analogAdcPinY: yup.number().label('Analog Stick Pin Y').validatePinWhenValue('AnalogInputEnabled'), - forced_circularity: yup.number().label('Force Circularity').validateRangeWhenValue('AnalogInputEnabled', 0, 1), + forced_circularity: yup.number().label('Force Circularity').validateRangeWhenValue('AnalogInputEnabled', 0, 1), + analog_deadzone: yup.number().label('Deadzone Size (%)').validateRangeWhenValue('AnalogInputEnabled', 0, 100), BoardLedAddonEnabled: yup.number().required().label('Board LED Add-On Enabled'), onBoardLedMode: yup.number().label('On-Board LED Mode').validateSelectionWhenValue('BoardLedAddonEnabled', ON_BOARD_LED_MODES), @@ -359,6 +360,7 @@ const defaultValues = { analogAdcPinX : -1, analogAdcPinY : -1, forced_circularity : 0, + analog_deadzone: 5, bootselButtonMap: 0, buzzerPin: -1, buzzerVolume: 100, @@ -482,6 +484,8 @@ const sanitizeData = (values) => { values.analogAdcPinY = parseInt(values.analogAdcPinY); if (!!values.forced_circularity) values.forced_circularity = parseInt(values.forced_circularity); + if (!!values.analog_deadzone) + values.analog_deadzone = parseInt(values.analog_deadzone); if (!!values.bootselButtonMap) values.bootselButtonMap = parseInt(values.bootselButtonMap); if (!!values.buzzerPin) @@ -731,6 +735,18 @@ export default function AddonsConfigPage() { checked={Boolean(values.forced_circularity)} onChange={(e) => {handleCheckbox("forced_circularity", values); handleChange(e);}} /> + Date: Tue, 13 Jun 2023 09:35:18 -0700 Subject: [PATCH 3/4] remove junk Forgot to remove print debugs and copy/paste --- headers/addons/analog.h | 2 +- src/addons/analog.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/headers/addons/analog.h b/headers/addons/analog.h index cae73061e..0264be525 100644 --- a/headers/addons/analog.h +++ b/headers/addons/analog.h @@ -25,7 +25,7 @@ #ifndef DEFAULT_ANALOG_DEADZONE #define DEFAULT_ANALOG_DEADZONE 5 -#endif // DEFAULT_SHOT_PER_SEC +#endif // Analog Module Name #define AnalogName "Analog" diff --git a/src/addons/analog.cpp b/src/addons/analog.cpp index 2d96553f5..59f93f7ef 100644 --- a/src/addons/analog.cpp +++ b/src/addons/analog.cpp @@ -49,9 +49,6 @@ void AnalogInput::process() if ( abs(adc_y - ANALOG_CENTER) < deadzone ) // deadzones adc_y = ANALOG_CENTER; } - - printf("deadzone - %f\n", deadzone); - printf("analog_deadzone - %f\n", analog_deadzone); // Alter coordinates to force perfect circularity if (forced_circularity){ From 6894a91c7dd09dae15ab47853d7b69e2dd5842b9 Mon Sep 17 00:00:00 2001 From: NickGuyver Date: Mon, 19 Jun 2023 19:47:03 -0700 Subject: [PATCH 4/4] Update AddonsConfigPage.jsx --- www/src/Pages/AddonsConfigPage.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/www/src/Pages/AddonsConfigPage.jsx b/www/src/Pages/AddonsConfigPage.jsx index cfbec1d49..c31239108 100644 --- a/www/src/Pages/AddonsConfigPage.jsx +++ b/www/src/Pages/AddonsConfigPage.jsx @@ -370,7 +370,6 @@ const defaultValues = { analogAdcPinY : -1, forced_circularity : 0, analog_deadzone: 5, - analogAdcPinY : -1, bootselButtonMap: 0, buzzerPin: -1, buzzerVolume: 100,