Compare commits

...

16 Commits
v0.9.0 ... main

Author SHA1 Message Date
572718ccf3
changelog bump
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2025-02-10 18:30:32 -06:00
3d4d826566
update the reserved storage size and board config location for 32 KB
this change is in GP2040-CE main and bumping it up is necessary for the
concatenate invocation to put the board config at the right location

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2025-02-10 18:23:39 -06:00
697c30406d
changelog for v0.11.0
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-12-18 08:46:14 -06:00
7fbccb6cde
provide better feedback when we have exhausted all config_pb2 options
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-12-18 08:46:14 -06:00
c81f4cd139
properly test protobuf structure packaging options
this should all be tested now:
1. invoking against precompiled _pb2.py files provided by user
2. invoking against .proto files provided by user which must be compiled
3. invoking with a special option to use shipped (by us) .proto files
   which must be compiled
4. erroring because none of the above occurred

this took some reorganization, but this should finally give me stability
in using this in GP2040-CE's build process

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-12-18 08:46:14 -06:00
c9c73c979a
tweak the debugging output of getting protobuf modules
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-12-18 08:46:14 -06:00
2334b8c630
version bumps, which necessitated a small update to tests
for some reason the GUI pilot server for testing doesn't go to the end
of the input field for edits, so the things that backspaced over old
values need an extra 'end' keypress now. I didn't look into why this is,
because it's fine in the actual GUI regardless

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-12-18 08:46:05 -06:00
98052312d9
release notes for v0.10.0
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-30 10:27:56 -05:00
783a0f08dd
extend tox coverage to Python 3.12
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-30 09:58:45 -05:00
f058727f34
requirements version bumps
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-30 09:58:45 -05:00
d4c4bbde96
update the repository for v0.7.10
note that the google protobuf project does not recommend shipping
generated _pb2.py files, so that functionality has been removed from the
project. this also partially undoes the previous commit since using the
provided .proto files is less of an issue and also the default now, so
maybe don't spam the console as much

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-30 09:58:07 -05:00
18f4f45bb5
log the exception causing to revert to the precompiled fallback
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-20 13:00:17 -05:00
733b49676c
allow for saving the board dump in .uf2 format
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-09-16 11:33:37 -05:00
dace99b9e0
fix comparison of configs in Save As test
newer config structures will convert old configs to the new fields'
defaults, meaning the after won't be the same as the before once there's
a proto change not present in the original file (such as with this proto
bump for 0.7.9), so just do a more rudimentary compare

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-06-05 11:39:17 -05:00
a64ae256a0
update protobuf snapshot files for GP2040-CE v0.7.9
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-06-05 11:38:52 -05:00
975afbbd6c
add twine to dev dependencies, for packaging to pypi
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-05-21 13:13:34 -05:00
31 changed files with 1043 additions and 978 deletions

