1 Commits

Author SHA1 Message Date
Eric Tang
aeaef7b788 Remove the semaphore 2018-08-16 13:54:20 -07:00
21 changed files with 72 additions and 143 deletions

View File

@@ -5,36 +5,6 @@ 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.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 ## [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

View File

@@ -1,8 +0,0 @@
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.

View File

@@ -12,15 +12,19 @@ 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.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). 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).
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.
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. ## Building and flashing the firmware
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 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.
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*. 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.
## Contributing ## Contributing

View File

@@ -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 && !keyState->suppressed) { if (keyState->current) {
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) {

View File

@@ -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_COMMA_AND_LESS_THAN_SIGN; return HID_KEYBOARD_SC_KEYPAD_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 {
delayStart = CurrentTime; Timer_SetCurrentTime(&delayStart);
inDelay = true; inDelay = true;
} }
return inDelay; return inDelay;

View File

@@ -2,13 +2,12 @@
#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 delayLength; static volatile uint32_t currentTime, delayLength;
void PIT_TIMER_HANDLER(void) void PIT_TIMER_HANDLER(void)
{ {
CurrentTime++; currentTime++;
if (delayLength) { if (delayLength) {
--delayLength; --delayLength;
} }
@@ -29,11 +28,15 @@ 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
@@ -41,6 +44,11 @@ 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();
@@ -48,18 +56,20 @@ void Timer_SetCurrentTimeMicros(uint32_t *time)
uint32_t Timer_GetElapsedTime(uint32_t *time) uint32_t Timer_GetElapsedTime(uint32_t *time)
{ {
return CurrentTime - *time; uint32_t elapsedTime = Timer_GetCurrentTime() - *time;
return elapsedTime;
} }
uint32_t Timer_GetElapsedTimeMicros(uint32_t *time) uint32_t Timer_GetElapsedTimeMicros(uint32_t *time)
{ {
return Timer_GetCurrentTimeMicros() - *time; uint32_t elapsedTime = 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 = CurrentTime; *time = Timer_GetCurrentTime();
return elapsedTime; return elapsedTime;
} }

View File

@@ -9,14 +9,12 @@
#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);

View File

@@ -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, CurrentTime); SetDebugBufferUint32(25, Timer_GetCurrentTime());
SetDebugBufferUint32(29, UsbGenericHidActionCounter); SetDebugBufferUint32(29, UsbGenericHidActionCounter);
SetDebugBufferUint32(33, UsbBasicKeyboardActionCounter); SetDebugBufferUint32(33, UsbBasicKeyboardActionCounter);
SetDebugBufferUint32(37, UsbMediaKeyboardActionCounter); SetDebugBufferUint32(37, UsbMediaKeyboardActionCounter);

View File

@@ -69,7 +69,7 @@ void UsbCommand_GetDeviceProperty(void)
SetUsbTxBufferUint32(6, I2cMainBusActualBaudRateBps); SetUsbTxBufferUint32(6, I2cMainBusActualBaudRateBps);
break; break;
case DevicePropertyId_Uptime: case DevicePropertyId_Uptime:
SetUsbTxBufferUint32(1, CurrentTime); SetUsbTxBufferUint32(1, Timer_GetCurrentTime());
break; break;
default: default:
SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty); SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty);

View File

@@ -21,8 +21,5 @@ 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;
} }
} }

View File

@@ -24,8 +24,5 @@ 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;
} }
} }

View File

