Compare commits
23 Commits
semaphore-
...
v8.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f2b45c27c | ||
|
|
98f7d512de | ||
|
|
c5cf738fd0 | ||
|
|
af31ae210a | ||
|
|
44799995b9 | ||
|
|
3f5f83a19b | ||
|
|
bc4f35e578 | ||
|
|
e9309aab16 | ||
|
|
f004b84399 | ||
|
|
58f8120611 | ||
|
|
5b71fb7aaa | ||
|
|
9d0f41bf5e | ||
|
|
47a3a8ad80 | ||
|
|
b4908bf2ac | ||
|
|
846342e851 | ||
|
|
3196abe574 | ||
|
|
5f0bae1840 | ||
|
|
c3a38c8b59 | ||
|
|
1f9d31cad4 | ||
|
|
b89de6655e | ||
|
|
4a1b747197 | ||
|
|
eca87d2f62 | ||
|
|
2e2b9d08a9 |
18
CHANGELOG.md
18
CHANGELOG.md
@@ -5,6 +5,24 @@ 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/)
|
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.
|
and this project adheres to the [UHK Versioning](VERSIONING.md) conventions.
|
||||||
|
|
||||||
|
## [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
|
## [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
|
Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0
|
||||||
|
|||||||
1
ISSUE_TEMPLATE
Normal file
1
ISSUE_TEMPLATE
Normal file
@@ -0,0 +1 @@
|
|||||||
|
If you're using Karabiner Elements on your Mac, then stop here! Make sure to close Karabiner Elements, then try to reproduce the issue again, even if you think that Karabiner Elements shouldn't be the cause. Karabiner Elements is the source of numerous problems, and we don't want to receive any more reports it causes.
|
||||||
12
README.md
12
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`
|
`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.
|
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.
|
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*.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
Submodule lib/agent updated: 80e8c014ec...6e2b1fb18d
@@ -5,6 +5,7 @@
|
|||||||
#include "config_parser/parse_keymap.h"
|
#include "config_parser/parse_keymap.h"
|
||||||
#include "config_parser/config_globals.h"
|
#include "config_parser/config_globals.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
#include "usb_report_updater.h"
|
||||||
|
|
||||||
keymap_reference_t AllKeymaps[MAX_KEYMAP_NUM] = {
|
keymap_reference_t AllKeymaps[MAX_KEYMAP_NUM] = {
|
||||||
{
|
{
|
||||||
@@ -24,6 +25,7 @@ void SwitchKeymapById(uint8_t index)
|
|||||||
ValidatedUserConfigBuffer.offset = AllKeymaps[index].offset;
|
ValidatedUserConfigBuffer.offset = AllKeymaps[index].offset;
|
||||||
ParseKeymap(&ValidatedUserConfigBuffer, index, AllKeymapsCount, AllMacrosCount);
|
ParseKeymap(&ValidatedUserConfigBuffer, index, AllKeymapsCount, AllMacrosCount);
|
||||||
LedDisplay_UpdateText();
|
LedDisplay_UpdateText();
|
||||||
|
KeymapChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitchKeymapByAbbreviation(uint8_t length, char *abbrev)
|
bool SwitchKeymapByAbbreviation(uint8_t length, char *abbrev)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void updateLayerStates(void)
|
|||||||
for (uint8_t slotId=0; slotId<SLOT_COUNT; slotId++) {
|
for (uint8_t slotId=0; slotId<SLOT_COUNT; slotId++) {
|
||||||
for (uint8_t keyId=0; keyId<MAX_KEY_COUNT_PER_MODULE; keyId++) {
|
for (uint8_t keyId=0; keyId<MAX_KEY_COUNT_PER_MODULE; keyId++) {
|
||||||
key_state_t *keyState = &KeyStates[slotId][keyId];
|
key_state_t *keyState = &KeyStates[slotId][keyId];
|
||||||
if (keyState->current) {
|
if (keyState->current && !keyState->suppressed) {
|
||||||
key_action_t action = CurrentKeymap[LayerId_Base][slotId][keyId];
|
key_action_t action = CurrentKeymap[LayerId_Base][slotId][keyId];
|
||||||
if (action.type == KeyActionType_SwitchLayer) {
|
if (action.type == KeyActionType_SwitchLayer) {
|
||||||
if (action.switchLayer.mode != SwitchLayerMode_Toggle) {
|
if (action.switchLayer.mode != SwitchLayerMode_Toggle) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ uint8_t characterToScancode(char character)
|
|||||||
return HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN;
|
return HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN;
|
||||||
case ',':
|
case ',':
|
||||||
case '<':
|
case '<':
|
||||||
return HID_KEYBOARD_SC_KEYPAD_LESS_THAN_SIGN;
|
return HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN;
|
||||||
case '/':
|
case '/':
|
||||||
case '\?':
|
case '\?':
|
||||||
return HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK;
|
return HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK;
|
||||||
@@ -286,7 +286,7 @@ bool processDelayAction(void)
|
|||||||
inDelay = false;
|
inDelay = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timer_SetCurrentTime(&delayStart);
|
delayStart = CurrentTime;
|
||||||
inDelay = true;
|
inDelay = true;
|
||||||
}
|
}
|
||||||
return inDelay;
|
return inDelay;
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "peripherals/test_led.h"
|
#include "peripherals/test_led.h"
|
||||||
|
|
||||||
|
volatile uint32_t CurrentTime;
|
||||||
static uint32_t timerClockFrequency;
|
static uint32_t timerClockFrequency;
|
||||||
static volatile uint32_t currentTime, delayLength;
|
static volatile uint32_t delayLength;
|
||||||
|
|
||||||
void PIT_TIMER_HANDLER(void)
|
void PIT_TIMER_HANDLER(void)
|
||||||
{
|
{
|
||||||
currentTime++;
|
CurrentTime++;
|
||||||
if (delayLength) {
|
if (delayLength) {
|
||||||
--delayLength;
|
--delayLength;
|
||||||
}
|
}
|
||||||
@@ -28,15 +29,11 @@ void Timer_Init(void)
|
|||||||
PIT_StartTimer(PIT, PIT_TIMER_CHANNEL);
|
PIT_StartTimer(PIT, PIT_TIMER_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Timer_GetCurrentTime() {
|
|
||||||
return currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Timer_GetCurrentTimeMicros() {
|
uint32_t Timer_GetCurrentTimeMicros() {
|
||||||
uint32_t primask, count, ms;
|
uint32_t primask, count, ms;
|
||||||
primask = DisableGlobalIRQ(); // Make sure the read is atomic
|
primask = DisableGlobalIRQ(); // Make sure the read is atomic
|
||||||
count = PIT_GetCurrentTimerCount(PIT, PIT_TIMER_CHANNEL); // Read the current timer count
|
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
|
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
|
// 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;
|
return ms * 1000U * TIMER_INTERVAL_MSEC + us;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer_SetCurrentTime(uint32_t *time)
|
|
||||||
{
|
|
||||||
*time = Timer_GetCurrentTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timer_SetCurrentTimeMicros(uint32_t *time)
|
void Timer_SetCurrentTimeMicros(uint32_t *time)
|
||||||
{
|
{
|
||||||
*time = Timer_GetCurrentTimeMicros();
|
*time = Timer_GetCurrentTimeMicros();
|
||||||
@@ -56,20 +48,18 @@ void Timer_SetCurrentTimeMicros(uint32_t *time)
|
|||||||
|
|
||||||
uint32_t Timer_GetElapsedTime(uint32_t *time)
|
uint32_t Timer_GetElapsedTime(uint32_t *time)
|
||||||
{
|
{
|
||||||
uint32_t elapsedTime = Timer_GetCurrentTime() - *time;
|
return CurrentTime - *time;
|
||||||
return elapsedTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Timer_GetElapsedTimeMicros(uint32_t *time)
|
uint32_t Timer_GetElapsedTimeMicros(uint32_t *time)
|
||||||
{
|
{
|
||||||
uint32_t elapsedTime = Timer_GetCurrentTimeMicros() - *time;
|
return Timer_GetCurrentTimeMicros() - *time;
|
||||||
return elapsedTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Timer_GetElapsedTimeAndSetCurrent(uint32_t *time)
|
uint32_t Timer_GetElapsedTimeAndSetCurrent(uint32_t *time)
|
||||||
{
|
{
|
||||||
uint32_t elapsedTime = Timer_GetElapsedTime(time);
|
uint32_t elapsedTime = Timer_GetElapsedTime(time);
|
||||||
*time = Timer_GetCurrentTime();
|
*time = CurrentTime;
|
||||||
return elapsedTime;
|
return elapsedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
|
|
||||||
#define TIMER_INTERVAL_MSEC 1
|
#define TIMER_INTERVAL_MSEC 1
|
||||||
|
|
||||||
|
// Variables:
|
||||||
|
|
||||||
|
extern volatile uint32_t CurrentTime;
|
||||||
|
|
||||||
// Functions:
|
// Functions:
|
||||||
|
|
||||||
void Timer_Init(void);
|
void Timer_Init(void);
|
||||||
uint32_t Timer_GetCurrentTime();
|
|
||||||
uint32_t Timer_GetCurrentTimeMicros();
|
uint32_t Timer_GetCurrentTimeMicros();
|
||||||
void Timer_SetCurrentTime(uint32_t *time);
|
|
||||||
void Timer_SetCurrentTimeMicros(uint32_t *time);
|
void Timer_SetCurrentTimeMicros(uint32_t *time);
|
||||||
uint32_t Timer_GetElapsedTime(uint32_t *time);
|
uint32_t Timer_GetElapsedTime(uint32_t *time);
|
||||||
uint32_t Timer_GetElapsedTimeMicros(uint32_t *time);
|
uint32_t Timer_GetElapsedTimeMicros(uint32_t *time);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ void UsbCommand_GetDebugBuffer(void)
|
|||||||
SetDebugBufferUint32(13, I2cWatchdog_RecoveryCounter);
|
SetDebugBufferUint32(13, I2cWatchdog_RecoveryCounter);
|
||||||
SetDebugBufferUint32(17, MatrixScanCounter);
|
SetDebugBufferUint32(17, MatrixScanCounter);
|
||||||
SetDebugBufferUint32(21, UsbReportUpdateCounter);
|
SetDebugBufferUint32(21, UsbReportUpdateCounter);
|
||||||
SetDebugBufferUint32(25, Timer_GetCurrentTime());
|
SetDebugBufferUint32(25, CurrentTime);
|
||||||
SetDebugBufferUint32(29, UsbGenericHidActionCounter);
|
SetDebugBufferUint32(29, UsbGenericHidActionCounter);
|
||||||
SetDebugBufferUint32(33, UsbBasicKeyboardActionCounter);
|
SetDebugBufferUint32(33, UsbBasicKeyboardActionCounter);
|
||||||
SetDebugBufferUint32(37, UsbMediaKeyboardActionCounter);
|
SetDebugBufferUint32(37, UsbMediaKeyboardActionCounter);
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void UsbCommand_GetDeviceProperty(void)
|
|||||||
SetUsbTxBufferUint32(6, I2cMainBusActualBaudRateBps);
|
SetUsbTxBufferUint32(6, I2cMainBusActualBaudRateBps);
|
||||||
break;
|
break;
|
||||||
case DevicePropertyId_Uptime:
|
case DevicePropertyId_Uptime:
|
||||||
SetUsbTxBufferUint32(1, Timer_GetCurrentTime());
|
SetUsbTxBufferUint32(1, CurrentTime);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty);
|
SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty);
|
||||||
|
|||||||
@@ -21,5 +21,8 @@ void UsbCommand_GetVariable(void)
|
|||||||
case UsbVariable_DebounceTimeRelease:
|
case UsbVariable_DebounceTimeRelease:
|
||||||
SetUsbTxBufferUint8(1, DebounceTimeRelease);
|
SetUsbTxBufferUint8(1, DebounceTimeRelease);
|
||||||
break;
|
break;
|
||||||
|
case UsbVariable_UsbReportSemaphore:
|
||||||
|
SetUsbTxBufferUint8(1, UsbReportUpdateSemaphore);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,8 @@ void UsbCommand_SetVariable(void)
|
|||||||
case UsbVariable_DebounceTimeRelease:
|
case UsbVariable_DebounceTimeRelease:
|
||||||
DebounceTimeRelease = GetUsbRxBufferUint8(2);
|
DebounceTimeRelease = GetUsbRxBufferUint8(2);
|
||||||
break;
|
break;
|
||||||
|
case UsbVariable_UsbReportSemaphore:
|
||||||
|
UsbReportUpdateSemaphore = GetUsbRxBufferUint8(2);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
UsbVariable_TestSwitches,
|
UsbVariable_TestSwitches,
|
||||||
UsbVariable_TestUsbStack,
|
UsbVariable_TestUsbStack,
|
||||||
UsbVariable_DebounceTimePress,
|
UsbVariable_DebounceTimePress,
|
||||||
UsbVariable_DebounceTimeRelease
|
UsbVariable_DebounceTimeRelease,
|
||||||
|
UsbVariable_UsbReportSemaphore,
|
||||||
} usb_variable_id_t;
|
} usb_variable_id_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ static uint16_t DoubleTapSwitchLayerReleaseTimeout = 200;
|
|||||||
|
|
||||||
static bool activeMouseStates[ACTIVE_MOUSE_STATES_COUNT];
|
static bool activeMouseStates[ACTIVE_MOUSE_STATES_COUNT];
|
||||||
bool TestUsbStack = false;
|
bool TestUsbStack = false;
|
||||||
|
bool KeymapChanged = false;
|
||||||
|
static uint8_t layerCache[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE];
|
||||||
|
|
||||||
volatile uint8_t UsbReportUpdateSemaphore = 0;
|
volatile uint8_t UsbReportUpdateSemaphore = 0;
|
||||||
|
|
||||||
@@ -206,15 +208,15 @@ static void handleSwitchLayerAction(key_state_t *keyState, key_action_t *action)
|
|||||||
doubleTapSwitchLayerKey = NULL;
|
doubleTapSwitchLayerKey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action->type != KeyActionType_SwitchLayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!keyState->previous && isLayerDoubleTapToggled && ToggledLayer == action->switchLayer.layer) {
|
if (!keyState->previous && isLayerDoubleTapToggled && ToggledLayer == action->switchLayer.layer) {
|
||||||
ToggledLayer = LayerId_Base;
|
ToggledLayer = LayerId_Base;
|
||||||
isLayerDoubleTapToggled = false;
|
isLayerDoubleTapToggled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action->type != KeyActionType_SwitchLayer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyState->previous && doubleTapSwitchLayerKey == keyState &&
|
if (keyState->previous && doubleTapSwitchLayerKey == keyState &&
|
||||||
Timer_GetElapsedTime(&doubleTapSwitchLayerTriggerTime) > DoubleTapSwitchLayerReleaseTimeout)
|
Timer_GetElapsedTime(&doubleTapSwitchLayerTriggerTime) > DoubleTapSwitchLayerReleaseTimeout)
|
||||||
{
|
{
|
||||||
@@ -225,11 +227,11 @@ static void handleSwitchLayerAction(key_state_t *keyState, key_action_t *action)
|
|||||||
if (doubleTapSwitchLayerKey && Timer_GetElapsedTimeAndSetCurrent(&doubleTapSwitchLayerStartTime) < DoubleTapSwitchLayerTimeout) {
|
if (doubleTapSwitchLayerKey && Timer_GetElapsedTimeAndSetCurrent(&doubleTapSwitchLayerStartTime) < DoubleTapSwitchLayerTimeout) {
|
||||||
ToggledLayer = action->switchLayer.layer;
|
ToggledLayer = action->switchLayer.layer;
|
||||||
isLayerDoubleTapToggled = true;
|
isLayerDoubleTapToggled = true;
|
||||||
doubleTapSwitchLayerTriggerTime = Timer_GetCurrentTime();
|
doubleTapSwitchLayerTriggerTime = CurrentTime;
|
||||||
} else {
|
} else {
|
||||||
doubleTapSwitchLayerKey = keyState;
|
doubleTapSwitchLayerKey = keyState;
|
||||||
}
|
}
|
||||||
doubleTapSwitchLayerStartTime = Timer_GetCurrentTime();
|
doubleTapSwitchLayerStartTime = CurrentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,6 +239,10 @@ static uint8_t basicScancodeIndex = 0;
|
|||||||
static uint8_t mediaScancodeIndex = 0;
|
static uint8_t mediaScancodeIndex = 0;
|
||||||
static uint8_t systemScancodeIndex = 0;
|
static uint8_t systemScancodeIndex = 0;
|
||||||
static uint8_t stickyModifiers;
|
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)
|
static void applyKeyAction(key_state_t *keyState, key_action_t *action)
|
||||||
{
|
{
|
||||||
@@ -288,6 +294,7 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action)
|
|||||||
case KeyActionType_SwitchKeymap:
|
case KeyActionType_SwitchKeymap:
|
||||||
if (!keyState->previous) {
|
if (!keyState->previous) {
|
||||||
stickyModifiers = 0;
|
stickyModifiers = 0;
|
||||||
|
secondaryRoleState = SecondaryRoleState_Released;
|
||||||
SwitchKeymapById(action->switchKeymap.keymapId);
|
SwitchKeymapById(action->switchKeymap.keymapId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -300,11 +307,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)
|
static void updateActiveUsbReports(void)
|
||||||
{
|
{
|
||||||
if (MacroPlaying) {
|
if (MacroPlaying) {
|
||||||
@@ -333,7 +335,8 @@ static void updateActiveUsbReports(void)
|
|||||||
if (layerChanged) {
|
if (layerChanged) {
|
||||||
stickyModifiers = 0;
|
stickyModifiers = 0;
|
||||||
}
|
}
|
||||||
bool layerGotReleased = layerChanged && activeLayer == LayerId_Base;
|
bool keymapChangedLastCycle = KeymapChanged;
|
||||||
|
KeymapChanged = false;
|
||||||
LedDisplay_SetLayer(activeLayer);
|
LedDisplay_SetLayer(activeLayer);
|
||||||
|
|
||||||
if (TestUsbStack) {
|
if (TestUsbStack) {
|
||||||
@@ -351,39 +354,44 @@ static void updateActiveUsbReports(void)
|
|||||||
isEvenMedia = !isEvenMedia;
|
isEvenMedia = !isEvenMedia;
|
||||||
ActiveUsbMediaKeyboardReport->scancodes[mediaScancodeIndex++] = isEvenMedia ? MEDIA_VOLUME_DOWN : MEDIA_VOLUME_UP;
|
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; slotId<SLOT_COUNT; slotId++) {
|
for (uint8_t slotId=0; slotId<SLOT_COUNT; slotId++) {
|
||||||
for (uint8_t keyId=0; keyId<MAX_KEY_COUNT_PER_MODULE; keyId++) {
|
for (uint8_t keyId=0; keyId<MAX_KEY_COUNT_PER_MODULE; keyId++) {
|
||||||
key_state_t *keyState = &KeyStates[slotId][keyId];
|
key_state_t *keyState = &KeyStates[slotId][keyId];
|
||||||
key_action_t *action = &CurrentKeymap[activeLayer][slotId][keyId];
|
key_action_t *action;
|
||||||
|
|
||||||
if (keyState->debouncing) {
|
if (keyState->debouncing) {
|
||||||
if ((uint8_t)(Timer_GetCurrentTime() - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) {
|
if ((uint8_t)(CurrentTime - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) {
|
||||||
keyState->debouncing = false;
|
keyState->debouncing = false;
|
||||||
} else {
|
} else {
|
||||||
keyState->current = keyState->previous;
|
keyState->current = keyState->previous;
|
||||||
}
|
}
|
||||||
} else if (keyState->previous != keyState->current) {
|
} else if (keyState->previous != keyState->current) {
|
||||||
keyState->timestamp = Timer_GetCurrentTime();
|
keyState->timestamp = CurrentTime;
|
||||||
keyState->debouncing = true;
|
keyState->debouncing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyState->current) {
|
if (keyState->current && !keyState->previous) {
|
||||||
if (SleepModeActive && !keyState->previous) {
|
if (SleepModeActive) {
|
||||||
WakeUpHost();
|
WakeUpHost();
|
||||||
}
|
}
|
||||||
key_action_t *baseAction = &CurrentKeymap[LayerId_Base][slotId][keyId];
|
if (secondaryRoleState == SecondaryRoleState_Pressed) {
|
||||||
if (layerGotReleased && !(baseAction->type == KeyActionType_Keystroke && baseAction->keystroke.scancode == 0 && baseAction->keystroke.modifiers)) {
|
// Trigger secondary role.
|
||||||
keyState->suppressed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger secondary role.
|
|
||||||
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Pressed) {
|
|
||||||
secondaryRoleState = SecondaryRoleState_Triggered;
|
secondaryRoleState = SecondaryRoleState_Triggered;
|
||||||
keyState->current = false;
|
keyState->current = false;
|
||||||
|
} else {
|
||||||
|
layerCache[slotId][keyId] = activeLayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action = &CurrentKeymap[layerCache[slotId][keyId]][slotId][keyId];
|
||||||
|
|
||||||
|
if (keyState->current) {
|
||||||
|
if ((KeymapChanged || keymapChangedLastCycle) && keyState->previous) {
|
||||||
|
keyState->suppressed = true;
|
||||||
} else if (action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole) {
|
} else if (action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole) {
|
||||||
// Press released secondary role key.
|
// Press released secondary role key.
|
||||||
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) {
|
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) {
|
||||||
@@ -397,14 +405,13 @@ static void updateActiveUsbReports(void)
|
|||||||
applyKeyAction(keyState, action);
|
applyKeyAction(keyState, action);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (keyState->suppressed) {
|
keyState->suppressed = false;
|
||||||
keyState->suppressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release secondary role key.
|
// Release secondary role key.
|
||||||
if (keyState->previous && secondaryRoleSlotId == slotId && secondaryRoleKeyId == keyId) {
|
if (keyState->previous && secondaryRoleSlotId == slotId && secondaryRoleKeyId == keyId) {
|
||||||
// Trigger primary role.
|
// Trigger primary role.
|
||||||
if (secondaryRoleState == SecondaryRoleState_Pressed) {
|
if (secondaryRoleState == SecondaryRoleState_Pressed) {
|
||||||
|
keyState->previous = false;
|
||||||
applyKeyAction(keyState, action);
|
applyKeyAction(keyState, action);
|
||||||
}
|
}
|
||||||
secondaryRoleState = SecondaryRoleState_Released;
|
secondaryRoleState = SecondaryRoleState_Released;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
extern uint32_t UsbReportUpdateCounter;
|
extern uint32_t UsbReportUpdateCounter;
|
||||||
extern volatile uint8_t UsbReportUpdateSemaphore;
|
extern volatile uint8_t UsbReportUpdateSemaphore;
|
||||||
extern bool TestUsbStack;
|
extern bool TestUsbStack;
|
||||||
|
extern bool KeymapChanged;
|
||||||
|
|
||||||
// Functions:
|
// Functions:
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
"commander": "^2.11.0",
|
"commander": "^2.11.0",
|
||||||
"shelljs": "^0.7.8"
|
"shelljs": "^0.7.8"
|
||||||
},
|
},
|
||||||
"firmwareVersion": "8.4.4",
|
"firmwareVersion": "8.5.0",
|
||||||
"deviceProtocolVersion": "4.4.0",
|
"deviceProtocolVersion": "4.5.0",
|
||||||
"moduleProtocolVersion": "4.0.0",
|
"moduleProtocolVersion": "4.0.0",
|
||||||
"userConfigVersion": "4.1.0",
|
"userConfigVersion": "4.1.0",
|
||||||
"hardwareConfigVersion": "1.0.0",
|
"hardwareConfigVersion": "1.0.0",
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
// Variables:
|
// Variables:
|
||||||
|
|
||||||
#define FIRMWARE_MAJOR_VERSION 8
|
#define FIRMWARE_MAJOR_VERSION 8
|
||||||
#define FIRMWARE_MINOR_VERSION 4
|
#define FIRMWARE_MINOR_VERSION 5
|
||||||
#define FIRMWARE_PATCH_VERSION 4
|
#define FIRMWARE_PATCH_VERSION 0
|
||||||
|
|
||||||
#define DEVICE_PROTOCOL_MAJOR_VERSION 4
|
#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 DEVICE_PROTOCOL_PATCH_VERSION 0
|
||||||
|
|
||||||
#define MODULE_PROTOCOL_MAJOR_VERSION 4
|
#define MODULE_PROTOCOL_MAJOR_VERSION 4
|
||||||
|
|||||||
Reference in New Issue
Block a user