@ -19,7 +19,7 @@ Copyright: © 2023 Brian S. Stephan <bss@incorporeal.org>
License: GPL-3.0-or-later
# Test data (GP2040-CE-derived)
Files: tests/test-files/pb2-files/* tests/test-files/proto-files/*
Files: tests/test-files/proto-files/*
Copyright: (c) 2024 OpenStickCommunity (gp2040-ce.info)
License: MIT

@ -3,6 +3,46 @@
Included is a summary of changes to the project. For full details, especially on behind-the-scenes code changes and
development tools, see the commit history.
## v0.11.1
### Miscellaneous
* The storage size and subsequent tests have been updated to expect a 32 KB config section (rather than the previous 16
KB).
## v0.11.0
### Improvements
* The usage of provided GP2040-CE config Protobuf files must be explicitly specified via the `-S` flag. This is in order
to not accidentally fall back to them and be confused by the results. The net effect is that in most situations, users
will have to provide either `-P PATH` or `-S`.
* The testing of the above fallbacks covers the options far better than before now.
### Miscellaneous
* Version bumps, which brought about a couple updates to the tests.
## v0.10.0
### Features
* The board dump can now be made in UF2 format.
* Kind of a retrograde feature --- precompiled Python files are no longer shipped with the project, as that is not
recommended by upstream protobuf. The version bumps have potentially fixed the Windows issues that led to the
precompiled Python files (rather than just the protobuf snapshots) being shipped in the first place, so we'll stop
shipping them for now.
### Improvements
* The protobuf snapshot files have been updated for GP2040-CE v0.7.10.
### Miscellaneous
* The TUI "Save As" test was checking old vs. new outputs, which wouldn't make any sense once the latest output fills in
new defaults, etc. not present in the origin file, which is pretty normal, so the test was simplified.
* twine was added in the dev dependencies, and version bumps done for both requirements files.
## v0.9.0
### Features

@ -13,9 +13,9 @@ over USB.
All tools take `-P PATH` flag(s) in order to import Protobuf files (either precompiled Python files or raw .proto files)
if you have them locally, in order to work with the latest (or development) version of the configuration. That said,
this tool also includes a precompiled fallback version of the config structure if you cannot supply these files. Be
aware, however, that they are a point in time snapshot, and may lag the real format in undesirable ways. Supply the
latest Protobuf files if you can.
this tool also includes a copy of the config files if you cannot supply these files, and will attempt to compile those
as a fallback. Be aware, however, that they are a point in time snapshot, and may lag the real format in undesirable
ways. Supply the latest Protobuf files if you can.
An example of this invocation is:
@ -232,11 +232,11 @@ The latest update of the configuration snapshot is from **v0.7.8**.
### Dumping the GP2040-CE board with picotool
Some of these tools require a dump of your GP2040-CE board, either the storage section or the whole board, depending on
the context. The storage section of a GP2040-CE board is a reserved 16 KB starting at `0x101FC000`. To dump your board's
storage with picotool:
the context. The user config storage section of a GP2040-CE board is a reserved 32 KB starting at `0x101F8000`. To dump
your board's storage with picotool:
```
% picotool save -r 101FC000 10200000 memory.bin
% picotool save -r 101F8000 10200000 memory.bin
```
And to dump your whole board:

@ -40,6 +40,8 @@ core_parser.add_argument('-d', '--debug', action='store_true', help="enable debu
core_parser.add_argument('-P', '--proto-files-path', type=pathlib.Path, default=list(), action='append',
help="path to .proto files to read, including dependencies; you will likely need "
"to supply this twice, once for GP2040-CE's .proto files and once for nanopb's")
core_parser.add_argument('-S', '--use-shipped-fallback', action='store_true',
help="utilize shipped (potentially stale) .proto files because you can't supply your own")
args, _ = core_parser.parse_known_args()
for path in args.proto_files_path:
sys.path.append(os.path.abspath(os.path.expanduser(path)))
@ -50,20 +52,27 @@ else:
handler.setLevel(logging.WARNING)
def get_config_pb2():
def get_config_pb2(with_fallback: bool = args.use_shipped_fallback):
"""Retrieve prebuilt _pb2 file or attempt to compile it live."""
# try to just import a precompiled module if we have been given it in our path
# (perhaps someone already compiled it for us for whatever reason)
try:
logger.debug("Trying precompiled protobuf modules...")
return importlib.import_module('config_pb2')
except ModuleNotFoundError:
# no found precompiled config, try to compile the proto files in realtime
# because it's possible someone put them on the path
try:
logger.info("Invoking gRPC tool to compile config.proto...")
logger.debug("No precompiled protobuf modules found, invoking gRPC tool to compile config.proto...")
return grpc.protos('config.proto')
except (ModuleNotFoundError, TypeError):
# (TypeError could be the windows bug https://github.com/protocolbuffers/protobuf/issues/14345)
# that failed, import a precompiled snapshot (may be lagging what's in GP2040-CE)
if not with_fallback:
logger.exception("no viable set of protobuf modules could be found, please use -P or -S!")
raise RuntimeError("no viable set of protobuf modules could be found, please use -P or -S!")
# that failed, import the snapshot (may be lagging what's in GP2040-CE)
logger.warning("using the fallback .proto files! please supply your files with -P if you can!")
sys.path.append(os.path.join(pathlib.Path(__file__).parent.resolve(), 'proto_snapshot'))
return importlib.import_module('config_pb2')
logger.debug("Invoking gRPC tool again to compile shipped config.proto...")
return grpc.protos('config.proto')

@ -338,7 +338,11 @@ def dump_gp2040ce():
args, _ = parser.parse_known_args()
content, _, _ = get_gp2040ce_from_usb()
with open(args.binary_filename, 'wb') as out_file:
out_file.write(content)
if args.binary_filename[-4:] == '.uf2':
# we must pad to storage start in order for the UF2 write addresses to make sense
out_file.write(storage.convert_binary_to_uf2([(0, content)]))
else:
out_file.write(content)
def summarize_gp2040ce():

@ -1,9 +0,0 @@
"""COPIED OUTPUT OF `protoc foo.proto --python_out .`.
The .proto files here have been copied from https://github.com/OpenStickCommunity/GP2040-CE and
are a point in time import of the GP2040-CE firmware's configuration structure. THEY MAY BE OUT
OF DATE. If you are a developer, you should really use the `-P` flags to import your local copy
of the .proto files.
"""
GP2040CE_SNAPSHOT_VERSION = 'v0.7.7'

@ -28,6 +28,7 @@ message GamepadOptions
optional InputModeAuthType ps4AuthType = 21;
optional InputModeAuthType ps5AuthType = 22;
optional InputModeAuthType xinputAuthType = 23;
optional PS4ControllerIDMode ps4ControllerIDMode = 24;
}
message KeyboardMapping
@ -50,6 +51,21 @@ message KeyboardMapping
optional uint32 keyButtonR3 = 16;
optional uint32 keyButtonA1 = 17;
optional uint32 keyButtonA2 = 18;
optional uint32 keyButtonA3 = 19;
optional uint32 keyButtonA4 = 20;
optional uint32 keyButtonE1 = 21;
optional uint32 keyButtonE2 = 22;
optional uint32 keyButtonE3 = 23;
optional uint32 keyButtonE4 = 24;
optional uint32 keyButtonE5 = 25;
optional uint32 keyButtonE6 = 26;
optional uint32 keyButtonE7 = 27;
optional uint32 keyButtonE8 = 28;
optional uint32 keyButtonE9 = 29;
optional uint32 keyButtonE10 = 30;
optional uint32 keyButtonE11 = 31;
optional uint32 keyButtonE12 = 32;
}
message HotkeyEntry
@ -168,11 +184,16 @@ message PinMappings
message GpioMappingInfo
{
optional GpioAction action = 1;
optional GpioDirection direction = 2;
optional uint32 customDpadMask = 3;
optional uint32 customButtonMask = 4;
}
message GpioMappings
{
repeated GpioMappingInfo pins = 1 [(nanopb).max_count = 30];
optional string profileLabel = 2 [(nanopb).max_length = 16];
optional bool enabled = 3 [default = false];
}
@ -203,25 +224,25 @@ message DisplayOptions
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cAddress = 5 [deprecated = true];
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
optional ButtonLayout buttonLayout = 7;
optional ButtonLayoutRight buttonLayoutRight = 8;
optional ButtonLayoutCustomOptions buttonLayoutCustomOptions = 9;
optional SplashMode splashMode = 10;
optional SplashChoice splashChoice = 11;
optional int32 splashDuration = 12;
optional bytes splashImage = 13 [(nanopb).max_size = 1024];
optional int32 size = 14;
optional int32 flip = 15;
optional bool invert = 16;
optional int32 displaySaverTimeout = 17;
optional bool turnOffWhenSuspended = 18;
}
@ -234,7 +255,7 @@ message LEDOptions
optional uint32 ledsPerButton = 4;
optional uint32 brightnessMaximum = 5;
optional uint32 brightnessSteps = 6;
optional int32 indexUp = 7;
optional int32 indexDown = 8;
optional int32 indexLeft = 9;
@ -253,7 +274,7 @@ message LEDOptions
optional int32 indexR3 = 22;
optional int32 indexA1 = 23;
optional int32 indexA2 = 24;
optional PLEDType pledType = 25;
optional int32 pledPin1 = 26;
optional int32 pledPin2 = 27;
@ -279,7 +300,7 @@ message AnimationOptions_Proto
optional int32 chaseCycleTime = 5;
optional int32 rainbowCycleTime = 6;
optional uint32 themeIndex = 7;
optional bool hasCustomTheme = 8;
optional uint32 customThemeUp = 9;
optional uint32 customThemeDown = 10;
@ -317,7 +338,7 @@ message AnimationOptions_Proto
optional uint32 customThemeR3Pressed = 42;
optional uint32 customThemeA1Pressed = 43;
optional uint32 customThemeA2Pressed = 44;
optional uint32 buttonPressColorCooldownTimeInMs = 45;
optional uint32 buttonPressColorCooldownTimeInMs = 45;
}
message BootselButtonOptions
@ -335,11 +356,11 @@ message OnBoardLedOptions
message AnalogOptions
{
optional bool enabled = 1;
optional int32 analogAdc1PinX = 2;
optional int32 analogAdc1PinY = 3;
optional bool forced_circularity = 4;
optional uint32 analog_deadzone = 5;
optional uint32 inner_deadzone = 5;
optional int32 analogAdc2PinX = 6;
optional int32 analogAdc2PinY = 7;
optional DpadMode analogAdc1Mode = 8;
@ -347,17 +368,21 @@ message AnalogOptions
optional InvertMode analogAdc1Invert = 10;
optional InvertMode analogAdc2Invert = 11;
optional bool auto_calibrate = 12;
optional uint32 outer_deadzone = 13;
optional bool analog_smoothing = 14;
optional float smoothing_factor = 15;
optional uint32 analog_error = 16;
}
message TurboOptions
{
optional bool enabled = 1;
optional int32 deprecatedButtonPin = 2 [deprecated = true];
optional int32 ledPin = 3;
optional uint32 shotCount = 4;
optional int32 shmupDialPin = 5;
optional bool shmupModeEnabled = 6;
optional uint32 shmupAlwaysOn1 = 7;
optional uint32 shmupAlwaysOn2 = 8;
@ -377,21 +402,21 @@ message TurboOptions
message SliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinSliderOne = 2 [deprecated = true];
optional int32 deprecatedPinSliderTwo = 3 [deprecated = true];
optional DpadMode deprecatedModeOne = 4 [deprecated = true];
optional DpadMode deprecatedModeTwo = 5 [deprecated = true];
optional DpadMode modeDefault = 6;
optional DpadMode deprecatedModeDefault = 6;
}
message SOCDSliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinOne = 2 [deprecated = true];
optional int32 deprecatedPinTwo = 3 [deprecated = true];
optional SOCDMode modeDefault = 4;
optional SOCDMode deprecatedModeOne = 5 [deprecated = true];
optional SOCDMode deprecatedModeTwo = 6 [deprecated = true];
@ -400,10 +425,10 @@ message SOCDSliderOptions
message ReverseOptions
{
optional bool enabled = 1;
optional int32 buttonPin = 2;
optional int32 ledPin = 3;
optional uint32 actionUp = 4;
optional uint32 actionDown = 5;
optional uint32 actionLeft = 6;
@ -414,10 +439,10 @@ message AnalogADS1219Options
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cAddress = 5 [deprecated = true];
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
}
@ -435,12 +460,12 @@ message AnalogADS1256Options
message DualDirectionalOptions
{
optional bool enabled = 1;
optional int32 deprecatedUpPin = 2 [deprecated = true];
optional int32 deprecatedDownPin = 3 [deprecated = true];
optional int32 deprecatedLeftPin = 4 [deprecated = true];
optional int32 deprecatedRightPin = 5 [deprecated = true];
optional DpadMode dpadMode = 6;
optional DualDirectionalCombinationMode combineMode = 7;
optional bool fourWayMode = 8;
@ -463,7 +488,7 @@ message TiltOptions
optional int32 tiltRightAnalogRightPin = 12;
optional SOCDMode tiltSOCDMode = 13;
optional int32 factorTilt1LeftX = 14;
optional int32 factorTilt1LeftY = 15;
optional int32 factorTilt1RightX = 16;
@ -477,7 +502,7 @@ message TiltOptions
message BuzzerOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 volume = 3;
optional int32 enablePin = 4;
@ -486,7 +511,7 @@ message BuzzerOptions
message ExtraButtonOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 buttonMap = 3;
}
@ -539,7 +564,7 @@ message WiiOptions
optional AnalogAxis x = 1;
optional AnalogAxis y = 2;
}
message NunchukOptions
{
optional int32 buttonC = 1;
@ -570,7 +595,7 @@ message WiiOptions
optional AnalogAxis rightTrigger = 19;
}
message TaikoOptions
message TaikoOptions
{
optional int32 buttonKatLeft = 1;
optional int32 buttonKatRight = 2;
@ -636,7 +661,7 @@ message WiiOptions
}
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 deprecatedI2cSpeed = 5 [deprecated = true];
@ -658,6 +683,9 @@ message KeyboardHostOptions
optional int32 deprecatedPinDplus = 2 [deprecated = true];
optional KeyboardMapping mapping = 3;
optional int32 deprecatedPin5V = 4 [deprecated = true];
optional uint32 mouseLeft = 5;
optional uint32 mouseMiddle = 6;
optional uint32 mouseRight = 7;
}
message FocusModeOptions
@ -727,13 +755,46 @@ message RotaryOptions
optional RotaryPinOptions encoderTwo = 3;
}
message PCF8575Options
{
optional bool enabled = 1;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
repeated GpioMappingInfo pins = 3 [(nanopb).max_count = 16];
}
message DRV8833RumbleOptions
{
optional bool enabled = 1;
optional int32 leftMotorPin = 2;
optional int32 rightMotorPin = 3;
optional int32 motorSleepPin = 4;
optional uint32 pwmFrequency = 5;
optional float dutyMin = 6;
optional float dutyMax = 7;
}
message ReactiveLEDInfo
{
optional int32 pin = 1;
optional GpioAction action = 2;
optional ReactiveLEDMode modeDown = 3;
optional ReactiveLEDMode modeUp = 4;
}
message ReactiveLEDOptions
{
optional bool enabled = 1;
repeated ReactiveLEDInfo leds = 2 [(nanopb).max_count = 10];
}
message AddonOptions
{
optional BootselButtonOptions bootselButtonOptions = 1;
optional OnBoardLedOptions onBoardLedOptions = 2;
optional AnalogOptions analogOptions = 3;
optional TurboOptions turboOptions = 4;
optional SliderOptions sliderOptions = 5;
optional SliderOptions deprecatedSliderOptions = 5;
optional ReverseOptions reverseOptions = 6;
optional AnalogADS1219Options analogADS1219Options = 7;
optional DualDirectionalOptions dualDirectionalOptions = 8;
@ -753,6 +814,9 @@ message AddonOptions
optional XBOnePassthroughOptions xbonePassthroughOptions = 22 [deprecated = true];
optional AnalogADS1256Options analogADS1256Options = 23;
optional RotaryOptions rotaryOptions = 24;
optional PCF8575Options pcf8575Options = 25;
optional DRV8833RumbleOptions drv8833RumbleOptions = 26;
optional ReactiveLEDOptions reactiveLEDOptions = 27;
}
message MigrationHistory
@ -760,12 +824,13 @@ message MigrationHistory
optional bool hotkeysMigrated = 1 [default = false];
optional bool gpioMappingsMigrated = 2 [default = false];
optional bool buttonProfilesMigrated = 3 [default = false];
optional bool profileEnabledFlagsMigrated = 4 [default = false];
}
message Config
{
optional string boardVersion = 1 [(nanopb).max_length = 31];
optional GamepadOptions gamepadOptions = 2;
optional HotkeyOptions hotkeyOptions = 3;
optional PinMappings deprecatedPinMappings = 4 [deprecated = true];
@ -776,7 +841,7 @@ message Config
optional AddonOptions addonOptions = 9;
optional ForcedSetupOptions forcedSetupOptions = 10;
optional ProfileOptions profileOptions = 11;
optional string boardConfig = 12 [(nanopb).max_length = 63];
optional GpioMappings gpioMappings = 13;
optional MigrationHistory migrations = 14;

File diff suppressed because one or more lines are too long

@ -39,6 +39,7 @@ enum ButtonLayout
BUTTON_LAYOUT_6GAWD_A = 30;
BUTTON_LAYOUT_6GAWD_ALLBUTTON_A = 31;
BUTTON_LAYOUT_6GAWD_ALLBUTTONPLUS_A = 32;
BUTTON_LAYOUT_STICKLESS_R16 = 33;
}
enum ButtonLayoutRight
@ -82,6 +83,7 @@ enum ButtonLayoutRight
BUTTON_LAYOUT_6GAWD_B = 34;
BUTTON_LAYOUT_6GAWD_ALLBUTTON_B = 35;
BUTTON_LAYOUT_6GAWD_ALLBUTTONPLUS_B = 36;
BUTTON_LAYOUT_STICKLESS_R16B = 37;
}
enum SplashMode
@ -109,7 +111,7 @@ enum SplashChoice
enum OnBoardLedMode
{
option (nanopb_enumopt).long_names = false;
ON_BOARD_LED_MODE_OFF = 0;
ON_BOARD_LED_MODE_MODE_INDICATOR = 1;
ON_BOARD_LED_MODE_INPUT_TEST = 2;
@ -122,7 +124,7 @@ enum InputMode
INPUT_MODE_XINPUT = 0;
INPUT_MODE_SWITCH = 1;
INPUT_MODE_HID = 2;
INPUT_MODE_PS3 = 2;
INPUT_MODE_KEYBOARD = 3;
INPUT_MODE_PS4 = 4;
INPUT_MODE_XBONE = 5;
@ -134,6 +136,7 @@ enum InputMode
INPUT_MODE_PSCLASSIC = 11;
INPUT_MODE_XBOXORIGINAL = 12;
INPUT_MODE_PS5 = 13;
INPUT_MODE_GENERIC = 14;
INPUT_MODE_CONFIG = 255;
}
@ -225,6 +228,29 @@ enum GpioAction
BUTTON_PRESS_MACRO_4 = 37;
BUTTON_PRESS_MACRO_5 = 38;
BUTTON_PRESS_MACRO_6 = 39;
CUSTOM_BUTTON_COMBO = 40;
BUTTON_PRESS_A3 = 41;
BUTTON_PRESS_A4 = 42;
BUTTON_PRESS_E1 = 43;
BUTTON_PRESS_E2 = 44;
BUTTON_PRESS_E3 = 45;
BUTTON_PRESS_E4 = 46;
BUTTON_PRESS_E5 = 47;
BUTTON_PRESS_E6 = 48;
BUTTON_PRESS_E7 = 49;
BUTTON_PRESS_E8 = 50;
BUTTON_PRESS_E9 = 51;
BUTTON_PRESS_E10 = 52;
BUTTON_PRESS_E11 = 53;
BUTTON_PRESS_E12 = 54;
}
enum GpioDirection
{
option (nanopb_enumopt).long_names = false;
GPIO_DIRECTION_INPUT = 0;
GPIO_DIRECTION_OUTPUT = 1;
}
enum GamepadHotkey
@ -266,6 +292,14 @@ enum GamepadHotkey
HOTKEY_S2_BUTTON = 32;
HOTKEY_A1_BUTTON = 33;
HOTKEY_A2_BUTTON = 34;
HOTKEY_NEXT_PROFILE = 35;
HOTKEY_A3_BUTTON = 36;
HOTKEY_A4_BUTTON = 37;
HOTKEY_DPAD_UP = 38;
HOTKEY_DPAD_DOWN = 39;
HOTKEY_DPAD_LEFT = 40;
HOTKEY_DPAD_RIGHT = 41;
HOTKEY_PREVIOUS_PROFILE = 42;
}
// This has to be kept in sync with LEDFormat in NeoPico.hpp
@ -288,7 +322,7 @@ enum ShmupMixMode
enum PLEDType
{
option (nanopb_enumopt).long_names = false;
PLED_TYPE_NONE = -1;
PLED_TYPE_PWM = 0;
PLED_TYPE_RGB = 1;
@ -297,7 +331,7 @@ enum PLEDType
enum ForcedSetupMode
{
option (nanopb_enumopt).long_names = false;
FORCED_SETUP_MODE_OFF = 0;
FORCED_SETUP_MODE_LOCK_MODE_SWITCH = 1;
FORCED_SETUP_MODE_LOCK_WEB_CONFIG = 2;
@ -317,7 +351,7 @@ enum DualDirectionalCombinationMode
enum PS4ControllerType
{
option (nanopb_enumopt).long_names = false;
PS4_CONTROLLER = 0;
PS4_ARCADESTICK = 7;
}
@ -349,7 +383,7 @@ enum GPElement
enum GPShape_Type
{
option (nanopb_enumopt).long_names = false;
GP_SHAPE_ELLIPSE = 0;
GP_SHAPE_SQUARE = 1;
GP_SHAPE_LINE = 2;
@ -371,3 +405,21 @@ enum RotaryEncoderPinMode
ENCODER_MODE_DPAD_X = 7;
ENCODER_MODE_DPAD_Y = 8;
};
enum ReactiveLEDMode
{
option (nanopb_enumopt).long_names = false;
REACTIVE_LED_STATIC_OFF = 0;
REACTIVE_LED_STATIC_ON = 1;
REACTIVE_LED_FADE_IN = 2;
REACTIVE_LED_FADE_OUT = 3;
};
enum PS4ControllerIDMode
{
option (nanopb_enumopt).long_names = false;
PS4_ID_CONSOLE = 0;
PS4_ID_EMULATION = 1;
};

File diff suppressed because one or more lines are too long

@ -1,39 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: nanopb.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xc4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK\x12\x1e\n\x0f\x64isallow_export\x18\x1e \x01(\x08:\x05\x66\x61lse*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nanopb_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(nanopb_fileopt)
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(nanopb_msgopt)
google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(nanopb_enumopt)
google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(nanopb)
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopb'
_FIELDTYPE._serialized_start=1017
_FIELDTYPE._serialized_end=1122
_INTSIZE._serialized_start=1124
_INTSIZE._serialized_end=1192
_TYPENAMEMANGLING._serialized_start=1194
_TYPENAMEMANGLING._serialized_end=1284
_DESCRIPTORSIZE._serialized_start=1286
_DESCRIPTORSIZE._serialized_end=1355
_NANOPBOPTIONS._serialized_start=51
_NANOPBOPTIONS._serialized_end=1015
# @@protoc_insertion_point(module_scope)

@ -17,10 +17,11 @@ from gp2040ce_bintools.rp2040 import get_bootsel_endpoints, read
logger = logging.getLogger(__name__)
BOARD_CONFIG_BINARY_LOCATION = 0x1F8000
STORAGE_SIZE = 32768
BOARD_CONFIG_BINARY_LOCATION = (2 * 1024 * 1024) - (STORAGE_SIZE * 2) # 0x1F0000
BOARD_CONFIG_BOOTSEL_ADDRESS = 0x10000000 + BOARD_CONFIG_BINARY_LOCATION
STORAGE_SIZE = 16384
USER_CONFIG_BINARY_LOCATION = 0x1FC000
USER_CONFIG_BINARY_LOCATION = (2 * 1024 * 1024) - STORAGE_SIZE # 0x1F8000
USER_CONFIG_BOOTSEL_ADDRESS = 0x10000000 + USER_CONFIG_BINARY_LOCATION
FOOTER_SIZE = 12
@ -425,7 +426,7 @@ def visualize():
group.add_argument('--usb', action='store_true', help="retrieve the config from a RP2040 board connected over USB "
"and in BOOTSEL mode")
group.add_argument('--filename', help=".bin file of a GP2040-CE board's storage section, bytes "
"101FC000-10200000, or of a GP2040-CE's whole board dump "
"101F8000-10200000, or of a GP2040-CE's whole board dump "
"if --whole-board is specified")
args, _ = parser.parse_known_args()

@ -31,7 +31,7 @@ classifiers = [
dev = ["bandit", "decorator", "flake8", "flake8-blind-except", "flake8-builtins", "flake8-docstrings",
"flake8-executable", "flake8-fixme", "flake8-isort", "flake8-logging-format", "flake8-mutable",
"flake8-pyproject", "mypy", "pip-tools", "pytest", "pytest-asyncio", "pytest-cov", "reuse",
"setuptools-scm", "textual-dev", "tox"]
"setuptools-scm", "textual-dev", "tox", "twine"]
[project.scripts]
concatenate = "gp2040ce_bintools.builder:concatenate"
@ -74,6 +74,10 @@ ignore_errors = true
[tool.pytest]
python_files = ["*_tests.py", "tests.py", "test_*.py"]
[tool.pytest.ini_options]
log_cli = 0
log_cli_level = "WARNING"
[tool.setuptools]
packages = [
"gp2040ce_bintools",

@ -4,13 +4,22 @@
#
# pip-compile --extra=dev --output-file=requirements/requirements-dev.txt
#
aiohttp==3.9.5
# via textual-dev
aiosignal==1.3.1
aiohappyeyeballs==2.4.4
# via aiohttp
attrs==23.2.0
aiohttp==3.11.10
# via
# aiohttp-jinja2
# textual-dev
# textual-serve
aiohttp-jinja2==1.6
# via textual-serve
aiosignal==1.3.2
# via aiohttp
bandit==1.7.8
attrs==24.3.0
# via
# aiohttp
# reuse
bandit==1.8.0
# via gp2040ce-binary-tools (pyproject.toml)
binaryornot==0.4.4
# via reuse
@ -18,32 +27,43 @@ boolean-py==4.0
# via
# license-expression
# reuse
build==1.2.1
build==1.2.2.post1
# via pip-tools
cachetools==5.3.3
cachetools==5.5.0
# via tox
certifi==2024.12.14
# via requests
cffi==1.17.1
# via cryptography
chardet==5.2.0
# via
# binaryornot
# python-debian
# tox
charset-normalizer==3.4.0
# via requests
click==8.1.7
# via
# pip-tools
# reuse
# textual-dev
colorama==0.4.6
# via tox
coverage[toml]==7.5.1
coverage[toml]==7.6.9
# via pytest-cov
cryptography==44.0.0
# via secretstorage
decorator==5.1.1
# via gp2040ce-binary-tools (pyproject.toml)
distlib==0.3.8
distlib==0.3.9
# via virtualenv
filelock==3.14.0
docutils==0.21.2
# via readme-renderer
filelock==3.16.1
# via
# tox
# virtualenv
flake8==7.0.0
flake8==7.1.1
# via
# flake8-builtins
# flake8-docstrings
@ -64,29 +84,46 @@ flake8-fixme==1.1.1
# via gp2040ce-binary-tools (pyproject.toml)
flake8-isort==6.1.1
# via gp2040ce-binary-tools (pyproject.toml)
flake8-logging-format==0.9.0
flake8-logging-format==2024.24.12
# via gp2040ce-binary-tools (pyproject.toml)
flake8-mutable==1.2.0
# via gp2040ce-binary-tools (pyproject.toml)
flake8-pyproject==1.2.3
# via gp2040ce-binary-tools (pyproject.toml)
frozenlist==1.4.1
frozenlist==1.5.0
# via
# aiohttp
# aiosignal
grpcio==1.64.0
grpcio==1.68.1
# via grpcio-tools
grpcio-tools==1.64.0
grpcio-tools==1.68.1
# via gp2040ce-binary-tools (pyproject.toml)
idna==3.7
# via yarl
idna==3.10
# via
# requests
# yarl
iniconfig==2.0.0
# via pytest
isort==5.13.2
# via flake8-isort
jaraco-classes==3.4.0
# via keyring
jaraco-context==6.0.1
# via keyring
jaraco-functools==4.1.0
# via keyring
jeepney==0.8.0
# via
# keyring
# secretstorage
jinja2==3.1.4
# via reuse
license-expression==30.3.0
# via
# aiohttp-jinja2
# reuse
# textual-serve
keyring==25.5.0
# via twine
license-expression==30.4.0
# via reuse
linkify-it-py==2.0.3
# via markdown-it-py
@ -95,106 +132,149 @@ markdown-it-py[linkify,plugins]==3.0.0
# mdit-py-plugins
# rich
# textual
markupsafe==2.1.5
markupsafe==3.0.2
# via jinja2
mccabe==0.7.0
# via flake8
mdit-py-plugins==0.4.1
mdit-py-plugins==0.4.2
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
msgpack==1.0.8
more-itertools==10.5.0
# via
# jaraco-classes
# jaraco-functools
msgpack==1.1.0
# via textual-dev
multidict==6.0.5
multidict==6.1.0
# via
# aiohttp
# yarl
mypy==1.10.0
mypy==1.13.0
# via gp2040ce-binary-tools (pyproject.toml)
mypy-extensions==1.0.0
# via mypy
packaging==24.0
nh3==0.2.20
# via readme-renderer
packaging==24.2
# via
# build
# pyproject-api
# pytest
# setuptools-scm
# tox
pbr==6.0.0
# twine
pbr==6.1.0
# via stevedore
pip-tools==7.4.1
# via gp2040ce-binary-tools (pyproject.toml)
platformdirs==4.2.2
pkginfo==1.12.0
# via twine
platformdirs==4.3.6
# via
# textual
# tox
# virtualenv
pluggy==1.5.0
# via
# pytest
# tox
protobuf==5.26.1
propcache==0.2.1
# via
# aiohttp
# yarl
protobuf==5.29.1
# via grpcio-tools
pycodestyle==2.11.1
pycodestyle==2.12.1
# via flake8
pycparser==2.22
# via cffi
pydocstyle==6.3.0
# via flake8-docstrings
pyflakes==3.2.0
# via flake8
pygments==2.18.0
# via rich
pyproject-api==1.6.1
# via
# readme-renderer
# rich
pyproject-api==1.8.0
# via tox
pyproject-hooks==1.1.0
pyproject-hooks==1.2.0
# via
# build
# pip-tools
pytest==8.2.1
pytest==8.3.4
# via
# gp2040ce-binary-tools (pyproject.toml)
# pytest-asyncio
# pytest-cov
pytest-asyncio==0.23.7
pytest-asyncio==0.25.0
# via gp2040ce-binary-tools (pyproject.toml)
pytest-cov==5.0.0
pytest-cov==6.0.0
# via gp2040ce-binary-tools (pyproject.toml)
python-debian==0.1.49
# via reuse
pyusb==1.2.1
# via gp2040ce-binary-tools (pyproject.toml)
pyyaml==6.0.1
pyyaml==6.0.2
# via bandit
reuse==3.0.2
readme-renderer==44.0
# via twine
requests==2.32.3
# via
# requests-toolbelt
# twine
requests-toolbelt==1.0.0
# via twine
reuse==5.0.2
# via gp2040ce-binary-tools (pyproject.toml)
rich==13.7.1
rfc3986==2.0.0
# via twine
rich==13.9.4
# via
# bandit
# textual
# textual-serve
# twine
secretstorage==3.3.3
# via keyring
setuptools-scm==8.1.0
# via gp2040ce-binary-tools (pyproject.toml)
snowballstemmer==2.2.0
# via pydocstyle
stevedore==5.2.0
stevedore==5.4.0
# via bandit
textual==0.62.0
textual==1.0.0
# via
# gp2040ce-binary-tools (pyproject.toml)
# textual-dev
textual-dev==1.5.1
# textual-serve
textual-dev==1.7.0
# via gp2040ce-binary-tools (pyproject.toml)
tox==4.15.0
textual-serve==1.1.1
# via textual-dev
tomlkit==0.13.2
# via reuse
tox==4.23.2
# via gp2040ce-binary-tools (pyproject.toml)
typing-extensions==4.11.0
twine==6.0.1
# via gp2040ce-binary-tools (pyproject.toml)
typing-extensions==4.12.2
# via
# mypy
# textual
# textual-dev
uc-micro-py==1.0.3
# via linkify-it-py
virtualenv==20.26.2
urllib3==2.2.3
# via
# requests
# twine
virtualenv==20.28.0
# via tox
wheel==0.43.0
wheel==0.45.1
# via pip-tools
yarl==1.9.4
yarl==1.18.3
# via aiohttp
# The following packages are considered to be unsafe in a requirements file:

@ -4,9 +4,9 @@
#
# pip-compile --output-file=requirements/requirements.txt
#
grpcio==1.64.0
grpcio==1.68.1
# via grpcio-tools
grpcio-tools==1.64.0
grpcio-tools==1.68.1
# via gp2040ce-binary-tools (pyproject.toml)
linkify-it-py==2.0.3
# via markdown-it-py
@ -15,21 +15,23 @@ markdown-it-py[linkify,plugins]==3.0.0
# mdit-py-plugins
# rich
# textual
mdit-py-plugins==0.4.1
mdit-py-plugins==0.4.2
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
protobuf==5.26.1
platformdirs==4.3.6
# via textual
protobuf==5.29.1
# via grpcio-tools
pygments==2.18.0
# via rich
pyusb==1.2.1
# via gp2040ce-binary-tools (pyproject.toml)
rich==13.7.1
rich==13.9.4
# via textual
textual==0.62.0
textual==1.0.0
# via gp2040ce-binary-tools (pyproject.toml)
typing-extensions==4.11.0
typing-extensions==4.12.2
# via textual
uc-micro-py==1.0.3
# via linkify-it-py

@ -42,7 +42,7 @@ def firmware_binary():
@pytest.fixture
def storage_dump():
"""Read in a test storage dump file (101FC000-10200000) of a GP2040-CE board."""
"""Read in a test storage dump file (101F8000-10200000) of a GP2040-CE board."""
filename = os.path.join(HERE, 'test-files', 'test-storage-area.bin')
with open(filename, 'rb') as file:
content = file.read()

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,11 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: nanopb.proto
# Protobuf Python Version: 5.27.2
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
5,
27,
2,
'',
'nanopb.proto'
)
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
@ -16,24 +27,20 @@ from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xc4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK\x12\x1e\n\x0f\x64isallow_export\x18\x1e \x01(\x08:\x05\x66\x61lse*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nanopb_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(nanopb_fileopt)
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(nanopb_msgopt)
google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(nanopb_enumopt)
google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(nanopb)
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopb'
_FIELDTYPE._serialized_start=1017
_FIELDTYPE._serialized_end=1122
_INTSIZE._serialized_start=1124
_INTSIZE._serialized_end=1192
_TYPENAMEMANGLING._serialized_start=1194
_TYPENAMEMANGLING._serialized_end=1284
_DESCRIPTORSIZE._serialized_start=1286
_DESCRIPTORSIZE._serialized_end=1355
_NANOPBOPTIONS._serialized_start=51
_NANOPBOPTIONS._serialized_end=1015
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nanopb_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopb'
_globals['_FIELDTYPE']._serialized_start=1017
_globals['_FIELDTYPE']._serialized_end=1122
_globals['_INTSIZE']._serialized_start=1124
_globals['_INTSIZE']._serialized_end=1192
_globals['_TYPENAMEMANGLING']._serialized_start=1194
_globals['_TYPENAMEMANGLING']._serialized_end=1284
_globals['_DESCRIPTORSIZE']._serialized_start=1286
_globals['_DESCRIPTORSIZE']._serialized_end=1355
_globals['_NANOPBOPTIONS']._serialized_start=51
_globals['_NANOPBOPTIONS']._serialized_end=1015
# @@protoc_insertion_point(module_scope)

@ -28,6 +28,7 @@ message GamepadOptions
optional InputModeAuthType ps4AuthType = 21;
optional InputModeAuthType ps5AuthType = 22;
optional InputModeAuthType xinputAuthType = 23;
optional PS4ControllerIDMode ps4ControllerIDMode = 24;
}
message KeyboardMapping
@ -50,6 +51,21 @@ message KeyboardMapping
optional uint32 keyButtonR3 = 16;
optional uint32 keyButtonA1 = 17;
optional uint32 keyButtonA2 = 18;
optional uint32 keyButtonA3 = 19;
optional uint32 keyButtonA4 = 20;
optional uint32 keyButtonE1 = 21;
optional uint32 keyButtonE2 = 22;
optional uint32 keyButtonE3 = 23;
optional uint32 keyButtonE4 = 24;
optional uint32 keyButtonE5 = 25;
optional uint32 keyButtonE6 = 26;
optional uint32 keyButtonE7 = 27;
optional uint32 keyButtonE8 = 28;
optional uint32 keyButtonE9 = 29;
optional uint32 keyButtonE10 = 30;
optional uint32 keyButtonE11 = 31;
optional uint32 keyButtonE12 = 32;
}
message HotkeyEntry
@ -168,11 +184,16 @@ message PinMappings
message GpioMappingInfo
{
optional GpioAction action = 1;
optional GpioDirection direction = 2;
optional uint32 customDpadMask = 3;
optional uint32 customButtonMask = 4;
}
message GpioMappings
{
repeated GpioMappingInfo pins = 1 [(nanopb).max_count = 30];
optional string profileLabel = 2 [(nanopb).max_length = 16];
optional bool enabled = 3 [default = false];
}
@ -203,25 +224,25 @@ message DisplayOptions
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cAddress = 5 [deprecated = true];
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
optional ButtonLayout buttonLayout = 7;
optional ButtonLayoutRight buttonLayoutRight = 8;
optional ButtonLayoutCustomOptions buttonLayoutCustomOptions = 9;
optional SplashMode splashMode = 10;
optional SplashChoice splashChoice = 11;
optional int32 splashDuration = 12;
optional bytes splashImage = 13 [(nanopb).max_size = 1024];
optional int32 size = 14;
optional int32 flip = 15;
optional bool invert = 16;
optional int32 displaySaverTimeout = 17;
optional bool turnOffWhenSuspended = 18;
}
@ -234,7 +255,7 @@ message LEDOptions
optional uint32 ledsPerButton = 4;
optional uint32 brightnessMaximum = 5;
optional uint32 brightnessSteps = 6;
optional int32 indexUp = 7;
optional int32 indexDown = 8;
optional int32 indexLeft = 9;
@ -253,7 +274,7 @@ message LEDOptions
optional int32 indexR3 = 22;
optional int32 indexA1 = 23;
optional int32 indexA2 = 24;
optional PLEDType pledType = 25;
optional int32 pledPin1 = 26;
optional int32 pledPin2 = 27;
@ -279,7 +300,7 @@ message AnimationOptions_Proto
optional int32 chaseCycleTime = 5;
optional int32 rainbowCycleTime = 6;
optional uint32 themeIndex = 7;
optional bool hasCustomTheme = 8;
optional uint32 customThemeUp = 9;
optional uint32 customThemeDown = 10;
@ -317,7 +338,7 @@ message AnimationOptions_Proto
optional uint32 customThemeR3Pressed = 42;
optional uint32 customThemeA1Pressed = 43;
optional uint32 customThemeA2Pressed = 44;
optional uint32 buttonPressColorCooldownTimeInMs = 45;
optional uint32 buttonPressColorCooldownTimeInMs = 45;
}
message BootselButtonOptions
@ -335,11 +356,11 @@ message OnBoardLedOptions
message AnalogOptions
{
optional bool enabled = 1;
optional int32 analogAdc1PinX = 2;
optional int32 analogAdc1PinY = 3;
optional bool forced_circularity = 4;
optional uint32 analog_deadzone = 5;
optional uint32 inner_deadzone = 5;
optional int32 analogAdc2PinX = 6;
optional int32 analogAdc2PinY = 7;
optional DpadMode analogAdc1Mode = 8;
@ -347,17 +368,21 @@ message AnalogOptions
optional InvertMode analogAdc1Invert = 10;
optional InvertMode analogAdc2Invert = 11;
optional bool auto_calibrate = 12;
optional uint32 outer_deadzone = 13;
optional bool analog_smoothing = 14;
optional float smoothing_factor = 15;
optional uint32 analog_error = 16;
}
message TurboOptions
{
optional bool enabled = 1;
optional int32 deprecatedButtonPin = 2 [deprecated = true];
optional int32 ledPin = 3;
optional uint32 shotCount = 4;
optional int32 shmupDialPin = 5;
optional bool shmupModeEnabled = 6;
optional uint32 shmupAlwaysOn1 = 7;
optional uint32 shmupAlwaysOn2 = 8;
@ -377,21 +402,21 @@ message TurboOptions
message SliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinSliderOne = 2 [deprecated = true];
optional int32 deprecatedPinSliderTwo = 3 [deprecated = true];
optional DpadMode deprecatedModeOne = 4 [deprecated = true];
optional DpadMode deprecatedModeTwo = 5 [deprecated = true];
optional DpadMode modeDefault = 6;
optional DpadMode deprecatedModeDefault = 6;
}
message SOCDSliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinOne = 2 [deprecated = true];
optional int32 deprecatedPinTwo = 3 [deprecated = true];
optional SOCDMode modeDefault = 4;
optional SOCDMode deprecatedModeOne = 5 [deprecated = true];
optional SOCDMode deprecatedModeTwo = 6 [deprecated = true];
@ -400,10 +425,10 @@ message SOCDSliderOptions
message ReverseOptions
{
optional bool enabled = 1;
optional int32 buttonPin = 2;
optional int32 ledPin = 3;
optional uint32 actionUp = 4;
optional uint32 actionDown = 5;
optional uint32 actionLeft = 6;
@ -414,10 +439,10 @@ message AnalogADS1219Options
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cAddress = 5 [deprecated = true];
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
}
@ -435,12 +460,12 @@ message AnalogADS1256Options
message DualDirectionalOptions
{
optional bool enabled = 1;
optional int32 deprecatedUpPin = 2 [deprecated = true];
optional int32 deprecatedDownPin = 3 [deprecated = true];
optional int32 deprecatedLeftPin = 4 [deprecated = true];
optional int32 deprecatedRightPin = 5 [deprecated = true];
optional DpadMode dpadMode = 6;
optional DualDirectionalCombinationMode combineMode = 7;
optional bool fourWayMode = 8;
@ -463,7 +488,7 @@ message TiltOptions
optional int32 tiltRightAnalogRightPin = 12;
optional SOCDMode tiltSOCDMode = 13;
optional int32 factorTilt1LeftX = 14;
optional int32 factorTilt1LeftY = 15;
optional int32 factorTilt1RightX = 16;
@ -477,7 +502,7 @@ message TiltOptions
message BuzzerOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 volume = 3;
optional int32 enablePin = 4;
@ -486,7 +511,7 @@ message BuzzerOptions
message ExtraButtonOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 buttonMap = 3;
}
@ -539,7 +564,7 @@ message WiiOptions
optional AnalogAxis x = 1;
optional AnalogAxis y = 2;
}
message NunchukOptions
{
optional int32 buttonC = 1;
@ -570,7 +595,7 @@ message WiiOptions
optional AnalogAxis rightTrigger = 19;
}
message TaikoOptions
message TaikoOptions
{
optional int32 buttonKatLeft = 1;
optional int32 buttonKatRight = 2;
@ -636,7 +661,7 @@ message WiiOptions
}
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 deprecatedI2cSpeed = 5 [deprecated = true];
@ -658,6 +683,9 @@ message KeyboardHostOptions
optional int32 deprecatedPinDplus = 2 [deprecated = true];
optional KeyboardMapping mapping = 3;
optional int32 deprecatedPin5V = 4 [deprecated = true];
optional uint32 mouseLeft = 5;
optional uint32 mouseMiddle = 6;
optional uint32 mouseRight = 7;
}
message FocusModeOptions
@ -727,13 +755,46 @@ message RotaryOptions
optional RotaryPinOptions encoderTwo = 3;
}
message PCF8575Options
{
optional bool enabled = 1;
optional int32 deprecatedI2cBlock = 2 [deprecated = true];
repeated GpioMappingInfo pins = 3 [(nanopb).max_count = 16];
}
message DRV8833RumbleOptions
{
optional bool enabled = 1;
optional int32 leftMotorPin = 2;
optional int32 rightMotorPin = 3;
optional int32 motorSleepPin = 4;
optional uint32 pwmFrequency = 5;
optional float dutyMin = 6;
optional float dutyMax = 7;
}
message ReactiveLEDInfo
{
optional int32 pin = 1;
optional GpioAction action = 2;
optional ReactiveLEDMode modeDown = 3;
optional ReactiveLEDMode modeUp = 4;
}
message ReactiveLEDOptions
{
optional bool enabled = 1;
repeated ReactiveLEDInfo leds = 2 [(nanopb).max_count = 10];
}
message AddonOptions
{
optional BootselButtonOptions bootselButtonOptions = 1;
optional OnBoardLedOptions onBoardLedOptions = 2;
optional AnalogOptions analogOptions = 3;
optional TurboOptions turboOptions = 4;
optional SliderOptions sliderOptions = 5;
optional SliderOptions deprecatedSliderOptions = 5;
optional ReverseOptions reverseOptions = 6;
optional AnalogADS1219Options analogADS1219Options = 7;
optional DualDirectionalOptions dualDirectionalOptions = 8;
@ -753,6 +814,9 @@ message AddonOptions
optional XBOnePassthroughOptions xbonePassthroughOptions = 22 [deprecated = true];
optional AnalogADS1256Options analogADS1256Options = 23;
optional RotaryOptions rotaryOptions = 24;
optional PCF8575Options pcf8575Options = 25;
optional DRV8833RumbleOptions drv8833RumbleOptions = 26;
optional ReactiveLEDOptions reactiveLEDOptions = 27;
}
message MigrationHistory
@ -760,12 +824,13 @@ message MigrationHistory
optional bool hotkeysMigrated = 1 [default = false];
optional bool gpioMappingsMigrated = 2 [default = false];
optional bool buttonProfilesMigrated = 3 [default = false];
optional bool profileEnabledFlagsMigrated = 4 [default = false];
}
message Config
{
optional string boardVersion = 1 [(nanopb).max_length = 31];
optional GamepadOptions gamepadOptions = 2;
optional HotkeyOptions hotkeyOptions = 3;
optional PinMappings deprecatedPinMappings = 4 [deprecated = true];
@ -776,7 +841,7 @@ message Config
optional AddonOptions addonOptions = 9;
optional ForcedSetupOptions forcedSetupOptions = 10;
optional ProfileOptions profileOptions = 11;
optional string boardConfig = 12 [(nanopb).max_length = 63];
optional GpioMappings gpioMappings = 13;
optional MigrationHistory migrations = 14;

@ -39,6 +39,7 @@ enum ButtonLayout
BUTTON_LAYOUT_6GAWD_A = 30;
BUTTON_LAYOUT_6GAWD_ALLBUTTON_A = 31;
BUTTON_LAYOUT_6GAWD_ALLBUTTONPLUS_A = 32;
BUTTON_LAYOUT_STICKLESS_R16 = 33;
}
enum ButtonLayoutRight
@ -82,6 +83,7 @@ enum ButtonLayoutRight
BUTTON_LAYOUT_6GAWD_B = 34;
BUTTON_LAYOUT_6GAWD_ALLBUTTON_B = 35;
BUTTON_LAYOUT_6GAWD_ALLBUTTONPLUS_B = 36;
BUTTON_LAYOUT_STICKLESS_R16B = 37;
}
enum SplashMode
@ -109,7 +111,7 @@ enum SplashChoice
enum OnBoardLedMode
{
option (nanopb_enumopt).long_names = false;
ON_BOARD_LED_MODE_OFF = 0;
ON_BOARD_LED_MODE_MODE_INDICATOR = 1;
ON_BOARD_LED_MODE_INPUT_TEST = 2;
@ -122,7 +124,7 @@ enum InputMode
INPUT_MODE_XINPUT = 0;
INPUT_MODE_SWITCH = 1;
INPUT_MODE_HID = 2;
INPUT_MODE_PS3 = 2;
INPUT_MODE_KEYBOARD = 3;
INPUT_MODE_PS4 = 4;
INPUT_MODE_XBONE = 5;
@ -134,6 +136,7 @@ enum InputMode
INPUT_MODE_PSCLASSIC = 11;
INPUT_MODE_XBOXORIGINAL = 12;
INPUT_MODE_PS5 = 13;
INPUT_MODE_GENERIC = 14;
INPUT_MODE_CONFIG = 255;
}
@ -225,6 +228,29 @@ enum GpioAction
BUTTON_PRESS_MACRO_4 = 37;
BUTTON_PRESS_MACRO_5 = 38;
BUTTON_PRESS_MACRO_6 = 39;
CUSTOM_BUTTON_COMBO = 40;
BUTTON_PRESS_A3 = 41;
BUTTON_PRESS_A4 = 42;
BUTTON_PRESS_E1 = 43;
BUTTON_PRESS_E2 = 44;
BUTTON_PRESS_E3 = 45;
BUTTON_PRESS_E4 = 46;
BUTTON_PRESS_E5 = 47;
BUTTON_PRESS_E6 = 48;
BUTTON_PRESS_E7 = 49;
BUTTON_PRESS_E8 = 50;
BUTTON_PRESS_E9 = 51;
BUTTON_PRESS_E10 = 52;
BUTTON_PRESS_E11 = 53;
BUTTON_PRESS_E12 = 54;
}
enum GpioDirection
{
option (nanopb_enumopt).long_names = false;
GPIO_DIRECTION_INPUT = 0;
GPIO_DIRECTION_OUTPUT = 1;
}
enum GamepadHotkey
@ -266,6 +292,14 @@ enum GamepadHotkey
HOTKEY_S2_BUTTON = 32;
HOTKEY_A1_BUTTON = 33;
HOTKEY_A2_BUTTON = 34;
HOTKEY_NEXT_PROFILE = 35;
HOTKEY_A3_BUTTON = 36;
HOTKEY_A4_BUTTON = 37;
HOTKEY_DPAD_UP = 38;
HOTKEY_DPAD_DOWN = 39;
HOTKEY_DPAD_LEFT = 40;
HOTKEY_DPAD_RIGHT = 41;
HOTKEY_PREVIOUS_PROFILE = 42;
}
// This has to be kept in sync with LEDFormat in NeoPico.hpp
@ -288,7 +322,7 @@ enum ShmupMixMode
enum PLEDType
{
option (nanopb_enumopt).long_names = false;
PLED_TYPE_NONE = -1;
PLED_TYPE_PWM = 0;
PLED_TYPE_RGB = 1;
@ -297,7 +331,7 @@ enum PLEDType
enum ForcedSetupMode
{
option (nanopb_enumopt).long_names = false;
FORCED_SETUP_MODE_OFF = 0;
FORCED_SETUP_MODE_LOCK_MODE_SWITCH = 1;
FORCED_SETUP_MODE_LOCK_WEB_CONFIG = 2;
@ -317,7 +351,7 @@ enum DualDirectionalCombinationMode
enum PS4ControllerType
{
option (nanopb_enumopt).long_names = false;
PS4_CONTROLLER = 0;
PS4_ARCADESTICK = 7;
}
@ -349,7 +383,7 @@ enum GPElement
enum GPShape_Type
{
option (nanopb_enumopt).long_names = false;
GP_SHAPE_ELLIPSE = 0;
GP_SHAPE_SQUARE = 1;
GP_SHAPE_LINE = 2;
@ -371,3 +405,21 @@ enum RotaryEncoderPinMode
ENCODER_MODE_DPAD_X = 7;
ENCODER_MODE_DPAD_Y = 8;
};
enum ReactiveLEDMode
{
option (nanopb_enumopt).long_names = false;
REACTIVE_LED_STATIC_OFF = 0;
REACTIVE_LED_STATIC_ON = 1;
REACTIVE_LED_FADE_IN = 2;
REACTIVE_LED_FADE_OUT = 3;
};
enum PS4ControllerIDMode
{
option (nanopb_enumopt).long_names = false;
PS4_ID_CONSOLE = 0;
PS4_ID_EMULATION = 1;
};

@ -1,7 +1,7 @@
{
"boardVersion": "v0.7.6-15-g71f4512",
"gamepadOptions": {
"inputMode": "INPUT_MODE_HID",
"inputMode": "INPUT_MODE_PS3",
"dpadMode": "DPAD_MODE_DIGITAL",
"socdMode": "SOCD_MODE_SECOND_INPUT_PRIORITY",
"invertXAxis": false,
@ -163,10 +163,10 @@
},
"displayOptions": {
"enabled": false,
"i2cBlock": 0,
"deprecatedI2cBlock": 0,
"deprecatedI2cSDAPin": 0,
"deprecatedI2cSCLPin": 1,
"i2cAddress": 60,
"deprecatedI2cAddress": 60,
"deprecatedI2cSpeed": 400000,
"buttonLayout": "BUTTON_LAYOUT_STICK",
"buttonLayoutRight": "BUTTON_LAYOUT_VEWLIX",
@ -297,7 +297,7 @@
"analogAdc1PinX": -1,
"analogAdc1PinY": -1,
"forcedCircularity": false,
"analogDeadzone": 5,
"innerDeadzone": 5,
"analogAdc2PinX": -1,
"analogAdc2PinY": -1,
"analogAdc1Mode": "DPAD_MODE_LEFT_ANALOG",
@ -327,13 +327,13 @@
"shmupBtnMask4": 0,
"shmupMixMode": "SHMUP_MIX_MODE_TURBO_PRIORITY"
},
"sliderOptions": {
"deprecatedSliderOptions": {
"enabled": false,
"deprecatedPinSliderOne": 0,
"deprecatedPinSliderTwo": 0,
"deprecatedModeOne": "DPAD_MODE_DIGITAL",
"deprecatedModeTwo": "DPAD_MODE_DIGITAL",
"modeDefault": "DPAD_MODE_DIGITAL"
"deprecatedModeDefault": "DPAD_MODE_DIGITAL"
},
"reverseOptions": {
"enabled": false,
@ -346,10 +346,10 @@
},
"analogADS1219Options": {
"enabled": false,
"i2cBlock": 0,
"deprecatedI2cBlock": 0,
"deprecatedI2cSDAPin": -1,
"deprecatedI2cSCLPin": -1,
"i2cAddress": 64,
"deprecatedI2cAddress": 64,
"deprecatedI2cSpeed": 400000
},
"dualDirectionalOptions": {
@ -392,7 +392,7 @@
},
"wiiOptions": {
"enabled": false,
"i2cBlock": 0,
"deprecatedI2cBlock": 0,
"deprecatedI2cSDAPin": -1,
"deprecatedI2cSCLPin": -1,
"deprecatedI2cSpeed": 400000,

Binary file not shown.

@ -32,6 +32,8 @@ def with_pb2s(test, *args, **kwargs):
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
def test_concatenate_to_file(tmp_path):
@ -55,7 +57,7 @@ def test_concatenate_board_config_to_file(tmp_path):
combined_filename=tmp_file)
with open(tmp_file, 'rb') as file:
content = file.read()
assert len(content) == (2 * 1024 * 1024) - (16 * 1024)
assert len(content) == (2 * 1024 * 1024) - (32 * 1024)
def test_concatenate_both_configs_to_file(tmp_path):
@ -178,19 +180,19 @@ def test_dont_always_find_version_string(firmware_binary):
def test_padding_firmware(firmware_binary):
"""Test that firmware is padded to the expected size."""
padded = builder.pad_binary_up_to_user_config(firmware_binary)
assert len(padded) == 2080768
assert len(padded) == 2064384
def test_padding_firmware_can_truncate():
"""Test that firmware is padded to the expected size."""
padded = builder.pad_binary_up_to_user_config(bytearray(b'\x00' * 4 * 1024 * 1024), or_truncate=True)
assert len(padded) == 2080768
assert len(padded) == 2064384
def test_padding_firmware_to_board(firmware_binary):
"""Test that firmware is padded to the expected size."""
padded = builder.pad_binary_up_to_board_config(firmware_binary)
assert len(padded) == 2080768 - (16 * 1024)
assert len(padded) == 2064384 - (32 * 1024)
def test_firmware_plus_storage_section(firmware_binary, storage_dump):
@ -224,7 +226,7 @@ def test_chunky_firmware_plus_user_config_binary(config_binary):
def test_firmware_plus_board_config_binary(firmware_binary, config_binary):
"""Test that combining firmware and board config produces a valid combined binary."""
almost_whole_board = builder.combine_firmware_and_config(firmware_binary, config_binary, None)
assert len(almost_whole_board) == (2 * 1024 * 1024) - (16 * 1024)
assert len(almost_whole_board) == (2 * 1024 * 1024) - (32 * 1024)
# if this is valid, we should be able to find the storage and footer again
storage = get_board_storage_section(almost_whole_board)
footer_size, _, _ = get_config_footer(storage)

@ -25,6 +25,8 @@ def with_pb2s(test, *args, **kwargs):
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
def test_version_flag():
@ -49,7 +51,7 @@ def test_concatenate_invocation(tmpdir):
with open(out_filename, 'rb') as out_file, open('tests/test-files/test-storage-area.bin', 'rb') as storage_file:
out = out_file.read()
storage = storage_file.read()
assert out[2080768:2097152] == storage
assert out[2064384:2097152] == storage
def test_concatenate_invocation_json(tmpdir):
@ -86,7 +88,7 @@ def test_debug_storage_dump_invocation():
'--filename', 'tests/test-files/test-storage-area.bin'],
capture_output=True, encoding='utf8')
assert 'boardVersion: "v0.7.5"' in result.stdout
assert 'length of content to look for footer in: 16384' in result.stderr
assert 'length of content to look for footer in: 32768' in result.stderr
def test_storage_dump_json_invocation():

@ -28,6 +28,8 @@ async def with_pb2s(test, *args, **kwargs):
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
@pytest.mark.asyncio
@ -109,7 +111,7 @@ async def test_simple_edit_via_input_field():
async with app.run_test() as pilot:
tree = pilot.app.query_one(Tree)
display_node = tree.root.children[5]
i2cspeed_node = display_node.children[4]
i2cspeed_node = display_node.children[6]
assert pilot.app.config.displayOptions.deprecatedI2cSpeed == 400000
tree.root.expand_all()
@ -119,7 +121,7 @@ async def test_simple_edit_via_input_field():
await pilot.wait_for_scheduled_animations()
await pilot.click('Input#field-input')
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.press('end', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#confirm-button')
assert pilot.app.config.displayOptions.deprecatedI2cSpeed == 5
@ -199,7 +201,7 @@ async def test_simple_edit_via_input_field_string():
await pilot.wait_for_scheduled_animations()
await pilot.click('Input#field-input')
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', '-', 'h', 'i')
await pilot.press('end', 'backspace', '-', 'h', 'i')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#confirm-button')
assert pilot.app.config.boardVersion == 'v0.7.-hi'
@ -229,7 +231,7 @@ async def test_add_node_to_repeated():
await pilot.wait_for_scheduled_animations()
await pilot.click('Input#field-input')
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.press('end', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#confirm-button')
@ -275,4 +277,4 @@ async def test_save_as(config_binary, tmp_path):
with open('/tmp/gptest', 'rb') as new_file:
test_config_binary = new_file.read()
test_config = get_config(test_config_binary)
assert original_config == test_config
assert original_config.boardVersion == test_config.boardVersion

@ -6,43 +6,69 @@ SPDX-License-Identifier: GPL-3.0-or-later
import os
import sys
import pytest
from decorator import decorator
from gp2040ce_bintools import get_config_pb2
HERE = os.path.dirname(os.path.abspath(__file__))
def test_get_config_pb2_compile():
"""Without any precompiled files on the path, test we can read proto files and compile them."""
# append to path as -P would
proto_path = os.path.join(HERE, 'test-files', 'proto-files')
sys.path.append(proto_path)
# let grpc tools compile the proto files on demand and give us the module
config_pb2 = get_config_pb2()
_ = config_pb2.Config()
# clean up the path and unload config_pb2
sys.path.pop()
sys.path.pop()
del sys.modules['config_pb2']
def test_get_config_pb2_exception():
"""Without any precompiled files or proto files on the path, test we DO NOT raise an exception."""
# this used to raise ModuleNotFoundError, but with our snapshot included now,
# we should always have a config to import
_ = get_config_pb2()
def test_get_config_pb2_precompile():
"""Test we can import precompiled protobuf files."""
@decorator
def with_pb2s(test, *args, **kwargs):
"""Wrap a test with precompiled pb2 files on the path."""
proto_path = os.path.join(HERE, 'test-files', 'pb2-files')
sys.path.append(proto_path)
# let grpc tools import the proto files normally
test(*args, **kwargs)
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
@decorator
def with_protos(test, *args, **kwargs):
"""Wrap a test with .proto files on the path."""
proto_path = os.path.join(HERE, 'test-files', 'proto-files')
sys.path.append(proto_path)
test(*args, **kwargs)
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
@with_pb2s
def test_get_config_pb2_precompiled():
"""With precompiled files on the path, test we can read and use them."""
# get the module from the provided files
config_pb2 = get_config_pb2()
_ = config_pb2.Config()
# clean up the path and unload config_pb2
sys.path.pop()
def test_get_config_pb2_exception():
"""Test that we fail if no config .proto files are available."""
with pytest.raises(RuntimeError):
_ = get_config_pb2()
def test_get_config_pb2_shipped_config_files():
"""Without any precompiled files or proto files on the path, test we DO NOT raise an exception."""
# use the shipped .proto files to generate the config
config_pb2 = get_config_pb2(with_fallback=True)
_ = config_pb2.Config()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
@with_protos
def test_get_config_pb2_compile():
"""Without any precompiled files on the path, test we can read proto files and compile them."""
# let grpc tools compile the proto files on demand and give us the module
config_pb2 = get_config_pb2()
_ = config_pb2.Config()

@ -27,6 +27,8 @@ def with_pb2s(test, *args, **kwargs):
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
def test_get_bootsel_endpoints():

@ -27,6 +27,8 @@ def with_pb2s(test, *args, **kwargs):
sys.path.pop()
del sys.modules['config_pb2']
del sys.modules['enums_pb2']
del sys.modules['nanopb_pb2']
def test_config_footer(storage_dump):
@ -95,7 +97,7 @@ def test_get_board_config_from_file_whole_board_dump():
"""Test that we can open a storage dump file and find its config."""
filename = os.path.join(HERE, 'test-files', 'test-whole-board-with-board-config.bin')
config = storage.get_config_from_file(filename, whole_board=True, board_config=True)
assert config.boardVersion == 'v0.7.6-15-g71f4512'
assert config.boardVersion == 'v0.7.8'
assert config.addonOptions.bootselButtonOptions.enabled is False
@ -165,7 +167,7 @@ def test_convert_binary_to_uf2_with_offsets(whole_board_with_board_config_dump):
assert len(uf2) == 4194304 # binary is 8192 256 byte chunks, UF2 is 512 b per chunk
assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic
assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set
assert uf2[524:528] == bytearray(b'\x00\xc1\x1f\x10') # address to write the second chunk
assert uf2[524:528] == bytearray(b'\x00\x81\x1f\x10') # address to write the second chunk
def test_convert_binary_to_uf2_to_binary(whole_board_with_board_config_dump):
@ -213,7 +215,7 @@ def test_read_created_uf2(tmp_path, firmware_binary, config_binary):
binary = storage.convert_uf2_to_binary(content)
# the converted binary should be aligned properly and of the right size
assert len(binary) == 2 * 1024 * 1024
assert binary[-16384-4:-16384] == storage.FOOTER_MAGIC
assert binary[-32768-4:-32768] == storage.FOOTER_MAGIC
assert binary[-4:] == storage.FOOTER_MAGIC
user_storage = storage.get_user_storage_section(binary)
footer_size, _, _ = storage.get_config_footer(user_storage)
@ -255,13 +257,13 @@ def test_serialize_modified_config_with_footer(storage_dump):
def test_pad_config_to_storage(config_binary):
"""Test that we can properly pad a config section to the correct storage section size."""
storage_section = storage.pad_config_to_storage_size(config_binary)
assert len(storage_section) == 16384
assert len(storage_section) == 32768
def test_pad_config_to_storage_raises(config_binary):
"""Test that we raise an exception if the config is bigger than the storage section."""
with pytest.raises(storage.ConfigLengthError):
_ = storage.pad_config_to_storage_size(config_binary * 5)
_ = storage.pad_config_to_storage_size(config_binary * 10)
@with_pb2s
@ -278,7 +280,7 @@ def test_get_board_config_from_usb(config_binary):
config, _, _ = storage.get_board_config_from_usb()
mock_get.assert_called_once()
mock_read.assert_called_with(mock_out, mock_in, 0x101F8000, 16384)
mock_read.assert_called_with(mock_out, mock_in, 0x101F0000, 32768)
assert config == storage.get_config(config_binary)
@ -296,7 +298,7 @@ def test_get_user_config_from_usb(config_binary):
config, _, _ = storage.get_user_config_from_usb()
mock_get.assert_called_once()
mock_read.assert_called_with(mock_out, mock_in, 0x101FC000, 16384)
mock_read.assert_called_with(mock_out, mock_in, 0x101F8000, 32768)
assert config == storage.get_config(config_binary)

@ -5,7 +5,7 @@
[tox]
isolated_build = true
envlist = begin,py39,py310,py311,coverage,bandit,lint,reuse
envlist = begin,py39,py310,py311,py312,coverage,bandit,lint,reuse
[testenv]
allow_externals = pytest, coverage
@ -33,6 +33,11 @@ commands =
commands =
pytest --cov-append --cov={envsitepackagesdir}/gp2040ce_bintools/ --cov-branch
[testenv:py312]
# run pytest with coverage
commands =
pytest --cov-append --cov={envsitepackagesdir}/gp2040ce_bintools/ --cov-branch
[testenv:coverage]
# report on coverage runs from above
skip_install = true