@@ -1,6 +1,5 @@
#include "led_display.h" #include "led_display.h"
#include "usb_composite_device.h" #include "usb_composite_device.h"
#include "usb_report_updater.h"
static usb_basic_keyboard_report_t usbBasicKeyboardReports[2]; static usb_basic_keyboard_report_t usbBasicKeyboardReports[2];
uint32_t UsbBasicKeyboardActionCounter; uint32_t UsbBasicKeyboardActionCounter;
@@ -45,7 +44,6 @@ usb_status_t UsbBasicKeyboardCallback(class_handle_t handle, uint32_t event, voi
switch (event) { switch (event) {
// This event is received when the report has been sent // This event is received when the report has been sent
case kUSB_DeviceHidEventSendResponse: case kUSB_DeviceHidEventSendResponse:
UsbReportUpdateSemaphore &= ~(1 << USB_BASIC_KEYBOARD_INTERFACE_INDEX);
if (UsbCompositeDevice.attach) { if (UsbCompositeDevice.attach) {
error = kStatus_USB_Success; error = kStatus_USB_Success;
} }

View File

@@ -1,5 +1,4 @@
#include "usb_composite_device.h" #include "usb_composite_device.h"
#include "usb_report_updater.h"
uint32_t UsbMediaKeyboardActionCounter; uint32_t UsbMediaKeyboardActionCounter;
static usb_media_keyboard_report_t usbMediaKeyboardReports[2]; static usb_media_keyboard_report_t usbMediaKeyboardReports[2];
@@ -43,7 +42,6 @@ usb_status_t UsbMediaKeyboardCallback(class_handle_t handle, uint32_t event, voi
switch (event) { switch (event) {
// This event is received when the report has been sent // This event is received when the report has been sent
case kUSB_DeviceHidEventSendResponse: case kUSB_DeviceHidEventSendResponse:
UsbReportUpdateSemaphore &= ~(1 << USB_MEDIA_KEYBOARD_INTERFACE_INDEX);
if (UsbCompositeDevice.attach) { if (UsbCompositeDevice.attach) {
error = kStatus_USB_Success; error = kStatus_USB_Success;
} }

View File

@@ -1,5 +1,4 @@
#include "usb_composite_device.h" #include "usb_composite_device.h"
#include "usb_report_updater.h"
uint32_t UsbMouseActionCounter; uint32_t UsbMouseActionCounter;
static usb_mouse_report_t usbMouseReports[2]; static usb_mouse_report_t usbMouseReports[2];
@@ -43,7 +42,6 @@ usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param
switch (event) { switch (event) {
// This event is received when the report has been sent // This event is received when the report has been sent
case kUSB_DeviceHidEventSendResponse: case kUSB_DeviceHidEventSendResponse:
UsbReportUpdateSemaphore &= ~(1 << USB_MOUSE_INTERFACE_INDEX);
if (UsbCompositeDevice.attach) { if (UsbCompositeDevice.attach) {
error = kStatus_USB_Success; error = kStatus_USB_Success;
} }

View File

@@ -1,5 +1,4 @@
#include "usb_composite_device.h" #include "usb_composite_device.h"
#include "usb_report_updater.h"
uint32_t UsbSystemKeyboardActionCounter; uint32_t UsbSystemKeyboardActionCounter;
static usb_system_keyboard_report_t usbSystemKeyboardReports[2]; static usb_system_keyboard_report_t usbSystemKeyboardReports[2];
@@ -43,7 +42,6 @@ usb_status_t UsbSystemKeyboardCallback(class_handle_t handle, uint32_t event, vo
switch (event) { switch (event) {
// This event is received when the report has been sent // This event is received when the report has been sent
case kUSB_DeviceHidEventSendResponse: case kUSB_DeviceHidEventSendResponse:
UsbReportUpdateSemaphore &= ~(1 << USB_SYSTEM_KEYBOARD_INTERFACE_INDEX);
if (UsbCompositeDevice.attach) { if (UsbCompositeDevice.attach) {
error = kStatus_USB_Success; error = kStatus_USB_Success;
} }

View File

@@ -42,8 +42,7 @@
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 {

View File

@@ -25,9 +25,6 @@ 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;
static key_action_t actionCache[SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE];
volatile uint8_t UsbReportUpdateSemaphore = 0;
mouse_kinetic_state_t MouseMoveState = { mouse_kinetic_state_t MouseMoveState = {
.isScroll = false, .isScroll = false,
@@ -207,15 +204,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)
{ {
@@ -226,11 +223,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 = CurrentTime; doubleTapSwitchLayerTriggerTime = Timer_GetCurrentTime();
} else { } else {
doubleTapSwitchLayerKey = keyState; doubleTapSwitchLayerKey = keyState;
} }
doubleTapSwitchLayerStartTime = CurrentTime; doubleTapSwitchLayerStartTime = Timer_GetCurrentTime();
} }
} }
@@ -238,10 +235,6 @@ 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)
{ {
@@ -293,7 +286,6 @@ 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;
@@ -306,6 +298,11 @@ 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) {
@@ -334,6 +331,7 @@ static void updateActiveUsbReports(void)
if (layerChanged) { if (layerChanged) {
stickyModifiers = 0; stickyModifiers = 0;
} }
bool layerGotReleased = layerChanged && activeLayer == LayerId_Base;
LedDisplay_SetLayer(activeLayer); LedDisplay_SetLayer(activeLayer);
if (TestUsbStack) { if (TestUsbStack) {
@@ -351,43 +349,40 @@ 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 ? -5 : 5; MouseMoveState.xOut = isEven ? -1 : 1;
} }
} }
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; key_action_t *action = &CurrentKeymap[activeLayer][slotId][keyId];
if (keyState->debouncing) { if (keyState->debouncing) {
if ((uint8_t)(CurrentTime - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) { if ((uint8_t)(Timer_GetCurrentTime() - 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 = CurrentTime; keyState->timestamp = Timer_GetCurrentTime();
keyState->debouncing = true; keyState->debouncing = true;
} }
if (keyState->current && !keyState->previous) { if (keyState->current) {
if (SleepModeActive) { if (SleepModeActive && !keyState->previous) {
WakeUpHost(); WakeUpHost();
} }
if (secondaryRoleState == SecondaryRoleState_Pressed) { 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;
}
// Trigger secondary role. // Trigger secondary role.
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Pressed) {
secondaryRoleState = SecondaryRoleState_Triggered; secondaryRoleState = SecondaryRoleState_Triggered;
keyState->current = false; keyState->current = false;
} else { } else if (action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole) {
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. // Press released secondary role key.
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) { if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) {
secondaryRoleState = SecondaryRoleState_Pressed; secondaryRoleState = SecondaryRoleState_Pressed;
@@ -400,13 +395,14 @@ 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;
@@ -435,21 +431,10 @@ uint32_t UsbReportUpdateCounter;
void UpdateUsbReports(void) void UpdateUsbReports(void)
{ {
static uint32_t lastUpdateTime;
for (uint8_t keyId = 0; keyId < RIGHT_KEY_MATRIX_KEY_COUNT; keyId++) { for (uint8_t keyId = 0; keyId < RIGHT_KEY_MATRIX_KEY_COUNT; keyId++) {
KeyStates[SlotId_RightKeyboardHalf][keyId].current = RightKeyMatrix.keyStates[keyId]; KeyStates[SlotId_RightKeyboardHalf][keyId].current = RightKeyMatrix.keyStates[keyId];
} }
if (UsbReportUpdateSemaphore && !SleepModeActive) {
if (Timer_GetElapsedTime(&lastUpdateTime) < USB_SEMAPHORE_TIMEOUT) {
return;
} else {
UsbReportUpdateSemaphore = 0;
}
}
lastUpdateTime = CurrentTime;
UsbReportUpdateCounter++; UsbReportUpdateCounter++;
ResetActiveUsbBasicKeyboardReport(); ResetActiveUsbBasicKeyboardReport();
@@ -465,32 +450,20 @@ void UpdateUsbReports(void)
bool HasUsbMouseReportChanged = memcmp(ActiveUsbMouseReport, GetInactiveUsbMouseReport(), sizeof(usb_mouse_report_t)) != 0; bool HasUsbMouseReportChanged = memcmp(ActiveUsbMouseReport, GetInactiveUsbMouseReport(), sizeof(usb_mouse_report_t)) != 0;
if (HasUsbBasicKeyboardReportChanged) { if (HasUsbBasicKeyboardReportChanged) {
usb_status_t status = UsbBasicKeyboardAction(); UsbBasicKeyboardAction();
if (status == kStatus_USB_Success) {
UsbReportUpdateSemaphore |= 1 << USB_BASIC_KEYBOARD_INTERFACE_INDEX;
}
} }
if (HasUsbMediaKeyboardReportChanged) { if (HasUsbMediaKeyboardReportChanged) {
usb_status_t status = UsbMediaKeyboardAction(); UsbMediaKeyboardAction();
if (status == kStatus_USB_Success) {
UsbReportUpdateSemaphore |= 1 << USB_MEDIA_KEYBOARD_INTERFACE_INDEX;
}
} }
if (HasUsbSystemKeyboardReportChanged) { if (HasUsbSystemKeyboardReportChanged) {
usb_status_t status = UsbSystemKeyboardAction(); UsbSystemKeyboardAction();
if (status == kStatus_USB_Success) {
UsbReportUpdateSemaphore |= 1 << USB_SYSTEM_KEYBOARD_INTERFACE_INDEX;
}
} }
// Send out the mouse position and wheel values continuously if the report is not zeros, but only send the mouse button states when they change. // Send out the mouse position and wheel values continuously if the report is not zeros, but only send the mouse button states when they change.
if (HasUsbMouseReportChanged || ActiveUsbMouseReport->x || ActiveUsbMouseReport->y || if (HasUsbMouseReportChanged || ActiveUsbMouseReport->x || ActiveUsbMouseReport->y ||
ActiveUsbMouseReport->wheelX || ActiveUsbMouseReport->wheelY) { ActiveUsbMouseReport->wheelX || ActiveUsbMouseReport->wheelY) {
usb_status_t status = UsbMouseAction(); UsbMouseAction();
if (status == kStatus_USB_Success) {
UsbReportUpdateSemaphore |= 1 << USB_MOUSE_INTERFACE_INDEX;
}
} }
} }

View File

@@ -14,8 +14,6 @@
#define SECONDARY_ROLE_MODIFIER_TO_HID_MODIFIER(secondaryRoleModifier) (1 << ((secondaryRoleModifier) - 1)) #define SECONDARY_ROLE_MODIFIER_TO_HID_MODIFIER(secondaryRoleModifier) (1 << ((secondaryRoleModifier) - 1))
#define SECONDARY_ROLE_LAYER_TO_LAYER_ID(secondaryRoleLayer) ((secondaryRoleLayer) - SecondaryRole_RightSuper) #define SECONDARY_ROLE_LAYER_TO_LAYER_ID(secondaryRoleLayer) ((secondaryRoleLayer) - SecondaryRole_RightSuper)
#define USB_SEMAPHORE_TIMEOUT 100 // ms
// Typedefs: // Typedefs:
typedef enum { typedef enum {
@@ -72,7 +70,6 @@
extern mouse_kinetic_state_t MouseMoveState; extern mouse_kinetic_state_t MouseMoveState;
extern mouse_kinetic_state_t MouseScrollState; extern mouse_kinetic_state_t MouseScrollState;
extern uint32_t UsbReportUpdateCounter; extern uint32_t UsbReportUpdateCounter;
extern volatile uint8_t UsbReportUpdateSemaphore;
extern bool TestUsbStack; extern bool TestUsbStack;
// Functions: // Functions:

View File

@@ -15,8 +15,8 @@
"commander": "^2.11.0", "commander": "^2.11.0",
"shelljs": "^0.7.8" "shelljs": "^0.7.8"
}, },
"firmwareVersion": "8.5.2", "firmwareVersion": "8.4.4",
"deviceProtocolVersion": "4.5.0", "deviceProtocolVersion": "4.4.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",

View File

@@ -19,11 +19,11 @@
// Variables: // Variables:
#define FIRMWARE_MAJOR_VERSION 8 #define FIRMWARE_MAJOR_VERSION 8
#define FIRMWARE_MINOR_VERSION 5 #define FIRMWARE_MINOR_VERSION 4
#define FIRMWARE_PATCH_VERSION 2 #define FIRMWARE_PATCH_VERSION 4
#define DEVICE_PROTOCOL_MAJOR_VERSION 4 #define DEVICE_PROTOCOL_MAJOR_VERSION 4
#define DEVICE_PROTOCOL_MINOR_VERSION 5 #define DEVICE_PROTOCOL_MINOR_VERSION 4
#define DEVICE_PROTOCOL_PATCH_VERSION 0 #define DEVICE_PROTOCOL_PATCH_VERSION 0
#define MODULE_PROTOCOL_MAJOR_VERSION 4 #define MODULE_PROTOCOL_MAJOR_VERSION 4