Skip to content

Commit

Permalink
Implement Macro feature (#554)
Browse files Browse the repository at this point in the history
* Add macro implementation

* WIP

* Favor dedicated pin model

* Add interruptible, exclusive & wait options

* Add debounce for macro trigger

* Refactor and cleanup

* Move macro to proper addon order

* Cleanup

* Add more strings for frontend localization

* Fix frontend Macro schema and defaults

* Cleanup

* Cleanup

* Fix boolean serialization

* Fix some assignment and validation

* Fix label

* Fix another mistake in serialization

* Add missing fields in macro page defaultValues

* Fix direction pad macro combination issue

* Add tooltip on delete button

* Filter macro inputs that are empty

* Fix improper cleanup of empty macro inputs

* Revamp macro type with any button interruptibility

* Switch to microseconds & add show frame interface

* Update duration & exclusive toggle behavior

* Fix interruptibility for ON_PRESS macro type

* Fix default macro duration

* Add Macro Documentation

* Fix an issue failing to clear macro inputs

* Fix incorrectly referenced next macro time

---------

Co-authored-by: Kevin Nguyen <[email protected]>
  • Loading branch information
deeebug and InfraredAces authored Oct 8, 2023
1 parent a8ebe0e commit 170e97d
Show file tree
Hide file tree
Showing 24 changed files with 988 additions and 7 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ src/addons/reverse.cpp
src/addons/turbo.cpp
src/addons/slider_socd.cpp
src/addons/wiiext.cpp
src/addons/input_macro.cpp
src/addons/snes_input.cpp
src/gamepad/GamepadDebouncer.cpp
src/gamepad/GamepadDescriptors.cpp
Expand Down
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
**Web Configurator**

- [Web Configurator](web-configurator "GP2040-CE | Web Configurator")
- [Macros](macros "GP2040-CE | Macros")
- [Add-Ons](add-ons "GP2040-CE | Web Configurator - Add-ons")
- [Analog](add-ons/analog.md)
- [BOOTSEL Button](add-ons/bootsel-button.md)
Expand Down
Binary file added docs/assets/images/gpc-macros-input-line.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/images/gpc-macros.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions docs/macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Macro Settings

Purpose: Macros are a series or combination of gamepad inputs triggered with a single button or a combination of buttons.

![GP2040-CE Configurator - Macros](../assets/images/gpc-macros.png)

## Macro Options

`Macro Button Pin` - The GPIO Pin used to activate macros in combination with other inputs when `Uses Button` is enabled and set.

### Label

This is the name of the macro and is optional.

### Activate

- `Off` - The macro is not available for use.
- `On` - The macro is available for use when triggered by either the GPIO pin or the combination set in [`Uses Button`](#uses-button).

### Interruptible

- `Off` - The macro cannot be stopped and will execute all lines until the macro is completed.
- `On` - Any input will stop the current ongoing macro or, if the input is another macro, the interrupting macro trigger will start executing instead.

### Exclusive

- `Off` - Additional inputs from user will be sent as the macro continues to execute, resulting in a blend of macro and user inputs.
- `On` - Filters only the macro inputs through and excludes any additional user gamepad inputs

?> This option is **only** available when `Interruptible` is enabled.

### Show Frames

- `Off` - The duration in the macro input line editor will appear in milliseconds (ms).
- `On` - The duration in the macro input line editor will appear as a number of frames, assuming 60 frames per second.

### Uses Button

- `Off` - This macro is assigned to a GPIO pin on the board and when pressed, the macro will be triggered.
- `On` - This macro is assigned to a button combination of `Macro Button Pin + Input` where the input can be any of the standard gamepad inputs.

### Trigger Mode

This describes is how the GPIO pin or the combination set in [`Uses Button`](#uses-button) triggers and repeats the macro.

- Press - Full press of button triggers the macro once
- Hold Repeat - Holding button to repeatedly triggers macro
- Toggle - Full press of button causes the macro to repeatedly trigger, another full press of the button will stop the macro from repeatedly triggering.

## Macro Input Line Editor

Each individual macro has a maximum of 50 lines where each input line has a maximum of 18 gamepad inputs (using all available gamepad inputs).

![GP2040-CE Configurator - Macro Input Line](../assets/images/gpc-macros-input-line.png)

Each input line is composed of the following elements from left to right.

`Input Line Duration` ms `Inputs` | `Post Input Wait Duration` ms

- Input Line Duration - The duration that the inputs are held for. (Maximum 4,294,967ms or 268,435 frames)
- Inputs - The inputs to be held during the execution of the input line.
- Post Input Wait Duration - The duration in-between when that input line finishes executing and when the next line will start executing. (Maximum 4,294,967ms or 268,435 frames)

?> To delete an input line, double-click the "x" button.

## Note

- When a macro stops for any reason and are triggered. again, the macro starts again from the beginning.
47 changes: 47 additions & 0 deletions headers/addons/input_macro.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef _InputMacro_H
#define _InputMacro_H

#include "gpaddon.h"

#include "GamepadEnums.h"

#ifndef INPUT_MACRO_ENABLED
#define INPUT_MACRO_ENABLED 0
#endif

#ifndef INPUT_MACRO_PIN
#define INPUT_MACRO_PIN -1
#endif

#define MAX_MACRO_INPUT_LIMIT 50
#define MAX_MACRO_LIMIT 6
#define INPUT_HOLD_US 16666

// Input Macro Module Name
#define InputMacroName "Input Macro"

class InputMacro : public GPAddon {
public:
virtual bool available(); // GPAddon available
virtual void setup(); // Analog Setup
virtual void process() {}; // Analog Process
virtual void preprocess();
virtual std::string name() { return InputMacroName; }
private:
int macroPosition = -1;
bool isMacroRunning = false;
bool isMacroTriggerHeld = false;

uint64_t macroStartTime = 0;
uint64_t macroTriggerDebounceStartTime = 0;

int macroInputPosition = 0;
bool macroInputPressed = false;
uint32_t macroInputHoldTime = INPUT_HOLD_US;
bool prevMacroInputPressed = false;

MacroOptions inputMacroOptions;
void reset();
};

#endif // _InputMacro_H_
2 changes: 0 additions & 2 deletions headers/storagemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
#include "gamepad.h"

#include "config.pb.h"

#include <atomic>

#include "pico/critical_section.h"

#define SI Storage::getInstance()
Expand Down
5 changes: 3 additions & 2 deletions lib/FlashPROM/src/FlashPROM.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
#include <hardware/flash.h>
#include <hardware/timer.h>

#define EEPROM_SIZE_BYTES 0x2000 // Reserve 8k of flash memory (ensure this value is divisible by 256)
#define EEPROM_ADDRESS_START _u(0x101FE000) // The arduino-pico EEPROM lib starts here, so we'll do the same
#define EEPROM_SIZE_BYTES 0x4000 // Reserve 16k of flash memory (ensure this value is divisible by 256)
#define EEPROM_ADDRESS_START _u(0x101FC000) // The arduino-pico EEPROM lib starts here, so we'll do the same

// Warning: If the write wait is too long it can stall other processes
#define EEPROM_WRITE_WAIT 50 // Amount of time in ms to wait before blocking core1 and committing to flash

Expand Down
29 changes: 29 additions & 0 deletions proto/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,34 @@ message FocusModeOptions
optional bool buttonLockEnabled = 6;
}

message MacroInput
{
optional uint32 buttonMask = 1;
optional uint32 duration = 2;
optional uint32 waitDuration = 3 [default = 0];
}

message Macro
{
optional MacroType macroType = 1;
optional string macroLabel = 2 [(nanopb).max_length = 256];
repeated MacroInput macroInputs = 3 [(nanopb).max_count = 50];
optional bool enabled = 4;
optional bool useMacroTriggerButton = 5;
optional int32 macroTriggerPin = 6 [default = -1];
optional uint32 macroTriggerButton = 7;
optional bool exclusive = 8 [default = true];
optional bool interruptible = 9 [default = true];
optional bool showFrames = 10 [default = false];
}

message MacroOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
repeated Macro macroList = 3 [(nanopb).max_count = 6];
}

message AddonOptions
{
optional BootselButtonOptions bootselButtonOptions = 1;
Expand All @@ -609,6 +637,7 @@ message AddonOptions
optional KeyboardHostOptions keyboardHostOptions = 17;
optional TiltOptions tiltOptions = 18;
optional PSPassthroughOptions psPassthroughOptions = 19;
optional MacroOptions macroOptions = 20;
}

message Config
Expand Down
9 changes: 9 additions & 0 deletions proto/enums.proto
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,12 @@ enum PS4ControllerType
PS4_CONTROLLER = 0;
PS4_ARCADESTICK = 7;
}

enum MacroType
{
option (nanopb_enumopt).long_names = false;

ON_PRESS = 1;
ON_HOLD_REPEAT = 2;
ON_TOGGLE = 3;
};
Loading

0 comments on commit 170e97d

Please sign in to comment.