diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e08a92..5add778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,55 @@ All notable changes to this project will be documented in this file. The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to the [UHK Versioning](VERSIONING.md) conventions. +## [8.5.3] - 2018-10-20 + +Device Protocol: 4.5.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Re-enable the I2C watchdog of the left keyboard half which was accidentally disabled starting from firmware 8.4.3. This should fix the freezes of the left keyboard half. + +## [8.5.2] - 2018-10-06 + +Device Protocol: 4.5.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Don't suppress keys upon keymap change. + +## [8.5.1] - 2018-10-04 + +Device Protocol: 4.5.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Reset UsbReportUpdateSemaphore if it gets stuck for 100ms. This should fix occasional freezes. + +## [8.5.0] - 2018-10-04 + +Device Protocol: 4.**5.0** | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Send primary role modifiers consistently. +- Only allow layer switcher keys to deactivate toggled layers. +- Deactivate secondary roles when switching keymaps. +- Use the correct scancode so that commas are outputted for macros. +- Move the pointer not by 1 but by 5 pixels when testing the USB stack to make the pointer easier to see. +- Expose UsbReportUpdateSemaphore via UsbCommand_{Get,Set}Variable() `DEVICEPROTOCOL:MINOR` +- Extract CurrentTime and remove Timer_{Get,Set}CurrentTime() + +## [8.4.5] - 2018-08-21 + +Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Suppress pressed keys when the layer or keymap changes. + +## [8.4.4] - 2018-08-14 + +Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Don't wake the host if a key is held down through the beginning of sleep. +- Ensure that secondary roles are triggered consistently. + +## [8.4.3] - 2018-08-12 + +Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 + +- Compensate "double tap to lock layer" timeouts for the timer fix to make them as long as before 8.3.3 + ## [8.4.2] - 2018-08-02 Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 @@ -32,6 +81,7 @@ Device Protocol: 4.**4.0** | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardw Device Protocol: 4.3.1 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 - Implement the macro engine. +- Fix the timer which makes it tick twice as fast as before. - Fix the nondeterministic bug that made USB hang. - Restore the Windows related commits of firmware 8.3.1 because the USB hang bug has been fixed. - Restore debouncing to 100ms until it gets really fixed. diff --git a/ISSUE_TEMPLATE b/ISSUE_TEMPLATE new file mode 100644 index 0000000..4487bcf --- /dev/null +++ b/ISSUE_TEMPLATE @@ -0,0 +1,8 @@ +Before submitting a new issue, make sure to do the following: + +1. If you're using Karabiner Elements on your Mac, close it! +2. Install the latest Agent: + https://github.com/UltimateHackingKeyboard/agent/releases/latest +3. Use Agent to update to the latest firmware: + https://github.com/UltimateHackingKeyboard/firmware/releases/latest +4. Try to reproduce the issue, and only report it if it still persists. diff --git a/README.md b/README.md index 67c6e78..2a0138c 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,15 @@ If you're one of the brave few who wants to hack the firmware then read on. `git clone --recursive git@github.com:UltimateHackingKeyboard/firmware.git` -2. Download and install MCUXpresso IDE for [Linux](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/mcuxpressoide-10.1.1_606.x86_64.deb.bin), [Mac](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/MCUXpressoIDE_10.1.1_606.pkg), or [Windows](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/MCUXpressoIDE_10.1.1_606.exe). +2. Download and install MCUXpresso IDE for [Linux](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/mcuxpressoide-10.2.1_795.x86_64.deb.bin), [Mac](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/MCUXpressoIDE_10.2.1_795.pkg), or [Windows](https://storage.googleapis.com/ugl-static/mcuxpresso-ide/MCUXpressoIDE_10.2.1_795.exe). 3. In the IDE, import the project by invoking *File -> Import -> General -> Existing Projects into Workspace*, select the *left* or *right* directory depending on the desired firmware, then click on the *Finish* button. -## Building and flashing the firmware +4. In order to be able to flash the firmware via USB from the IDE, you must build [Agent](https://github.com/UltimateHackingKeyboard/agent) which is Git submodule of the this repo and located in the `lib/agent` directory. -For the left keyboard half, make sure to power it via the right keyboard half (which must be powered via USB). Also connect the left keyboard half to your SEGGER J-Link USB debug probe (which must also be connected via USB). Then in KDS, click on *Run -> Run Configurations*, select *GDB SEGGER J-Link Debugging -> uhk60-left_release_jlink*, and click on the *Debug* button. +5. Finally, in the IDE, click on *Run -> External Tools -> External Tools Configurations*, then select a release firmware to be flashed such as *uhk60-right_release_kboot*, and click on the *Run* button. -For the right keyboard half, flash [the bootloader](https://github.com/UltimateHackingKeyboard/bootloader) first. - -At this point, you can flash the right firmware via USB from KDS. To achieve this, you must build [Agent](https://github.com/UltimateHackingKeyboard/agent) that is Git submodule of the this repo and located in the `lib/agent` directory. Then in KDS, click on *Run -> Run Configurations*, select *C/C++ Application -> uhk60-right_release_kboot*, and click on the *Run* button. - -From this point on, you can upgrade the firmwares of both halves via USB by using the uhk60-left_release_kboot and uhk60-right_release_kboot run configurations. Alternatively, you can use your SEGGER J-Link probe. +Going forward, it's easier to flash the firmware of your choice by using the downwards toolbar icon which is located rightwards of the *green play + toolbox icon*. ## Contributing diff --git a/left/src/key_scanner.c b/left/src/key_scanner.c index 5c46040..6de9efc 100644 --- a/left/src/key_scanner.c +++ b/left/src/key_scanner.c @@ -5,9 +5,7 @@ void KEY_SCANNER_HANDLER(void) { KeyMatrix_ScanRow(&keyMatrix); -#ifdef I2C_WATCHDOG RunWatchdog(); -#endif LPTMR_ClearStatusFlags(KEY_SCANNER_LPTMR_BASEADDR, kLPTMR_TimerCompareFlag); } diff --git a/lib/agent b/lib/agent index 67d42f6..a4e3696 160000 --- a/lib/agent +++ b/lib/agent @@ -1 +1 @@ -Subproject commit 67d42f666c0008921875ac5cf05ba730da269f0f +Subproject commit a4e3696078216bc787b682e3323d89a35a517a81 diff --git a/right/src/layer.c b/right/src/layer.c index 9ad9541..0d99520 100644 --- a/right/src/layer.c +++ b/right/src/layer.c @@ -15,7 +15,7 @@ void updateLayerStates(void) for (uint8_t slotId=0; slotIdcurrent) { + if (keyState->current && !keyState->suppressed) { key_action_t action = CurrentKeymap[LayerId_Base][slotId][keyId]; if (action.type == KeyActionType_SwitchLayer) { if (action.switchLayer.mode != SwitchLayerMode_Toggle) { diff --git a/right/src/macros.c b/right/src/macros.c index 97df053..b30bad8 100644 --- a/right/src/macros.c +++ b/right/src/macros.c @@ -70,7 +70,7 @@ uint8_t characterToScancode(char character) return HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN; case ',': case '<': - return HID_KEYBOARD_SC_KEYPAD_LESS_THAN_SIGN; + return HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN; case '/': case '\?': return HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK; @@ -286,7 +286,7 @@ bool processDelayAction(void) inDelay = false; } } else { - Timer_SetCurrentTime(&delayStart); + delayStart = CurrentTime; inDelay = true; } return inDelay; diff --git a/right/src/timer.c b/right/src/timer.c index 3ddf4b9..5256401 100644 --- a/right/src/timer.c +++ b/right/src/timer.c @@ -2,12 +2,13 @@ #include "timer.h" #include "peripherals/test_led.h" +volatile uint32_t CurrentTime; static uint32_t timerClockFrequency; -static volatile uint32_t currentTime, delayLength; +static volatile uint32_t delayLength; void PIT_TIMER_HANDLER(void) { - currentTime++; + CurrentTime++; if (delayLength) { --delayLength; } @@ -28,15 +29,11 @@ void Timer_Init(void) PIT_StartTimer(PIT, PIT_TIMER_CHANNEL); } -uint32_t Timer_GetCurrentTime() { - return currentTime; -} - uint32_t Timer_GetCurrentTimeMicros() { uint32_t primask, count, ms; primask = DisableGlobalIRQ(); // Make sure the read is atomic count = PIT_GetCurrentTimerCount(PIT, PIT_TIMER_CHANNEL); // Read the current timer count - ms = currentTime; // Read the overflow counter + ms = CurrentTime; // Read the overflow counter EnableGlobalIRQ(primask); // Enable interrupts again if they where enabled before - this should make it interrupt safe // Calculate the counter value in microseconds - note that the PIT timer is counting downward, so we need to subtract the count from the period value @@ -44,11 +41,6 @@ uint32_t Timer_GetCurrentTimeMicros() { return ms * 1000U * TIMER_INTERVAL_MSEC + us; } -void Timer_SetCurrentTime(uint32_t *time) -{ - *time = Timer_GetCurrentTime(); -} - void Timer_SetCurrentTimeMicros(uint32_t *time) { *time = Timer_GetCurrentTimeMicros(); @@ -56,20 +48,18 @@ void Timer_SetCurrentTimeMicros(uint32_t *time) uint32_t Timer_GetElapsedTime(uint32_t *time) { - uint32_t elapsedTime = Timer_GetCurrentTime() - *time; - return elapsedTime; + return CurrentTime - *time; } uint32_t Timer_GetElapsedTimeMicros(uint32_t *time) { - uint32_t elapsedTime = Timer_GetCurrentTimeMicros() - *time; - return elapsedTime; + return Timer_GetCurrentTimeMicros() - *time; } uint32_t Timer_GetElapsedTimeAndSetCurrent(uint32_t *time) { uint32_t elapsedTime = Timer_GetElapsedTime(time); - *time = Timer_GetCurrentTime(); + *time = CurrentTime; return elapsedTime; } diff --git a/right/src/timer.h b/right/src/timer.h index 810bfc1..9d177d1 100644 --- a/right/src/timer.h +++ b/right/src/timer.h @@ -9,12 +9,14 @@ #define TIMER_INTERVAL_MSEC 1 +// Variables: + + extern volatile uint32_t CurrentTime; + // Functions: void Timer_Init(void); - uint32_t Timer_GetCurrentTime(); uint32_t Timer_GetCurrentTimeMicros(); - void Timer_SetCurrentTime(uint32_t *time); void Timer_SetCurrentTimeMicros(uint32_t *time); uint32_t Timer_GetElapsedTime(uint32_t *time); uint32_t Timer_GetElapsedTimeMicros(uint32_t *time); diff --git a/right/src/usb_commands/usb_command_get_debug_buffer.c b/right/src/usb_commands/usb_command_get_debug_buffer.c index 2347594..416cf47 100644 --- a/right/src/usb_commands/usb_command_get_debug_buffer.c +++ b/right/src/usb_commands/usb_command_get_debug_buffer.c @@ -22,7 +22,7 @@ void UsbCommand_GetDebugBuffer(void) SetDebugBufferUint32(13, I2cWatchdog_RecoveryCounter); SetDebugBufferUint32(17, MatrixScanCounter); SetDebugBufferUint32(21, UsbReportUpdateCounter); - SetDebugBufferUint32(25, Timer_GetCurrentTime()); + SetDebugBufferUint32(25, CurrentTime); SetDebugBufferUint32(29, UsbGenericHidActionCounter); SetDebugBufferUint32(33, UsbBasicKeyboardActionCounter); SetDebugBufferUint32(37, UsbMediaKeyboardActionCounter); diff --git a/right/src/usb_commands/usb_command_get_device_property.c b/right/src/usb_commands/usb_command_get_device_property.c index 50d67c6..62c1e5a 100644 --- a/right/src/usb_commands/usb_command_get_device_property.c +++ b/right/src/usb_commands/usb_command_get_device_property.c @@ -69,7 +69,7 @@ void UsbCommand_GetDeviceProperty(void) SetUsbTxBufferUint32(6, I2cMainBusActualBaudRateBps); break; case DevicePropertyId_Uptime: - SetUsbTxBufferUint32(1, Timer_GetCurrentTime()); + SetUsbTxBufferUint32(1, CurrentTime); break; default: SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty); diff --git a/right/src/usb_commands/usb_command_get_variable.c b/right/src/usb_commands/usb_command_get_variable.c index 68df5b8..17d15bf 100644 --- a/right/src/usb_commands/usb_command_get_variable.c +++ b/right/src/usb_commands/usb_command_get_variable.c @@ -21,5 +21,8 @@ void UsbCommand_GetVariable(void) case UsbVariable_DebounceTimeRelease: SetUsbTxBufferUint8(1, DebounceTimeRelease); break; + case UsbVariable_UsbReportSemaphore: + SetUsbTxBufferUint8(1, UsbReportUpdateSemaphore); + break; } } diff --git a/right/src/usb_commands/usb_command_set_variable.c b/right/src/usb_commands/usb_command_set_variable.c index ab31554..8910f41 100644 --- a/right/src/usb_commands/usb_command_set_variable.c +++ b/right/src/usb_commands/usb_command_set_variable.c @@ -24,5 +24,8 @@ void UsbCommand_SetVariable(void) case UsbVariable_DebounceTimeRelease: DebounceTimeRelease = GetUsbRxBufferUint8(2); break; + case UsbVariable_UsbReportSemaphore: + UsbReportUpdateSemaphore = GetUsbRxBufferUint8(2); + break; } } diff --git a/right/src/usb_protocol_handler.h b/right/src/usb_protocol_handler.h index 48cc983..17aa380 100644 --- a/right/src/usb_protocol_handler.h +++ b/right/src/usb_protocol_handler.h @@ -42,7 +42,8 @@ UsbVariable_TestSwitches, UsbVariable_TestUsbStack, UsbVariable_DebounceTimePress, - UsbVariable_DebounceTimeRelease + UsbVariable_DebounceTimeRelease, + UsbVariable_UsbReportSemaphore, } usb_variable_id_t; typedef enum { diff --git a/right/src/usb_report_updater.c b/right/src/usb_report_updater.c index 156db1a..c5f8022 100644 --- a/right/src/usb_report_updater.c +++ b/right/src/usb_report_updater.c @@ -20,11 +20,12 @@ static uint32_t mouseUsbReportUpdateTime = 0; static uint32_t mouseElapsedTime; -uint16_t DoubleTapSwitchLayerTimeout = 150; -static uint16_t DoubleTapSwitchLayerReleaseTimeout = 100; +uint16_t DoubleTapSwitchLayerTimeout = 300; +static uint16_t DoubleTapSwitchLayerReleaseTimeout = 200; static bool activeMouseStates[ACTIVE_MOUSE_STATES_COUNT]; bool TestUsbStack = false; +static key_action_t actionCache[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE]; volatile uint8_t UsbReportUpdateSemaphore = 0; @@ -206,15 +207,15 @@ static void handleSwitchLayerAction(key_state_t *keyState, key_action_t *action) doubleTapSwitchLayerKey = NULL; } + if (action->type != KeyActionType_SwitchLayer) { + return; + } + if (!keyState->previous && isLayerDoubleTapToggled && ToggledLayer == action->switchLayer.layer) { ToggledLayer = LayerId_Base; isLayerDoubleTapToggled = false; } - if (action->type != KeyActionType_SwitchLayer) { - return; - } - if (keyState->previous && doubleTapSwitchLayerKey == keyState && Timer_GetElapsedTime(&doubleTapSwitchLayerTriggerTime) > DoubleTapSwitchLayerReleaseTimeout) { @@ -225,11 +226,11 @@ static void handleSwitchLayerAction(key_state_t *keyState, key_action_t *action) if (doubleTapSwitchLayerKey && Timer_GetElapsedTimeAndSetCurrent(&doubleTapSwitchLayerStartTime) < DoubleTapSwitchLayerTimeout) { ToggledLayer = action->switchLayer.layer; isLayerDoubleTapToggled = true; - doubleTapSwitchLayerTriggerTime = Timer_GetCurrentTime(); + doubleTapSwitchLayerTriggerTime = CurrentTime; } else { doubleTapSwitchLayerKey = keyState; } - doubleTapSwitchLayerStartTime = Timer_GetCurrentTime(); + doubleTapSwitchLayerStartTime = CurrentTime; } } @@ -237,6 +238,10 @@ static uint8_t basicScancodeIndex = 0; static uint8_t mediaScancodeIndex = 0; static uint8_t systemScancodeIndex = 0; static uint8_t stickyModifiers; +static uint8_t secondaryRoleState = SecondaryRoleState_Released; +static uint8_t secondaryRoleSlotId; +static uint8_t secondaryRoleKeyId; +static secondary_role_t secondaryRole; static void applyKeyAction(key_state_t *keyState, key_action_t *action) { @@ -288,6 +293,7 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action) case KeyActionType_SwitchKeymap: if (!keyState->previous) { stickyModifiers = 0; + secondaryRoleState = SecondaryRoleState_Released; SwitchKeymapById(action->switchKeymap.keymapId); } break; @@ -300,11 +306,6 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action) } } -static uint8_t secondaryRoleState = SecondaryRoleState_Released; -static uint8_t secondaryRoleSlotId; -static uint8_t secondaryRoleKeyId; -static secondary_role_t secondaryRole; - static void updateActiveUsbReports(void) { if (MacroPlaying) { @@ -333,7 +334,6 @@ static void updateActiveUsbReports(void) if (layerChanged) { stickyModifiers = 0; } - bool layerGotReleased = layerChanged && activeLayer == LayerId_Base; LedDisplay_SetLayer(activeLayer); if (TestUsbStack) { @@ -351,32 +351,42 @@ static void updateActiveUsbReports(void) isEvenMedia = !isEvenMedia; ActiveUsbMediaKeyboardReport->scancodes[mediaScancodeIndex++] = isEvenMedia ? MEDIA_VOLUME_DOWN : MEDIA_VOLUME_UP; } - MouseMoveState.xOut = isEven ? -1 : 1; + MouseMoveState.xOut = isEven ? -5 : 5; } } for (uint8_t slotId=0; slotIddebouncing) { - if ((uint8_t)(Timer_GetCurrentTime() - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) { + if ((uint8_t)(CurrentTime - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) { keyState->debouncing = false; } else { keyState->current = keyState->previous; } } else if (keyState->previous != keyState->current) { - keyState->timestamp = Timer_GetCurrentTime(); + keyState->timestamp = CurrentTime; keyState->debouncing = true; } - if (keyState->current) { - key_action_t *baseAction = &CurrentKeymap[LayerId_Base][slotId][keyId]; - if (layerGotReleased && !(baseAction->type == KeyActionType_Keystroke && baseAction->keystroke.scancode == 0 && baseAction->keystroke.modifiers)) { - keyState->suppressed = true; + if (keyState->current && !keyState->previous) { + if (SleepModeActive) { + WakeUpHost(); } + if (secondaryRoleState == SecondaryRoleState_Pressed) { + // Trigger secondary role. + secondaryRoleState = SecondaryRoleState_Triggered; + keyState->current = false; + } else { + actionCache[slotId][keyId] = CurrentKeymap[activeLayer][slotId][keyId]; + } + } + action = &actionCache[slotId][keyId]; + + if (keyState->current) { if (action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole) { // Press released secondary role key. if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) { @@ -387,23 +397,16 @@ static void updateActiveUsbReports(void) keyState->suppressed = true; } } else { - // Trigger secondary role. - if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Pressed) { - secondaryRoleState = SecondaryRoleState_Triggered; - keyState->current = false; - } else { - applyKeyAction(keyState, action); - } + applyKeyAction(keyState, action); } } else { - if (keyState->suppressed) { - keyState->suppressed = false; - } + keyState->suppressed = false; // Release secondary role key. if (keyState->previous && secondaryRoleSlotId == slotId && secondaryRoleKeyId == keyId) { // Trigger primary role. if (secondaryRoleState == SecondaryRoleState_Pressed) { + keyState->previous = false; applyKeyAction(keyState, action); } secondaryRoleState = SecondaryRoleState_Released; @@ -432,26 +435,21 @@ uint32_t UsbReportUpdateCounter; void UpdateUsbReports(void) { + static uint32_t lastUpdateTime; + for (uint8_t keyId = 0; keyId < RIGHT_KEY_MATRIX_KEY_COUNT; keyId++) { KeyStates[SlotId_RightKeyboardHalf][keyId].current = RightKeyMatrix.keyStates[keyId]; } - if (SleepModeActive) { - for (uint8_t slotId = 0; slotId < SLOT_COUNT; slotId++) { - for (uint8_t keyId = 0; keyId < MAX_KEY_COUNT_PER_MODULE; keyId++) { - if (KeyStates[slotId][keyId].current) { - WakeUpHost(); - return; - } - } + if (UsbReportUpdateSemaphore && !SleepModeActive) { + if (Timer_GetElapsedTime(&lastUpdateTime) < USB_SEMAPHORE_TIMEOUT) { + return; + } else { + UsbReportUpdateSemaphore = 0; } - return; - } - - if (UsbReportUpdateSemaphore) { - return; } + lastUpdateTime = CurrentTime; UsbReportUpdateCounter++; ResetActiveUsbBasicKeyboardReport(); diff --git a/right/src/usb_report_updater.h b/right/src/usb_report_updater.h index bbdc507..493b2b4 100644 --- a/right/src/usb_report_updater.h +++ b/right/src/usb_report_updater.h @@ -14,6 +14,8 @@ #define SECONDARY_ROLE_MODIFIER_TO_HID_MODIFIER(secondaryRoleModifier) (1 << ((secondaryRoleModifier) - 1)) #define SECONDARY_ROLE_LAYER_TO_LAYER_ID(secondaryRoleLayer) ((secondaryRoleLayer) - SecondaryRole_RightSuper) + #define USB_SEMAPHORE_TIMEOUT 100 // ms + // Typedefs: typedef enum { diff --git a/scripts/package.json b/scripts/package.json index fec2b1b..22142bb 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -15,8 +15,8 @@ "commander": "^2.11.0", "shelljs": "^0.7.8" }, - "firmwareVersion": "8.4.2", - "deviceProtocolVersion": "4.4.0", + "firmwareVersion": "8.5.3", + "deviceProtocolVersion": "4.5.0", "moduleProtocolVersion": "4.0.0", "userConfigVersion": "4.1.0", "hardwareConfigVersion": "1.0.0", diff --git a/shared/versions.h b/shared/versions.h index bc737a3..1a6ccf0 100644 --- a/shared/versions.h +++ b/shared/versions.h @@ -19,11 +19,11 @@ // Variables: #define FIRMWARE_MAJOR_VERSION 8 - #define FIRMWARE_MINOR_VERSION 4 - #define FIRMWARE_PATCH_VERSION 2 + #define FIRMWARE_MINOR_VERSION 5 + #define FIRMWARE_PATCH_VERSION 3 #define DEVICE_PROTOCOL_MAJOR_VERSION 4 - #define DEVICE_PROTOCOL_MINOR_VERSION 4 + #define DEVICE_PROTOCOL_MINOR_VERSION 5 #define DEVICE_PROTOCOL_PATCH_VERSION 0 #define MODULE_PROTOCOL_MAJOR_VERSION 4