82 Commits

Author SHA1 Message Date
László Monda
a59b43b433 Bump version to 8.5.3, update package.json, changelog, versions.h and reference the latest Agent. 2018-10-20 01:20:31 +02:00
László Monda
ceb2f3de00 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. 2018-10-20 01:11:36 +02:00
László Monda
5cd4030a93 Merge branch 'master' of github.com:UltimateHackingKeyboard/firmware 2018-10-06 21:33:16 +02:00
László Monda
21ae72dd9e Bump version to 8.5.2, update changelog, package.json, versions.h, and Agent. 2018-10-06 21:31:32 +02:00
László Monda
dba61c6a42 Merge pull request #186 from UltimateHackingKeyboard/action-cache
Extend the behavior of keys upon layer changes to keymap changes
2018-10-06 20:56:06 +02:00
László Monda
f61acc483b Update ISSUE_TEMPLATE 2018-10-06 20:26:47 +02:00
László Monda
fb38e4099b Update ISSUE_TEMPLATE 2018-10-06 20:03:51 +02:00
László Monda
5fe19abe06 Merge branch 'master' into action-cache 2018-10-06 19:44:08 +02:00
Eric Tang
06e34fdcbc Convert the layer cache to an action cache 2018-10-06 10:02:46 -05:00
Eric Tang
cc6666b96d Don't suppress keys upon keymap changes 2018-10-06 10:02:23 -05:00
László Monda
a22dfdd917 Update version to 8.5.1, changelog, package.json and versions.h 2018-10-04 23:10:58 +02:00
László Monda
8b69a25dda Reset UsbReportUpdateSemaphore if it gets stuck for 100ms. This should fix occasional freezes. 2018-10-04 23:04:13 +02:00
László Monda
6f2b45c27c Update changelog, package.json, versions.h and Agent reference. 2018-10-04 22:46:01 +02:00
László Monda
98f7d512de Extract CurrentTime and remove Timer_{Get,Set}CurrentTime() 2018-10-04 20:38:36 +02:00
László Monda
c5cf738fd0 Expose UsbReportUpdateSemaphore via UsbCommand_{Get,Set}Variable() 2018-10-04 19:23:38 +02:00
László Monda
af31ae210a Move the pointer not by 1 but by 5 pixels when testing the USB stack to make the pointer easier to see. 2018-09-26 16:34:01 +02:00
László Monda
44799995b9 Update default issue text to include Karabiner Elements. 2018-09-26 00:03:20 +02:00
László Monda
3f5f83a19b Add issue template. 2018-09-25 23:55:56 +02:00
László Monda
bc4f35e578 Delete issue template. 2018-09-25 23:55:26 +02:00
László Monda
e9309aab16 Add issue template regarding Karabiner Elements 2018-09-25 23:52:09 +02:00
László Monda
f004b84399 Merge pull request #175 from UltimateHackingKeyboard/macro-engine
Use the correct scancode so that commas are outputted
2018-09-19 14:22:01 +02:00
Eric Tang
58f8120611 Use the correct scancode so that commas are outputted 2018-09-18 23:10:08 -05:00
László Monda
5b71fb7aaa Merge pull request #168 from UltimateHackingKeyboard/primary-role-modifiers
Send primary role modifiers consistently
2018-09-03 08:38:08 +02:00
Eric Tang
9d0f41bf5e Send primary role modifiers consistently 2018-09-02 00:02:40 -05:00
László Monda
47a3a8ad80 Merge pull request #163 from UltimateHackingKeyboard/layer-deactivation
Only allow layer switcher keys to deactivate toggled layers
2018-08-26 20:47:10 +02:00
Eric Tang
b4908bf2ac Only allow layer switcher keys to deactivate toggled layers 2018-08-26 11:46:38 -05:00
Eric Tang
846342e851 Deactivate secondary roles when switching keymaps 2018-08-25 07:22:48 -05:00
László Monda
3196abe574 Bump firmware version to 8.4.5, update changelog, package.json and versions.h 2018-08-21 21:56:41 +02:00
László Monda
5f0bae1840 Merge branch 'layer-cache' 2018-08-21 16:11:07 +02:00
László Monda
c3a38c8b59 Split the point to point that features Agent installation and running the external tool. 2018-08-21 04:21:06 +02:00
László Monda
1f9d31cad4 Update build instructions. 2018-08-21 04:18:54 +02:00
László Monda
b89de6655e Upgrade to the latest MCUXpresso IDE. 2018-08-21 03:50:30 +02:00
Eric Tang
4a1b747197 Implement a layer cache 2018-08-19 11:28:28 -07:00
László Monda
eca87d2f62 Merge pull request #159 from UltimateHackingKeyboard/suppress-keys
Suppress pressed keys when the layer or keymap changes
2018-08-19 05:00:10 +02:00
Eric Tang
2e2b9d08a9 Suppress pressed keys when the layer or keymap changes 2018-08-18 19:52:07 -07:00
László Monda
b4c2204e50 Bump firmware version to 8.4.4, update changelog, package.json and versions.h 2018-08-14 00:07:21 +02:00
László Monda
4c0546de6c Merge branch 'master' of github.com:UltimateHackingKeyboard/firmware 2018-08-13 23:08:53 +02:00
László Monda
bea4c34a51 Merge pull request #154 from UltimateHackingKeyboard/secondary-role
Ensure that secondary roles are triggered consistently
2018-08-13 23:03:48 +02:00
László Monda
bdc6232780 Merge branch 'master' of github.com:UltimateHackingKeyboard/firmware 2018-08-13 22:38:41 +02:00
László Monda
1d2d1c5049 Merge pull request #153 from UltimateHackingKeyboard/wake
Don't wake the host if a key is held down through the beginning of sleep
2018-08-13 21:42:46 +02:00
Eric Tang
67f07abd0d Ensure that secondary roles are triggered consistently 2018-08-13 12:30:36 -07:00
Eric Tang
4bfcd6e02c Don't wake the host if a key is held down through the beginning of sleep 2018-08-13 12:07:08 -07:00
László Monda
7eb190489b Bump firmware version to 8.4.3, update changelog, package.json, versions.h 2018-08-12 10:41:43 +02:00
László Monda
640c034111 Compensate "double tap to lock layer" timeouts for the timer fix to make them as long as before 8.3.3 2018-08-11 01:53:45 +02:00
László Monda
a6f12848ed Add timer related changelog entry. 2018-08-11 01:48:44 +02:00
László Monda
47f6a27e48 Move left/src/init_clock.[ch] to shared/slave 2018-08-06 00:16:26 +02:00
László Monda
9cc383a91d Delete config.h 2018-08-05 22:49:31 +02:00
László Monda
a441cdf5d2 Delete debug_over_spi.[ch] 2018-08-05 22:47:55 +02:00
László Monda
8297dd5c48 Don't include the debug over SPI code from any file. 2018-08-05 22:44:11 +02:00
László Monda
225a481938 Fix coding style. 2018-08-05 22:31:48 +02:00
László Monda
5572952dc8 Use one liner comment style. 2018-08-05 22:28:30 +02:00
László Monda
7d011237f8 Always use the I2C watchdog for the left half. Remove I2C_WATCHDOG and relevant preprocessor stuff. 2018-08-05 22:24:34 +02:00
László Monda
1a47c6e629 Minor MCUXpresso .cproject file modification. 2018-08-05 22:22:21 +02:00
László Monda
047a232e7e Update .cproject file to make MCUXpresso IDE not pop up the warning regarding SDK version. 2018-08-04 23:48:11 +02:00
László Monda
28f5999cbb Bump firmware version to 8.4.2, update changelog and versions.h 2018-08-02 13:00:31 +02:00
László Monda
fe7505a2df Merge branch 'master' of github.com:UltimateHackingKeyboard/firmware 2018-08-02 12:51:22 +02:00
László Monda
b6ac16074c Merge pull request #149 from UltimateHackingKeyboard/secondary-role
Fix various secondary role bugs
2018-08-02 03:41:25 +02:00
Eric Tang
0bf205c5d2 Keep sticky modifiers active when modifier-only keys are pressed 2018-08-01 18:12:12 -07:00
Eric Tang
e4a99a9400 Make sticky modifiers work consistently 2018-08-01 16:36:29 -07:00
Eric Tang
1e9b5833eb Correctly handle keypresses which triggers a secondary role 2018-08-01 15:53:55 -07:00
Eric Tang
79b052fca7 Remove redundant conditions 2018-07-31 16:12:51 -07:00
László Monda
baee0b5682 Bump firmware version to 8.4.1, update changelog, package.json, versions.h 2018-07-31 23:57:33 +02:00
László Monda
6153d54f59 Merge pull request #144 from UltimateHackingKeyboard/sleep-wake
Make some improvements to the sleep/wake code
2018-07-26 22:47:40 +02:00
Eric Tang
0a6ebe2903 Remove the old code for detecting new keypresses 2018-07-25 15:16:15 -07:00
László Monda
1fbbeb0f33 Bump firmware version to 8.4.0, update changelog, package.json, versions.h 2018-07-24 15:30:18 +02:00
László Monda
456f0e9e58 Merge branch 'master' of github.com:UltimateHackingKeyboard/firmware 2018-07-24 14:50:53 +02:00
László Monda
0248a0e79f Set debounce press and release time to 50ms by default. 2018-07-24 14:50:16 +02:00
Eric Tang
0e5ec29433 Tweak the logic of the USB stack test 2018-07-22 21:22:48 -07:00
Eric Tang
2d7cd68459 Make some improvements to the sleep/wake code 2018-07-22 13:13:29 -07:00
László Monda
5ac10fabcb Add back simulateKeypresses. 2018-07-22 16:24:05 +02:00
László Monda
b11017609d Merge pull request #143 from UltimateHackingKeyboard/usb-variables
Expose variables via USB
2018-07-22 16:04:55 +02:00
Eric Tang
c3a5d258e5 Rename the test mode for clarity 2018-07-20 17:31:00 -07:00
Eric Tang
a2866feb77 Temporarily allow the USB stack test to be activated through USB 2018-07-20 17:23:44 -07:00
Eric Tang
8c50192d6c Introduce a new way of activating the test mode 2018-07-20 17:17:59 -07:00
Eric Tang
63d82d92db Expose variables via USB 2018-07-20 17:17:30 -07:00
László Monda
1bced1be13 Merge branch 'debounce-configuration' 2018-07-16 18:24:38 +02:00
Eric Tang
86196d438c Add a test mode 2018-07-05 20:15:33 -07:00
Eric Tang
d722b3d173 Make debounce times configurable on the fly 2018-07-05 14:41:19 -07:00
Eric Tang
2ef5c49090 Merge branch 'interrupt-removal' 2018-07-05 14:34:33 -07:00
Eric Tang
5a137392ee Remove the key scanning interrupt 2018-07-05 12:43:38 -07:00
Eric Tang
27d12ea31f Remove the debouncing interrupt 2018-07-05 12:33:55 -07:00
Eric Tang
9ba09ec8eb Convert key_state_t to a bit field 2018-07-05 11:50:13 -07:00
47 changed files with 540 additions and 453 deletions

View File

@@ -5,11 +5,83 @@ 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.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
- Fix various bugs related to secondary role handling and sticky modifier states.
## [8.4.1] - 2018-07-31
Device Protocol: 4.4.0 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0
- Make some improvements to the sleep/wake code.
## [8.4.0] - 2018-07-24
Device Protocol: 4.**4.0** | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0
- Rewrite the key debouncer and set the press and release timeouts to 50ms.
- Add hardcoded test keymap.
- Make debounce timeouts configurable via USB. `DEVICEPROTOCOL:MINOR`
- Make the hardcoded test keymap able to trigger via USB. `DEVICEPROTOCOL:MINOR`
- Allow the USB stack test mode to be activated via USB. `DEVICEPROTOCOL:MINOR`
## [8.3.3] - 2018-07-03 ## [8.3.3] - 2018-07-03
Device Protocol: 4.3.1 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0 Device Protocol: 4.3.1 | Module Protocol: 4.0.0 | User Config: 4.1.0 | Hardware Config: 1.0.0
- Implement the macro engine. - Implement the macro engine.
- Fix the timer which makes it tick twice as fast as before.
- Fix the nondeterministic bug that made USB hang. - 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 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. - Restore debouncing to 100ms until it gets really fixed.

8
ISSUE_TEMPLATE Normal file
View File

@@ -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.

View File

@@ -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

View File

@@ -44,7 +44,8 @@ SOURCE = $(wildcard src/*.c) \
../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_lptmr.c \ ../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_lptmr.c \
../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_spi.c \ ../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_spi.c \
../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_tpm.c \ ../lib/KSDK_2.0_MKL03Z8xxx4/devices/MKL03Z4/drivers/fsl_tpm.c \
$(wildcard ../shared/*.c) $(wildcard ../shared/*.c) \
$(wildcard ../shared/slave/*.c)
# Header files. # Header files.
IPATH = src \ IPATH = src \

View File

@@ -1,13 +0,0 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
// Macros:
#define I2C_WATCHDOG_VALUE_REINIT 1
#define I2C_WATCHDOG_VALUE_REBOOT 2
// #define DEBUG_OVER_SPI
#define I2C_WATCHDOG I2C_WATCHDOG_VALUE_REINIT
// #define I2C_WATCHDOG I2C_WATCHDOG_VALUE_REBOOT
#endif

View File

@@ -1,56 +0,0 @@
#ifdef DEBUG_OVER_SPI
#include "debug_over_spi.h"
#include "config.h"
#include "fsl_gpio.h"
#define EXAMPLE_SPI_MASTER (SPI0)
#define EXAMPLE_SPI_MASTER_SOURCE_CLOCK (kCLOCK_BusClk)
#define BUFFER_SIZE (64)
static uint8_t srcBuff[BUFFER_SIZE];
static spi_transfer_t xfer = {0};
static spi_master_config_t userConfig;
spi_master_handle_t handle;
static volatile bool masterFinished = true;
static void masterCallback(SPI_Type *base, spi_master_handle_t *masterHandle, status_t status, void *userData)
{
masterFinished = true;
}
void DebugOverSpi_Init(void)
{
CLOCK_EnableClock(DEBUG_OVER_SPI_MOSI_CLOCK);
CLOCK_EnableClock(DEBUG_OVER_SPI_SCK_CLOCK);
PORT_SetPinMux(DEBUG_OVER_SPI_MOSI_PORT, DEBUG_OVER_SPI_MOSI_PIN, kPORT_MuxAlt3);
PORT_SetPinMux(DEBUG_OVER_SPI_SCK_PORT, DEBUG_OVER_SPI_SCK_PIN, kPORT_MuxAlt3);
GPIO_PinInit(DEBUG_OVER_SPI_MOSI_GPIO, DEBUG_OVER_SPI_MOSI_PIN, &(gpio_pin_config_t){kGPIO_DigitalOutput, 0});
GPIO_PinInit(DEBUG_OVER_SPI_SCK_GPIO, DEBUG_OVER_SPI_SCK_PIN, &(gpio_pin_config_t){kGPIO_DigitalOutput, 0});
GPIO_SetPinsOutput(DEBUG_OVER_SPI_MOSI_GPIO, 1U << DEBUG_OVER_SPI_MOSI_PIN);
GPIO_SetPinsOutput(DEBUG_OVER_SPI_SCK_GPIO, 1U << DEBUG_OVER_SPI_SCK_PIN);
SPI_MasterGetDefaultConfig(&userConfig);
uint32_t srcFreq = CLOCK_GetFreq(EXAMPLE_SPI_MASTER_SOURCE_CLOCK);
SPI_MasterInit(EXAMPLE_SPI_MASTER, &userConfig, srcFreq);
SPI_MasterTransferCreateHandle(EXAMPLE_SPI_MASTER, &handle, masterCallback, NULL);
}
void DebugOverSpi_Send(uint8_t *tx, uint8_t len)
{
if (masterFinished) {
masterFinished = false;
memcpy(srcBuff, tx, MIN(BUFFER_SIZE, len));
xfer.txData = srcBuff;
xfer.dataSize = len;
SPI_MasterTransferNonBlocking(EXAMPLE_SPI_MASTER, &handle, &xfer);
}
}
#endif

View File

@@ -1,34 +0,0 @@
#ifdef DEBUG_OVER_SPI
#ifndef __DEBUG_OVER_SPI_H__
#define __DEBUG_OVER_SPI_H__
// Includes:
#include "fsl_common.h"
#include "fsl_port.h"
#include "fsl_spi.h"
// Macros:
#define DEBUG_OVER_SPI_MOSI_PORT PORTA
#define DEBUG_OVER_SPI_MOSI_GPIO GPIOA
#define DEBUG_OVER_SPI_MOSI_CLOCK kCLOCK_PortA
#define DEBUG_OVER_SPI_MOSI_PIN 7
#define DEBUG_OVER_SPI_SCK_PORT PORTB
#define DEBUG_OVER_SPI_SCK_GPIO GPIOB
#define DEBUG_OVER_SPI_SCK_CLOCK kCLOCK_PortB
#define DEBUG_OVER_SPI_SCK_PIN 0
// Functions:
void DebugOverSpi_Init(void);
void DebugOverSpi_Send(uint8_t *tx, uint8_t len);
#endif
#else
#define DebugOverSpi_Init()
#define DebugOverSpi_Send(tx, len)
#endif

View File

@@ -3,40 +3,31 @@
#include "i2c_watchdog.h" #include "i2c_watchdog.h"
#include "test_led.h" #include "test_led.h"
#include "init_peripherals.h" #include "init_peripherals.h"
#include "config.h"
/* NOTE: Because of a bug in the ROM bootloader of the KL03Z, the watchdog timer is disabled and cannot be re-enabled. // NOTE: Because of a bug in the ROM bootloader of the KL03Z, the watchdog timer is disabled and cannot be re-enabled.
* See https://community.nxp.com/thread/457893 // See https://community.nxp.com/thread/457893
* Therefore the hardware watchdog timer cannot be used without an extra way to enter bootloader or application mode. // Therefore the hardware watchdog timer cannot be used without an extra way to enter bootloader or application mode.
*/ static uint32_t prevWatchdogCounter = 0;
#ifdef I2C_WATCHDOG static uint32_t I2cWatchdog_RecoveryCounter; // Counter for how many times we had to recover and restart
static uint32_t prevWatchdogCounter = 0;
static uint32_t I2cWatchdog_RecoveryCounter; /* counter for how many times we had to recover and restart */
void RunWatchdog(void) void RunWatchdog(void)
{ {
static volatile uint32_t I2cWatchdog_WatchCounter = 0; /* counter for timer */ static volatile uint32_t I2cWatchdog_WatchCounter = 0; // Counter for timer
static int cntr = 0; static int counter = 0;
cntr++; counter++;
if (cntr==100) { /* we get called from KEY_SCANNER_HANDLER() which runs at 1ms, thus scaling down by 100 here to get 100 ms period */ if (counter == 100) { // We get called from KEY_SCANNER_HANDLER() which runs at 1ms, thus scaling down by 100 here to get 100 ms period
cntr=0; counter=0;
TestLed_Toggle(); TestLed_Toggle();
I2cWatchdog_WatchCounter++; I2cWatchdog_WatchCounter++;
if (I2cWatchdog_WatchCounter>10) { /* do not check within the first 1000 ms, as I2C might not be running yet */ if (I2cWatchdog_WatchCounter > 10) { // Do not check within the first 1000 ms, as I2C might not be running yet
if (I2C_Watchdog == prevWatchdogCounter) { // Restart I2C if there hasn't been any interrupt during 100 ms. I2C_Watchdog gets incremented for every I2C transaction if (I2C_Watchdog == prevWatchdogCounter) { // Restart I2C if there hasn't been any interrupt during 100 ms. I2C_Watchdog gets incremented for every I2C transaction
I2cWatchdog_RecoveryCounter++; I2cWatchdog_RecoveryCounter++;
#if I2C_WATCHDOG == I2C_WATCHDOG_VALUE_REBOOT
NVIC_SystemReset();
#endif
#if I2C_WATCHDOG == I2C_WATCHDOG_VALUE_REINIT
I2C_SlaveDeinit(I2C_BUS_BASEADDR); I2C_SlaveDeinit(I2C_BUS_BASEADDR);
initI2c(); initI2c();
#endif
} }
} }
prevWatchdogCounter = I2C_Watchdog; /* remember previous counter */ prevWatchdogCounter = I2C_Watchdog;
} }
} }
#endif

View File

@@ -9,7 +9,6 @@
#include "led_pwm.h" #include "led_pwm.h"
#include "slave_protocol_handler.h" #include "slave_protocol_handler.h"
#include "i2c_watchdog.h" #include "i2c_watchdog.h"
#include "debug_over_spi.h"
#include "main.h" #include "main.h"
i2c_slave_config_t slaveConfig; i2c_slave_config_t slaveConfig;
@@ -23,7 +22,6 @@ static void i2cSlaveCallback(I2C_Type *base, i2c_slave_transfer_t *xfer, void *u
{ {
dosBuffer[0] = xfer->event; dosBuffer[0] = xfer->event;
dosBuffer[1] = userData; dosBuffer[1] = userData;
DebugOverSpi_Send(dosBuffer, 2);
switch (xfer->event) { switch (xfer->event) {
case kI2C_SlaveTransmitEvent: case kI2C_SlaveTransmitEvent:
@@ -86,6 +84,5 @@ void InitPeripherals(void)
InitLedDriver(); InitLedDriver();
TestLed_Init(); TestLed_Init();
LedPwm_Init(); LedPwm_Init();
DebugOverSpi_Init();
initI2c(); initI2c();
} }

View File

@@ -1,14 +1,11 @@
#include "fsl_lptmr.h" #include "fsl_lptmr.h"
#include "key_scanner.h" #include "key_scanner.h"
#include "config.h"
#include "i2c_watchdog.h" #include "i2c_watchdog.h"
void KEY_SCANNER_HANDLER(void) void KEY_SCANNER_HANDLER(void)
{ {
KeyMatrix_ScanRow(&keyMatrix); KeyMatrix_ScanRow(&keyMatrix);
#ifdef I2C_WATCHDOG
RunWatchdog(); RunWatchdog();
#endif
LPTMR_ClearStatusFlags(KEY_SCANNER_LPTMR_BASEADDR, kLPTMR_TimerCompareFlag); LPTMR_ClearStatusFlags(KEY_SCANNER_LPTMR_BASEADDR, kLPTMR_TimerCompareFlag);
} }

View File

@@ -1,9 +1,8 @@
#include "main.h" #include "main.h"
#include "init_clock.h" #include "slave/init_clock.h"
#include "init_peripherals.h" #include "init_peripherals.h"
#include "bootloader.h" #include "bootloader.h"
#include <stdio.h> #include <stdio.h>
#include "config.h"
#include "key_scanner.h" #include "key_scanner.h"
DEFINE_BOOTLOADER_CONFIG_AREA(I2C_ADDRESS_LEFT_KEYBOARD_HALF_BOOTLOADER) DEFINE_BOOTLOADER_CONFIG_AREA(I2C_ADDRESS_LEFT_KEYBOARD_HALF_BOOTLOADER)
@@ -15,11 +14,7 @@ key_matrix_t keyMatrix = {
{PORTB, GPIOB, kCLOCK_PortB, 11}, {PORTB, GPIOB, kCLOCK_PortB, 11},
{PORTA, GPIOA, kCLOCK_PortA, 6}, {PORTA, GPIOA, kCLOCK_PortA, 6},
{PORTA, GPIOA, kCLOCK_PortA, 8}, {PORTA, GPIOA, kCLOCK_PortA, 8},
#ifdef DEBUG_OVER_SPI
{PORTA, GPIOA, kCLOCK_PortA, 8},
#else
{PORTB, GPIOB, kCLOCK_PortB, 0}, {PORTB, GPIOB, kCLOCK_PortB, 0},
#endif
{PORTB, GPIOB, kCLOCK_PortB, 6}, {PORTB, GPIOB, kCLOCK_PortB, 6},
{PORTA, GPIOA, kCLOCK_PortA, 3}, {PORTA, GPIOA, kCLOCK_PortA, 3},
{PORTA, GPIOA, kCLOCK_PortA, 12} {PORTA, GPIOA, kCLOCK_PortA, 12}
@@ -28,11 +23,7 @@ key_matrix_t keyMatrix = {
{PORTB, GPIOB, kCLOCK_PortB, 7}, {PORTB, GPIOB, kCLOCK_PortB, 7},
{PORTB, GPIOB, kCLOCK_PortB, 10}, {PORTB, GPIOB, kCLOCK_PortB, 10},
{PORTA, GPIOA, kCLOCK_PortA, 5}, {PORTA, GPIOA, kCLOCK_PortA, 5},
#ifdef DEBUG_OVER_SPI
{PORTA, GPIOA, kCLOCK_PortA, 5},
#else
{PORTA, GPIOA, kCLOCK_PortA, 7}, {PORTA, GPIOA, kCLOCK_PortA, 7},
#endif
{PORTA, GPIOA, kCLOCK_PortA, 4} {PORTA, GPIOA, kCLOCK_PortA, 4}
} }
}; };

View File

@@ -460,73 +460,73 @@
<storageModule moduleId="com.crt.config"> <storageModule moduleId="com.crt.config">
<projectStorage>&lt;?xml version="1.0" encoding="UTF-8"?&gt; <projectStorage>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;TargetConfig&gt; &lt;TargetConfig&gt;
&lt;Properties property_3="NXP" property_4="MK22FN512xxx12" property_count="5" version="70200"/&gt; &lt;Properties property_3="NXP" property_4="MK22FN512xxx12" property_count="5" version="100200"/&gt;
&lt;infoList vendor="NXP"&gt;&lt;info chip="MK22FN512xxx12" name="MK22FN512xxx12"&gt;&lt;chip&gt;&lt;name&gt;MK22FN512xxx12&lt;/name&gt; &lt;infoList vendor="NXP"&gt;&lt;info chip="MK22FN512xxx12" name="MK22FN512xxx12"&gt;&lt;chip&gt;&lt;name&gt;MK22FN512xxx12&lt;/name&gt;
&lt;family&gt;K2x&lt;/family&gt; &lt;family&gt;K2x&lt;/family&gt;
&lt;vendor&gt;NXP&lt;/vendor&gt; &lt;vendor&gt;NXP&lt;/vendor&gt;
&lt;memory can_program="true" id="Flash" is_ro="true" size="512" type="Flash"/&gt; &lt;memory can_program="true" id="Flash" is_ro="true" size="0" type="Flash"/&gt;
&lt;memory id="RAM" size="128" type="RAM"/&gt; &lt;memory id="RAM" size="0" type="RAM"/&gt;
&lt;memoryInstance derived_from="Flash" driver="FTFA_2K.cfx" id="PROGRAM_FLASH" location="0x0" size="0x80000"/&gt; &lt;memoryInstance derived_from="Flash" driver="FTFA_2K.cfx" id="PROGRAM_FLASH" location="0x00000000" size="0x00080000"/&gt;
&lt;memoryInstance derived_from="RAM" id="SRAM_UPPER" location="0x20000000" size="0x10000"/&gt; &lt;memoryInstance derived_from="RAM" id="SRAM_UPPER" location="0x20000000" size="0x00010000"/&gt;
&lt;memoryInstance derived_from="RAM" id="SRAM_LOWER" location="0x1fff0000" size="0x10000"/&gt; &lt;memoryInstance derived_from="RAM" id="SRAM_LOWER" location="0x1fff0000" size="0x00010000"/&gt;
&lt;peripheralInstance derived_from="FTFA_FlashConfig" id="FTFA_FlashConfig" location="0x400"/&gt; &lt;peripheralInstance derived_from="FTFA-FlashConfig" determined="infoFile" id="FTFA-FlashConfig" location="0x400"/&gt;
&lt;peripheralInstance derived_from="DMA" id="DMA" location="0x40008000"/&gt; &lt;peripheralInstance derived_from="DMA" determined="infoFile" id="DMA" location="0x40008000"/&gt;
&lt;peripheralInstance derived_from="FB" id="FB" location="0x4000C000"/&gt; &lt;peripheralInstance derived_from="FB" determined="infoFile" id="FB" location="0x4000C000"/&gt;
&lt;peripheralInstance derived_from="FMC" id="FMC" location="0x4001F000"/&gt; &lt;peripheralInstance derived_from="FMC" determined="infoFile" id="FMC" location="0x4001F000"/&gt;
&lt;peripheralInstance derived_from="FTFA" id="FTFA" location="0x40020000"/&gt; &lt;peripheralInstance derived_from="FTFA" determined="infoFile" id="FTFA" location="0x40020000"/&gt;
&lt;peripheralInstance derived_from="DMAMUX" id="DMAMUX" location="0x40021000"/&gt; &lt;peripheralInstance derived_from="DMAMUX" determined="infoFile" id="DMAMUX" location="0x40021000"/&gt;
&lt;peripheralInstance derived_from="FTM0" id="FTM0" location="0x40038000"/&gt; &lt;peripheralInstance derived_from="FTM0" determined="infoFile" id="FTM0" location="0x40038000"/&gt;
&lt;peripheralInstance derived_from="FTM1" id="FTM1" location="0x40039000"/&gt; &lt;peripheralInstance derived_from="FTM1" determined="infoFile" id="FTM1" location="0x40039000"/&gt;
&lt;peripheralInstance derived_from="FTM2" id="FTM2" location="0x4003A000"/&gt; &lt;peripheralInstance derived_from="FTM2" determined="infoFile" id="FTM2" location="0x4003A000"/&gt;
&lt;peripheralInstance derived_from="FTM3" id="FTM3" location="0x40026000"/&gt; &lt;peripheralInstance derived_from="FTM3" determined="infoFile" id="FTM3" location="0x40026000"/&gt;
&lt;peripheralInstance derived_from="ADC0" id="ADC0" location="0x4003B000"/&gt; &lt;peripheralInstance derived_from="ADC0" determined="infoFile" id="ADC0" location="0x4003B000"/&gt;
&lt;peripheralInstance derived_from="ADC1" id="ADC1" location="0x40027000"/&gt; &lt;peripheralInstance derived_from="ADC1" determined="infoFile" id="ADC1" location="0x40027000"/&gt;
&lt;peripheralInstance derived_from="DAC0" id="DAC0" location="0x4003F000"/&gt; &lt;peripheralInstance derived_from="DAC0" determined="infoFile" id="DAC0" location="0x4003F000"/&gt;
&lt;peripheralInstance derived_from="DAC1" id="DAC1" location="0x40028000"/&gt; &lt;peripheralInstance derived_from="DAC1" determined="infoFile" id="DAC1" location="0x40028000"/&gt;
&lt;peripheralInstance derived_from="RNG" id="RNG" location="0x40029000"/&gt; &lt;peripheralInstance derived_from="RNG" determined="infoFile" id="RNG" location="0x40029000"/&gt;
&lt;peripheralInstance derived_from="LPUART0" id="LPUART0" location="0x4002A000"/&gt; &lt;peripheralInstance derived_from="LPUART0" determined="infoFile" id="LPUART0" location="0x4002A000"/&gt;
&lt;peripheralInstance derived_from="SPI0" id="SPI0" location="0x4002C000"/&gt; &lt;peripheralInstance derived_from="SPI0" determined="infoFile" id="SPI0" location="0x4002C000"/&gt;
&lt;peripheralInstance derived_from="SPI1" id="SPI1" location="0x4002D000"/&gt; &lt;peripheralInstance derived_from="SPI1" determined="infoFile" id="SPI1" location="0x4002D000"/&gt;
&lt;peripheralInstance derived_from="I2S0" id="I2S0" location="0x4002F000"/&gt; &lt;peripheralInstance derived_from="I2S0" determined="infoFile" id="I2S0" location="0x4002F000"/&gt;
&lt;peripheralInstance derived_from="CRC" id="CRC" location="0x40032000"/&gt; &lt;peripheralInstance derived_from="CRC" determined="infoFile" id="CRC" location="0x40032000"/&gt;
&lt;peripheralInstance derived_from="PDB0" id="PDB0" location="0x40036000"/&gt; &lt;peripheralInstance derived_from="PDB0" determined="infoFile" id="PDB0" location="0x40036000"/&gt;
&lt;peripheralInstance derived_from="PIT" id="PIT" location="0x40037000"/&gt; &lt;peripheralInstance derived_from="PIT" determined="infoFile" id="PIT" location="0x40037000"/&gt;
&lt;peripheralInstance derived_from="RTC" id="RTC" location="0x4003D000"/&gt; &lt;peripheralInstance derived_from="RTC" determined="infoFile" id="RTC" location="0x4003D000"/&gt;
&lt;peripheralInstance derived_from="RFVBAT" id="RFVBAT" location="0x4003E000"/&gt; &lt;peripheralInstance derived_from="RFVBAT" determined="infoFile" id="RFVBAT" location="0x4003E000"/&gt;
&lt;peripheralInstance derived_from="LPTMR0" id="LPTMR0" location="0x40040000"/&gt; &lt;peripheralInstance derived_from="LPTMR0" determined="infoFile" id="LPTMR0" location="0x40040000"/&gt;
&lt;peripheralInstance derived_from="RFSYS" id="RFSYS" location="0x40041000"/&gt; &lt;peripheralInstance derived_from="RFSYS" determined="infoFile" id="RFSYS" location="0x40041000"/&gt;
&lt;peripheralInstance derived_from="SIM" id="SIM" location="0x40047000"/&gt; &lt;peripheralInstance derived_from="SIM" determined="infoFile" id="SIM" location="0x40047000"/&gt;
&lt;peripheralInstance derived_from="PORTA" id="PORTA" location="0x40049000"/&gt; &lt;peripheralInstance derived_from="PORTA" determined="infoFile" id="PORTA" location="0x40049000"/&gt;
&lt;peripheralInstance derived_from="PORTB" id="PORTB" location="0x4004A000"/&gt; &lt;peripheralInstance derived_from="PORTB" determined="infoFile" id="PORTB" location="0x4004A000"/&gt;
&lt;peripheralInstance derived_from="PORTC" id="PORTC" location="0x4004B000"/&gt; &lt;peripheralInstance derived_from="PORTC" determined="infoFile" id="PORTC" location="0x4004B000"/&gt;
&lt;peripheralInstance derived_from="PORTD" id="PORTD" location="0x4004C000"/&gt; &lt;peripheralInstance derived_from="PORTD" determined="infoFile" id="PORTD" location="0x4004C000"/&gt;
&lt;peripheralInstance derived_from="PORTE" id="PORTE" location="0x4004D000"/&gt; &lt;peripheralInstance derived_from="PORTE" determined="infoFile" id="PORTE" location="0x4004D000"/&gt;
&lt;peripheralInstance derived_from="WDOG" id="WDOG" location="0x40052000"/&gt; &lt;peripheralInstance derived_from="WDOG" determined="infoFile" id="WDOG" location="0x40052000"/&gt;
&lt;peripheralInstance derived_from="EWM" id="EWM" location="0x40061000"/&gt; &lt;peripheralInstance derived_from="EWM" determined="infoFile" id="EWM" location="0x40061000"/&gt;
&lt;peripheralInstance derived_from="MCG" id="MCG" location="0x40064000"/&gt; &lt;peripheralInstance derived_from="MCG" determined="infoFile" id="MCG" location="0x40064000"/&gt;
&lt;peripheralInstance derived_from="OSC" id="OSC" location="0x40065000"/&gt; &lt;peripheralInstance derived_from="OSC" determined="infoFile" id="OSC" location="0x40065000"/&gt;
&lt;peripheralInstance derived_from="I2C0" id="I2C0" location="0x40066000"/&gt; &lt;peripheralInstance derived_from="I2C0" determined="infoFile" id="I2C0" location="0x40066000"/&gt;
&lt;peripheralInstance derived_from="I2C1" id="I2C1" location="0x40067000"/&gt; &lt;peripheralInstance derived_from="I2C1" determined="infoFile" id="I2C1" location="0x40067000"/&gt;
&lt;peripheralInstance derived_from="UART0" id="UART0" location="0x4006A000"/&gt; &lt;peripheralInstance derived_from="UART0" determined="infoFile" id="UART0" location="0x4006A000"/&gt;
&lt;peripheralInstance derived_from="UART1" id="UART1" location="0x4006B000"/&gt; &lt;peripheralInstance derived_from="UART1" determined="infoFile" id="UART1" location="0x4006B000"/&gt;
&lt;peripheralInstance derived_from="UART2" id="UART2" location="0x4006C000"/&gt; &lt;peripheralInstance derived_from="UART2" determined="infoFile" id="UART2" location="0x4006C000"/&gt;
&lt;peripheralInstance derived_from="USB0" id="USB0" location="0x40072000"/&gt; &lt;peripheralInstance derived_from="USB0" determined="infoFile" id="USB0" location="0x40072000"/&gt;
&lt;peripheralInstance derived_from="CMP0" id="CMP0" location="0x40073000"/&gt; &lt;peripheralInstance derived_from="CMP0" determined="infoFile" id="CMP0" location="0x40073000"/&gt;
&lt;peripheralInstance derived_from="CMP1" id="CMP1" location="0x40073008"/&gt; &lt;peripheralInstance derived_from="CMP1" determined="infoFile" id="CMP1" location="0x40073008"/&gt;
&lt;peripheralInstance derived_from="VREF" id="VREF" location="0x40074000"/&gt; &lt;peripheralInstance derived_from="VREF" determined="infoFile" id="VREF" location="0x40074000"/&gt;
&lt;peripheralInstance derived_from="LLWU" id="LLWU" location="0x4007C000"/&gt; &lt;peripheralInstance derived_from="LLWU" determined="infoFile" id="LLWU" location="0x4007C000"/&gt;
&lt;peripheralInstance derived_from="PMC" id="PMC" location="0x4007D000"/&gt; &lt;peripheralInstance derived_from="PMC" determined="infoFile" id="PMC" location="0x4007D000"/&gt;
&lt;peripheralInstance derived_from="SMC" id="SMC" location="0x4007E000"/&gt; &lt;peripheralInstance derived_from="SMC" determined="infoFile" id="SMC" location="0x4007E000"/&gt;
&lt;peripheralInstance derived_from="RCM" id="RCM" location="0x4007F000"/&gt; &lt;peripheralInstance derived_from="RCM" determined="infoFile" id="RCM" location="0x4007F000"/&gt;
&lt;peripheralInstance derived_from="GPIOA" id="GPIOA" location="0x400FF000"/&gt; &lt;peripheralInstance derived_from="GPIOA" determined="infoFile" id="GPIOA" location="0x400FF000"/&gt;
&lt;peripheralInstance derived_from="GPIOB" id="GPIOB" location="0x400FF040"/&gt; &lt;peripheralInstance derived_from="GPIOB" determined="infoFile" id="GPIOB" location="0x400FF040"/&gt;
&lt;peripheralInstance derived_from="GPIOC" id="GPIOC" location="0x400FF080"/&gt; &lt;peripheralInstance derived_from="GPIOC" determined="infoFile" id="GPIOC" location="0x400FF080"/&gt;
&lt;peripheralInstance derived_from="GPIOD" id="GPIOD" location="0x400FF0C0"/&gt; &lt;peripheralInstance derived_from="GPIOD" determined="infoFile" id="GPIOD" location="0x400FF0C0"/&gt;
&lt;peripheralInstance derived_from="GPIOE" id="GPIOE" location="0x400FF100"/&gt; &lt;peripheralInstance derived_from="GPIOE" determined="infoFile" id="GPIOE" location="0x400FF100"/&gt;
&lt;peripheralInstance derived_from="SystemControl" id="SystemControl" location="0xE000E000"/&gt; &lt;peripheralInstance derived_from="SystemControl" determined="infoFile" id="SystemControl" location="0xE000E000"/&gt;
&lt;peripheralInstance derived_from="SysTick" id="SysTick" location="0xE000E010"/&gt; &lt;peripheralInstance derived_from="SysTick" determined="infoFile" id="SysTick" location="0xE000E010"/&gt;
&lt;peripheralInstance derived_from="NVIC" id="NVIC" location="0xE000E100"/&gt; &lt;peripheralInstance derived_from="NVIC" determined="infoFile" id="NVIC" location="0xE000E100"/&gt;
&lt;peripheralInstance derived_from="MCM" id="MCM" location="0xE0080000"/&gt; &lt;peripheralInstance derived_from="MCM" determined="infoFile" id="MCM" location="0xE0080000"/&gt;
&lt;/chip&gt; &lt;/chip&gt;
&lt;processor&gt;&lt;name gcc_name="cortex-m4"&gt;Cortex-M4&lt;/name&gt; &lt;processor&gt;&lt;name gcc_name="cortex-m4"&gt;Cortex-M4&lt;/name&gt;
&lt;family&gt;Cortex-M&lt;/family&gt; &lt;family&gt;Cortex-M&lt;/family&gt;
@@ -538,6 +538,6 @@
</storageModule> </storageModule>
<storageModule moduleId="com.nxp.mcuxpresso.core.datamodels"> <storageModule moduleId="com.nxp.mcuxpresso.core.datamodels">
<sdkName>SDK_2.x_MK22FN512xxx12</sdkName> <sdkName>SDK_2.x_MK22FN512xxx12</sdkName>
<sdkVersion>2.3.1</sdkVersion> <sdkVersion>2.2.0</sdkVersion>
</storageModule> </storageModule>
</cproject> </cproject>

View File

@@ -12,7 +12,6 @@
#include "init_peripherals.h" #include "init_peripherals.h"
#include "eeprom.h" #include "eeprom.h"
#include "timer.h" #include "timer.h"
#include "key_debouncer.h"
#include "usb_api.h" #include "usb_api.h"
#include "slave_scheduler.h" #include "slave_scheduler.h"
#include "bootloader/wormhole.h" #include "bootloader/wormhole.h"
@@ -66,8 +65,6 @@ static void initInterruptPriorities(void)
NVIC_SetPriority(PIT_I2C_WATCHDOG_IRQ_ID, 1); NVIC_SetPriority(PIT_I2C_WATCHDOG_IRQ_ID, 1);
NVIC_SetPriority(I2C_EEPROM_BUS_IRQ_ID, 0); NVIC_SetPriority(I2C_EEPROM_BUS_IRQ_ID, 0);
NVIC_SetPriority(PIT_TIMER_IRQ_ID, 3); NVIC_SetPriority(PIT_TIMER_IRQ_ID, 3);
NVIC_SetPriority(PIT_KEY_SCANNER_IRQ_ID, 4);
NVIC_SetPriority(PIT_KEY_DEBOUNCER_IRQ_ID, 4);
NVIC_SetPriority(I2C_MAIN_BUS_IRQ_ID, 4); NVIC_SetPriority(I2C_MAIN_BUS_IRQ_ID, 4);
NVIC_SetPriority(USB_IRQ_ID, 4); NVIC_SetPriority(USB_IRQ_ID, 4);
} }
@@ -159,6 +156,5 @@ void InitPeripherals(void)
TestLed_Init(); TestLed_Init();
LedPwm_Init(); LedPwm_Init();
InitI2cWatchdog(); InitI2cWatchdog();
InitKeyDebouncer();
EEPROM_Init(); EEPROM_Init();
} }

View File

@@ -1,32 +0,0 @@
#include "key_debouncer.h"
#include "fsl_pit.h"
#include "slot.h"
#include "module.h"
#include "key_states.h"
#include "peripherals/test_led.h"
void PIT_KEY_DEBOUNCER_HANDLER(void)
{
TestLed_Toggle();
for (uint8_t slotId=0; slotId<SLOT_COUNT; slotId++) {
for (uint8_t keyId=0; keyId<MAX_KEY_COUNT_PER_MODULE; keyId++) {
uint8_t *debounceCounter = &KeyStates[slotId][keyId].debounceCounter;
if (*debounceCounter) {
--(*debounceCounter);
}
}
}
PIT_ClearStatusFlags(PIT, PIT_KEY_DEBOUNCER_CHANNEL, PIT_TFLG_TIF_MASK);
}
void InitKeyDebouncer(void)
{
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
PIT_Init(PIT, &pitConfig);
PIT_SetTimerPeriod(PIT, PIT_KEY_DEBOUNCER_CHANNEL, MSEC_TO_COUNT(KEY_DEBOUNCER_INTERVAL_MSEC, PIT_SOURCE_CLOCK));
PIT_EnableInterrupts(PIT, PIT_KEY_DEBOUNCER_CHANNEL, kPIT_TimerInterruptEnable);
EnableIRQ(PIT_KEY_DEBOUNCER_IRQ_ID);
PIT_StartTimer(PIT, PIT_KEY_DEBOUNCER_CHANNEL);
}

View File

@@ -1,18 +0,0 @@
#ifndef __KEY_DEBOUNCER_H__
#define __KEY_DEBOUNCER_H__
// Includes:
#include "peripherals/pit.h"
#include "fsl_common.h"
// Macros:
#define KEY_DEBOUNCER_INTERVAL_MSEC 1
#define KEY_DEBOUNCER_TIMEOUT_MSEC 100
// Functions:
void InitKeyDebouncer(void);
#endif

View File

@@ -1,22 +0,0 @@
#include "fsl_pit.h"
#include "key_scanner.h"
uint32_t KeyScannerCounter;
void PIT_KEY_SCANNER_HANDLER(void)
{
KeyMatrix_ScanRow(&RightKeyMatrix);
KeyScannerCounter++;
PIT_ClearStatusFlags(PIT, PIT_KEY_SCANNER_CHANNEL, PIT_TFLG_TIF_MASK);
}
void InitKeyScanner(void)
{
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
PIT_Init(PIT, &pitConfig);
PIT_SetTimerPeriod(PIT, PIT_KEY_SCANNER_CHANNEL, USEC_TO_COUNT(KEY_SCANNER_INTERVAL_USEC, PIT_SOURCE_CLOCK));
PIT_EnableInterrupts(PIT, PIT_KEY_SCANNER_CHANNEL, kPIT_TimerInterruptEnable);
EnableIRQ(PIT_KEY_SCANNER_IRQ_ID);
PIT_StartTimer(PIT, PIT_KEY_SCANNER_CHANNEL);
}

View File

@@ -1,21 +0,0 @@
#ifndef __KEY_SCANNER_H__
#define __KEY_SCANNER_H__
// Includes:
#include "peripherals/pit.h"
#include "right_key_matrix.h"
// Macros:
#define KEY_SCANNER_INTERVAL_USEC (1000 / RIGHT_KEY_MATRIX_ROWS_NUM)
// Variables:
extern uint32_t KeyScannerCounter;
// Functions:
void InitKeyScanner(void);
#endif

View File

@@ -10,10 +10,11 @@
// Typedefs: // Typedefs:
typedef struct { typedef struct {
bool previous; uint8_t timestamp;
bool current; bool previous : 1;
bool suppressed; bool current : 1;
uint8_t debounceCounter; bool suppressed : 1;
bool debouncing : 1;
} key_state_t; } key_state_t;
// Variables: // Variables:

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) { 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) {

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_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;

View File

@@ -6,7 +6,7 @@
#include "bus_pal_hardware.h" #include "bus_pal_hardware.h"
#include "command.h" #include "command.h"
#include "eeprom.h" #include "eeprom.h"
#include "key_scanner.h" #include "right_key_matrix.h"
#include "usb_commands/usb_command_apply_config.h" #include "usb_commands/usb_command_apply_config.h"
#include "peripherals/reset_button.h" #include "peripherals/reset_button.h"
#include "config_parser/config_globals.h" #include "config_parser/config_globals.h"
@@ -44,7 +44,6 @@ int main(void)
} else { } else {
InitSlaveScheduler(); InitSlaveScheduler();
KeyMatrix_Init(&RightKeyMatrix); KeyMatrix_Init(&RightKeyMatrix);
InitKeyScanner();
InitUsb(); InitUsb();
while (1) { while (1) {
@@ -52,6 +51,8 @@ int main(void)
UsbCommand_ApplyConfig(); UsbCommand_ApplyConfig();
IsConfigInitialized = true; IsConfigInitialized = true;
} }
KeyMatrix_ScanRow(&RightKeyMatrix);
++MatrixScanCounter;
UpdateUsbReports(); UpdateUsbReports();
__WFI(); __WFI();
} }

View File

@@ -17,12 +17,4 @@
#define PIT_TIMER_IRQ_ID PIT1_IRQn #define PIT_TIMER_IRQ_ID PIT1_IRQn
#define PIT_TIMER_CHANNEL kPIT_Chnl_1 #define PIT_TIMER_CHANNEL kPIT_Chnl_1
#define PIT_KEY_SCANNER_HANDLER PIT2_IRQHandler
#define PIT_KEY_SCANNER_IRQ_ID PIT2_IRQn
#define PIT_KEY_SCANNER_CHANNEL kPIT_Chnl_2
#define PIT_KEY_DEBOUNCER_HANDLER PIT3_IRQHandler
#define PIT_KEY_DEBOUNCER_IRQ_ID PIT3_IRQn
#define PIT_KEY_DEBOUNCER_CHANNEL kPIT_Chnl_3
#endif #endif

View File

@@ -1,5 +1,7 @@
#include "right_key_matrix.h" #include "right_key_matrix.h"
uint32_t MatrixScanCounter;
key_matrix_t RightKeyMatrix = { key_matrix_t RightKeyMatrix = {
.colNum = RIGHT_KEY_MATRIX_COLS_NUM, .colNum = RIGHT_KEY_MATRIX_COLS_NUM,
.rowNum = RIGHT_KEY_MATRIX_ROWS_NUM, .rowNum = RIGHT_KEY_MATRIX_ROWS_NUM,

View File

@@ -14,5 +14,6 @@
// Variables: // Variables:
extern key_matrix_t RightKeyMatrix; extern key_matrix_t RightKeyMatrix;
extern uint32_t MatrixScanCounter;
#endif #endif

113
right/src/test_switches.c Normal file
View File

@@ -0,0 +1,113 @@
#include "test_switches.h"
#include "led_display.h"
#include "key_action.h"
#include "keymap.h"
bool TestSwitches = false;
static const key_action_t TestKeymap[1][2][MAX_KEY_COUNT_PER_MODULE] = {
// Base layer
{
// Right keyboard half
{
// Row 1
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_7_AND_AMPERSAND } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_8_AND_ASTERISK } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_9_AND_OPENING_PARENTHESIS } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_MINUS_AND_UNDERSCORE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_EQUAL_AND_PLUS } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_BACKSPACE } },
// Row 2
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_U } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_I } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_O } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_P } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_OPENING_BRACKET_AND_OPENING_BRACE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_CLOSING_BRACKET_AND_CLOSING_BRACE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_BACKSLASH_AND_PIPE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_Y } },
// Row 3
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_J } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_K } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_L } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_SEMICOLON_AND_COLON } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_APOSTROPHE_AND_QUOTE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_PLUS } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_H } },
// Row 4
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_N } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_M } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_RIGHT_SHIFT } },
{ .type = KeyActionType_None },
// Row 5
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_6_AND_RIGHT_ARROW } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_ASTERISK } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_7_AND_HOME } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_8_AND_UP_ARROW } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_9_AND_PAGE_UP } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT } },
},
// Left keyboard half
{
// Row 1
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_GRAVE_ACCENT_AND_TILDE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_1_AND_EXCLAMATION } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_2_AND_AT } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_3_AND_HASHMARK } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_4_AND_DOLLAR } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_5_AND_PERCENTAGE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_6_AND_CARET } },
// Row 2
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_ESCAPE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_Q } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_W } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_E } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_R } },
{ .type = KeyActionType_None },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_T } },
// Row 3
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_MINUS } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_A } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_S } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_D } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_F } },
{ .type = KeyActionType_None },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_G } },
// Row 4
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_LEFT_SHIFT } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_NON_US_BACKSLASH_AND_PIPE } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_Z } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_X } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_C } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_V } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_B } },
// Row 5
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_1_AND_END } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_2_AND_DOWN_ARROW } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_3_AND_PAGE_DOWN } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_4_AND_LEFT_ARROW } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_SLASH } },
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_KEYPAD_5 } },
{ .type = KeyActionType_None },
}
}
};
void TestSwitches_Activate(void)
{
memcpy(&CurrentKeymap, &TestKeymap, sizeof TestKeymap);
LedDisplay_SetText(3, "TES");
}

16
right/src/test_switches.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef __TEST_MODE_H__
#define __TEST_MODE_H__
// Includes:
#include <stdbool.h>
// Functions:
void TestSwitches_Activate(void);
// Variables:
extern bool TestSwitches;
#endif

View File

@@ -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;
} }

View File

@@ -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);

View File

@@ -5,7 +5,7 @@
#include "i2c_watchdog.h" #include "i2c_watchdog.h"
#include "buffer.h" #include "buffer.h"
#include "timer.h" #include "timer.h"
#include "key_scanner.h" #include "right_key_matrix.h"
#include "usb_report_updater.h" #include "usb_report_updater.h"
#include "usb_interfaces/usb_interface_basic_keyboard.h" #include "usb_interfaces/usb_interface_basic_keyboard.h"
#include "usb_interfaces/usb_interface_media_keyboard.h" #include "usb_interfaces/usb_interface_media_keyboard.h"
@@ -20,9 +20,9 @@ void UsbCommand_GetDebugBuffer(void)
SetDebugBufferUint32(5, I2cSlaveScheduler_Counter); SetDebugBufferUint32(5, I2cSlaveScheduler_Counter);
SetDebugBufferUint32(9, I2cWatchdog_WatchCounter); SetDebugBufferUint32(9, I2cWatchdog_WatchCounter);
SetDebugBufferUint32(13, I2cWatchdog_RecoveryCounter); SetDebugBufferUint32(13, I2cWatchdog_RecoveryCounter);
SetDebugBufferUint32(17, KeyScannerCounter); 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);

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, Timer_GetCurrentTime()); SetUsbTxBufferUint32(1, CurrentTime);
break; break;
default: default:
SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty); SetUsbTxBufferUint8(0, UsbStatusCode_GetDeviceProperty_InvalidProperty);

View File

@@ -0,0 +1,28 @@
#include "usb_protocol_handler.h"
#include "usb_commands/usb_command_get_variable.h"
#include "key_matrix.h"
#include "test_switches.h"
#include "usb_report_updater.h"
void UsbCommand_GetVariable(void)
{
usb_variable_id_t variableId = GetUsbRxBufferUint8(1);
switch (variableId) {
case UsbVariable_TestSwitches:
SetUsbTxBufferUint8(1, TestSwitches);
break;
case UsbVariable_TestUsbStack:
SetUsbTxBufferUint8(1, TestUsbStack);
break;
case UsbVariable_DebounceTimePress:
SetUsbTxBufferUint8(1, DebounceTimePress);
break;
case UsbVariable_DebounceTimeRelease:
SetUsbTxBufferUint8(1, DebounceTimeRelease);
break;
case UsbVariable_UsbReportSemaphore:
SetUsbTxBufferUint8(1, UsbReportUpdateSemaphore);
break;
}
}

View File

@@ -0,0 +1,8 @@
#ifndef __USB_COMMAND_GET_VARIABLE_H__
#define __USB_COMMAND_GET_VARIABLE_H__
// Functions:
void UsbCommand_GetVariable(void);
#endif

View File

@@ -0,0 +1,31 @@
#include "usb_protocol_handler.h"
#include "usb_commands/usb_command_set_variable.h"
#include "key_matrix.h"
#include "test_switches.h"
#include "usb_report_updater.h"
void UsbCommand_SetVariable(void)
{
usb_variable_id_t variableId = GetUsbRxBufferUint8(1);
switch (variableId) {
case UsbVariable_TestSwitches:
if (GetUsbRxBufferUint8(2)) {
TestSwitches = true;
TestSwitches_Activate();
}
break;
case UsbVariable_TestUsbStack:
TestUsbStack = GetUsbRxBufferUint8(2);
break;
case UsbVariable_DebounceTimePress:
DebounceTimePress = GetUsbRxBufferUint8(2);
break;
case UsbVariable_DebounceTimeRelease:
DebounceTimeRelease = GetUsbRxBufferUint8(2);
break;
case UsbVariable_UsbReportSemaphore:
UsbReportUpdateSemaphore = GetUsbRxBufferUint8(2);
break;
}
}

View File

@@ -0,0 +1,8 @@
#ifndef __USB_COMMAND_SET_VARIABLE_H__
#define __USB_COMMAND_SET_VARIABLE_H__
// Functions:
void UsbCommand_SetVariable(void);
#endif

View File

@@ -163,23 +163,30 @@ static usb_device_class_config_list_struct_t UsbDeviceCompositeConfigList = {
} }
}}; }};
bool IsHostSleeping = false; volatile bool SleepModeActive = true;
static volatile bool wakeUpHostAllowed;
static void suspendHost(void) { static void suspendUhk(void) {
IsHostSleeping = true; SleepModeActive = true;
LedSlaveDriver_DisableLeds(); LedSlaveDriver_DisableLeds();
} }
void WakeUpHost(bool sendResume) { static void wakeUpUhk(void) {
if (sendResume) { // The device should wake up the host. SleepModeActive = false;
// Send resume signal - this will call USB_DeviceKhciControl(khciHandle, kUSB_DeviceControlResume, NULL);
USB_DeviceSetStatus(UsbCompositeDevice.deviceHandle, kUSB_DeviceStatusBus, NULL);
}
IsHostSleeping = false;
LedSlaveDriver_UpdateLeds(); LedSlaveDriver_UpdateLeds();
} }
void WakeUpHost(void) {
if (!wakeUpHostAllowed) {
return;
}
// Send resume signal - this will call USB_DeviceKhciControl(khciHandle, kUSB_DeviceControlResume, NULL);
USB_DeviceSetStatus(UsbCompositeDevice.deviceHandle, kUSB_DeviceStatusBus, NULL);
while (SleepModeActive) {
;
}
}
static usb_status_t usbDeviceCallback(usb_device_handle handle, uint32_t event, void *param) static usb_status_t usbDeviceCallback(usb_device_handle handle, uint32_t event, void *param)
{ {
usb_status_t status = kStatus_USB_Error; usb_status_t status = kStatus_USB_Error;
@@ -190,10 +197,6 @@ static usb_status_t usbDeviceCallback(usb_device_handle handle, uint32_t event,
return status; return status;
} }
if (IsHostSleeping) {
WakeUpHost(false); // Wake up the keyboard if there is any activity on the bus.
}
switch (event) { switch (event) {
case kUSB_DeviceEventBusReset: case kUSB_DeviceEventBusReset:
UsbCompositeDevice.attach = 0; UsbCompositeDevice.attach = 0;
@@ -201,17 +204,17 @@ static usb_status_t usbDeviceCallback(usb_device_handle handle, uint32_t event,
break; break;
case kUSB_DeviceEventSuspend: case kUSB_DeviceEventSuspend:
if (UsbCompositeDevice.attach) { if (UsbCompositeDevice.attach) {
suspendHost(); // The host sends this event when it goes to sleep, so turn off all the LEDs. suspendUhk(); // The host sends this event when it goes to sleep, so turn off all the LEDs.
status = kStatus_USB_Success; status = kStatus_USB_Success;
} }
break; break;
case kUSB_DeviceEventResume: case kUSB_DeviceEventResume:
// We will just wake up the host if there is any activity on the bus. wakeUpUhk();
// The problem is that the host won't send a resume event when it boots, so the lights will never come back on.
status = kStatus_USB_Success; status = kStatus_USB_Success;
break; break;
case kUSB_DeviceEventSetConfiguration: case kUSB_DeviceEventSetConfiguration:
UsbCompositeDevice.attach = 1; UsbCompositeDevice.attach = 1;
wakeUpUhk();
UsbCompositeDevice.currentConfiguration = *temp8; UsbCompositeDevice.currentConfiguration = *temp8;
UsbGenericHidSetConfiguration(UsbCompositeDevice.genericHidHandle, *temp8); UsbGenericHidSetConfiguration(UsbCompositeDevice.genericHidHandle, *temp8);
UsbBasicKeyboardSetConfiguration(UsbCompositeDevice.basicKeyboardHandle, *temp8); UsbBasicKeyboardSetConfiguration(UsbCompositeDevice.basicKeyboardHandle, *temp8);
@@ -266,6 +269,10 @@ static usb_status_t usbDeviceCallback(usb_device_handle handle, uint32_t event,
case kUSB_DeviceEventGetHidPhysicalDescriptor: case kUSB_DeviceEventGetHidPhysicalDescriptor:
status = USB_DeviceGetHidPhysicalDescriptor(handle, (usb_device_get_hid_physical_descriptor_struct_t *)param); status = USB_DeviceGetHidPhysicalDescriptor(handle, (usb_device_get_hid_physical_descriptor_struct_t *)param);
break; break;
case kUSB_DeviceEventSetRemoteWakeup:
wakeUpHostAllowed = *temp8;
status = kStatus_USB_Success;
break;
} }
return status; return status;

View File

@@ -28,12 +28,12 @@
// Variables: // Variables:
extern bool IsHostSleeping; extern volatile bool SleepModeActive;
extern usb_composite_device_t UsbCompositeDevice; extern usb_composite_device_t UsbCompositeDevice;
//Functions: //Functions:
void InitUsb(void); void InitUsb(void);
void WakeUpHost(bool sendResume); void WakeUpHost(void);
#endif #endif

View File

@@ -17,6 +17,8 @@
#include "usb_commands/usb_command_get_slave_i2c_errors.h" #include "usb_commands/usb_command_get_slave_i2c_errors.h"
#include "usb_commands/usb_command_set_i2c_baud_rate.h" #include "usb_commands/usb_command_set_i2c_baud_rate.h"
#include "usb_commands/usb_command_switch_keymap.h" #include "usb_commands/usb_command_switch_keymap.h"
#include "usb_commands/usb_command_get_variable.h"
#include "usb_commands/usb_command_set_variable.h"
void UsbProtocolHandler(void) void UsbProtocolHandler(void)
{ {
@@ -77,6 +79,12 @@ void UsbProtocolHandler(void)
case UsbCommandId_SwitchKeymap: case UsbCommandId_SwitchKeymap:
UsbCommand_SwitchKeymap(); UsbCommand_SwitchKeymap();
break; break;
case UsbCommandId_GetVariable:
UsbCommand_GetVariable();
break;
case UsbCommandId_SetVariable:
UsbCommand_SetVariable();
break;
default: default:
SetUsbTxBufferUint8(0, UsbStatusCode_InvalidCommand); SetUsbTxBufferUint8(0, UsbStatusCode_InvalidCommand);
break; break;

View File

@@ -34,8 +34,18 @@
UsbCommandId_GetSlaveI2cErrors = 0x0f, UsbCommandId_GetSlaveI2cErrors = 0x0f,
UsbCommandId_SetI2cBaudRate = 0x10, UsbCommandId_SetI2cBaudRate = 0x10,
UsbCommandId_SwitchKeymap = 0x11, UsbCommandId_SwitchKeymap = 0x11,
UsbCommandId_GetVariable = 0x12,
UsbCommandId_SetVariable = 0x13,
} usb_command_id_t; } usb_command_id_t;
typedef enum {
UsbVariable_TestSwitches,
UsbVariable_TestUsbStack,
UsbVariable_DebounceTimePress,
UsbVariable_DebounceTimeRelease,
UsbVariable_UsbReportSemaphore,
} usb_variable_id_t;
typedef enum { typedef enum {
UsbStatusCode_Success = 0, UsbStatusCode_Success = 0,
UsbStatusCode_InvalidCommand = 1, UsbStatusCode_InvalidCommand = 1,

View File

@@ -13,7 +13,6 @@
#include "layer.h" #include "layer.h"
#include "usb_report_updater.h" #include "usb_report_updater.h"
#include "timer.h" #include "timer.h"
#include "key_debouncer.h"
#include "config_parser/parse_keymap.h" #include "config_parser/parse_keymap.h"
#include "usb_commands/usb_command_get_debug_buffer.h" #include "usb_commands/usb_command_get_debug_buffer.h"
#include "arduino_hid/ConsumerAPI.h" #include "arduino_hid/ConsumerAPI.h"
@@ -21,10 +20,12 @@
static uint32_t mouseUsbReportUpdateTime = 0; static uint32_t mouseUsbReportUpdateTime = 0;
static uint32_t mouseElapsedTime; static uint32_t mouseElapsedTime;
uint16_t DoubleTapSwitchLayerTimeout = 150; uint16_t DoubleTapSwitchLayerTimeout = 300;
static uint16_t DoubleTapSwitchLayerReleaseTimeout = 100; static uint16_t DoubleTapSwitchLayerReleaseTimeout = 200;
static bool activeMouseStates[ACTIVE_MOUSE_STATES_COUNT]; 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; volatile uint8_t UsbReportUpdateSemaphore = 0;
@@ -206,15 +207,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,17 +226,22 @@ 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;
} }
} }
static uint8_t basicScancodeIndex = 0; 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 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)
{ {
@@ -247,8 +253,13 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action)
switch (action->type) { switch (action->type) {
case KeyActionType_Keystroke: case KeyActionType_Keystroke:
ActiveUsbBasicKeyboardReport->modifiers |= action->keystroke.modifiers; if (action->keystroke.scancode) {
if (!keyState->previous) {
stickyModifiers = action->keystroke.modifiers;
}
} else {
ActiveUsbBasicKeyboardReport->modifiers |= action->keystroke.modifiers;
}
switch (action->keystroke.keystrokeType) { switch (action->keystroke.keystrokeType) {
case KeystrokeType_Basic: case KeystrokeType_Basic:
if (basicScancodeIndex >= USB_BASIC_KEYBOARD_MAX_KEYS || action->keystroke.scancode == 0) { if (basicScancodeIndex >= USB_BASIC_KEYBOARD_MAX_KEYS || action->keystroke.scancode == 0) {
@@ -271,6 +282,9 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action)
} }
break; break;
case KeyActionType_Mouse: case KeyActionType_Mouse:
if (!keyState->previous) {
stickyModifiers = 0;
}
activeMouseStates[action->mouseAction] = true; activeMouseStates[action->mouseAction] = true;
break; break;
case KeyActionType_SwitchLayer: case KeyActionType_SwitchLayer:
@@ -278,26 +292,22 @@ static void applyKeyAction(key_state_t *keyState, key_action_t *action)
break; break;
case KeyActionType_SwitchKeymap: case KeyActionType_SwitchKeymap:
if (!keyState->previous) { if (!keyState->previous) {
stickyModifiers = 0;
secondaryRoleState = SecondaryRoleState_Released;
SwitchKeymapById(action->switchKeymap.keymapId); SwitchKeymapById(action->switchKeymap.keymapId);
} }
break; break;
case KeyActionType_PlayMacro: case KeyActionType_PlayMacro:
if (!keyState->previous) { if (!keyState->previous) {
stickyModifiers = 0;
Macros_StartMacro(action->playMacro.macroId); Macros_StartMacro(action->playMacro.macroId);
} }
break; break;
} }
} }
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)
{ {
static uint8_t previousModifiers = 0;
if (MacroPlaying) { if (MacroPlaying) {
Macros_ContinueMacro(); Macros_ContinueMacro();
memcpy(ActiveUsbMouseReport, &MacroMouseReport, sizeof MacroMouseReport); memcpy(ActiveUsbMouseReport, &MacroMouseReport, sizeof MacroMouseReport);
@@ -320,51 +330,66 @@ static void updateActiveUsbReports(void)
if (activeLayer == LayerId_Base) { if (activeLayer == LayerId_Base) {
activeLayer = GetActiveLayer(); activeLayer = GetActiveLayer();
} }
bool layerGotReleased = previousLayer != LayerId_Base && activeLayer == LayerId_Base; bool layerChanged = previousLayer != activeLayer;
if (layerChanged) {
stickyModifiers = 0;
}
LedDisplay_SetLayer(activeLayer); LedDisplay_SetLayer(activeLayer);
#if 0 // Used to toggle key presses at the maximum rate - this was used to reproduce: https://github.com/UltimateHackingKeyboard/firmware/issues/122 if (TestUsbStack) {
static bool simulateKeypresses = false; static bool simulateKeypresses, isEven, isEvenMedia;
static bool isEven = false; static uint32_t mediaCounter = 0;
static bool isEvenMedia = false; key_state_t *testKeyState = &KeyStates[SlotId_LeftKeyboardHalf][0];
static uint32_t mediaCounter = 0;
key_state_t *testKeyState = &KeyStates[SlotId_LeftKeyboardHalf][0]; if (activeLayer == LayerId_Fn && testKeyState->current && !testKeyState->previous) {
if (!testKeyState->previous && testKeyState->current && activeLayer == LayerId_Fn) { simulateKeypresses = !simulateKeypresses;
simulateKeypresses = !simulateKeypresses; }
} if (simulateKeypresses) {
isEven = !isEven;
if (simulateKeypresses) { ActiveUsbBasicKeyboardReport->scancodes[basicScancodeIndex++] = isEven ? HID_KEYBOARD_SC_A : HID_KEYBOARD_SC_BACKSPACE;
isEven = !isEven; if (++mediaCounter % 200 == 0) {
ActiveUsbBasicKeyboardReport->scancodes[basicScancodeIndex++] = isEven ? HID_KEYBOARD_SC_A : HID_KEYBOARD_SC_BACKSPACE; isEvenMedia = !isEvenMedia;
if (++mediaCounter % 200 == 0) { ActiveUsbMediaKeyboardReport->scancodes[mediaScancodeIndex++] = isEvenMedia ? MEDIA_VOLUME_DOWN : MEDIA_VOLUME_UP;
isEvenMedia = !isEvenMedia; }
ActiveUsbMediaKeyboardReport->scancodes[mediaScancodeIndex++] = isEvenMedia ? MEDIA_VOLUME_DOWN : MEDIA_VOLUME_UP; MouseMoveState.xOut = isEven ? -5 : 5;
} }
MouseMoveState.xOut = isEven ? -1 : 1;
} }
#endif
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->debounceCounter) { if (keyState->debouncing) {
keyState->current = keyState->previous; if ((uint8_t)(CurrentTime - keyState->timestamp) > (keyState->previous ? DebounceTimePress : DebounceTimeRelease)) {
} else if (!keyState->previous && keyState->current) { keyState->debouncing = false;
keyState->debounceCounter = KEY_DEBOUNCER_TIMEOUT_MSEC + 1; } else {
keyState->current = keyState->previous;
}
} else if (keyState->previous != keyState->current) {
keyState->timestamp = CurrentTime;
keyState->debouncing = true;
} }
if (keyState->current) { if (keyState->current && !keyState->previous) {
key_action_t *baseAction = &CurrentKeymap[LayerId_Base][slotId][keyId]; if (SleepModeActive) {
if (layerGotReleased && !(baseAction->type == KeyActionType_Keystroke && baseAction->keystroke.scancode == 0 && baseAction->keystroke.modifiers)) { WakeUpHost();
keyState->suppressed = true;
} }
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) { if (action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole) {
// Press released secondary role key. // Press released secondary role key.
if (!keyState->previous && action->type == KeyActionType_Keystroke && action->keystroke.secondaryRole && secondaryRoleState == SecondaryRoleState_Released) { if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Released) {
secondaryRoleState = SecondaryRoleState_Pressed; secondaryRoleState = SecondaryRoleState_Pressed;
secondaryRoleSlotId = slotId; secondaryRoleSlotId = slotId;
secondaryRoleKeyId = keyId; secondaryRoleKeyId = keyId;
@@ -372,22 +397,16 @@ static void updateActiveUsbReports(void)
keyState->suppressed = true; keyState->suppressed = true;
} }
} else { } else {
// Trigger secondary role. applyKeyAction(keyState, action);
if (!keyState->previous && secondaryRoleState == SecondaryRoleState_Pressed) {
secondaryRoleState = SecondaryRoleState_Triggered;
} else {
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;
@@ -403,15 +422,12 @@ static void updateActiveUsbReports(void)
// When a layer switcher key gets pressed along with another key that produces some modifiers // When a layer switcher key gets pressed along with another key that produces some modifiers
// and the accomanying key gets released then keep the related modifiers active a long as the // and the accomanying key gets released then keep the related modifiers active a long as the
// layer switcher key stays pressed. Useful for Alt+Tab keymappings and the like. // layer switcher key stays pressed. Useful for Alt+Tab keymappings and the like.
if (activeLayer != LayerId_Base && activeLayer == PreviousHeldLayer && basicScancodeIndex == 0) { ActiveUsbBasicKeyboardReport->modifiers |= stickyModifiers;
ActiveUsbBasicKeyboardReport->modifiers |= previousModifiers;
}
if (secondaryRoleState == SecondaryRoleState_Triggered && IS_SECONDARY_ROLE_MODIFIER(secondaryRole)) { if (secondaryRoleState == SecondaryRoleState_Triggered && IS_SECONDARY_ROLE_MODIFIER(secondaryRole)) {
ActiveUsbBasicKeyboardReport->modifiers |= SECONDARY_ROLE_MODIFIER_TO_HID_MODIFIER(secondaryRole); ActiveUsbBasicKeyboardReport->modifiers |= SECONDARY_ROLE_MODIFIER_TO_HID_MODIFIER(secondaryRole);
} }
previousModifiers = ActiveUsbBasicKeyboardReport->modifiers;
previousLayer = activeLayer; previousLayer = activeLayer;
} }
@@ -419,26 +435,21 @@ 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 (IsHostSleeping) { if (UsbReportUpdateSemaphore && !SleepModeActive) {
for (uint8_t slotId = 0; slotId < SLOT_COUNT; slotId++) { if (Timer_GetElapsedTime(&lastUpdateTime) < USB_SEMAPHORE_TIMEOUT) {
for (uint8_t keyId = 0; keyId < MAX_KEY_COUNT_PER_MODULE; keyId++) { return;
if (KeyStates[slotId][keyId].current) { } else {
WakeUpHost(true); UsbReportUpdateSemaphore = 0;
return;
}
}
} }
return;
}
if (UsbReportUpdateSemaphore) {
return;
} }
lastUpdateTime = CurrentTime;
UsbReportUpdateCounter++; UsbReportUpdateCounter++;
ResetActiveUsbBasicKeyboardReport(); ResetActiveUsbBasicKeyboardReport();
@@ -453,10 +464,6 @@ void UpdateUsbReports(void)
bool HasUsbSystemKeyboardReportChanged = memcmp(ActiveUsbSystemKeyboardReport, GetInactiveUsbSystemKeyboardReport(), sizeof(usb_system_keyboard_report_t)) != 0; bool HasUsbSystemKeyboardReportChanged = memcmp(ActiveUsbSystemKeyboardReport, GetInactiveUsbSystemKeyboardReport(), sizeof(usb_system_keyboard_report_t)) != 0;
bool HasUsbMouseReportChanged = memcmp(ActiveUsbMouseReport, GetInactiveUsbMouseReport(), sizeof(usb_mouse_report_t)) != 0; bool HasUsbMouseReportChanged = memcmp(ActiveUsbMouseReport, GetInactiveUsbMouseReport(), sizeof(usb_mouse_report_t)) != 0;
if (IsHostSleeping && (previousLayer != LayerId_Base || HasUsbBasicKeyboardReportChanged || HasUsbMediaKeyboardReportChanged || HasUsbSystemKeyboardReportChanged || HasUsbMouseReportChanged)) {
WakeUpHost(true); // Wake up the host if any key is pressed and the computer is sleeping.
}
if (HasUsbBasicKeyboardReportChanged) { if (HasUsbBasicKeyboardReportChanged) {
usb_status_t status = UsbBasicKeyboardAction(); usb_status_t status = UsbBasicKeyboardAction();
if (status == kStatus_USB_Success) { if (status == kStatus_USB_Success) {

View File

@@ -14,6 +14,8 @@
#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 {
@@ -71,6 +73,7 @@
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 volatile uint8_t UsbReportUpdateSemaphore;
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.3.3", "firmwareVersion": "8.5.3",
"deviceProtocolVersion": "4.3.1", "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",

View File

@@ -1,6 +1,8 @@
#include "fsl_gpio.h" #include "fsl_gpio.h"
#include "key_matrix.h" #include "key_matrix.h"
uint8_t DebounceTimePress = 50, DebounceTimeRelease = 50;
void KeyMatrix_Init(key_matrix_t *keyMatrix) void KeyMatrix_Init(key_matrix_t *keyMatrix)
{ {
for (key_matrix_pin_t *row = keyMatrix->rows; row < keyMatrix->rows + keyMatrix->rowNum; row++) { for (key_matrix_pin_t *row = keyMatrix->rows; row < keyMatrix->rows + keyMatrix->rowNum; row++) {

View File

@@ -28,6 +28,10 @@
uint8_t keyStates[MAX_KEYS_IN_MATRIX]; uint8_t keyStates[MAX_KEYS_IN_MATRIX];
} key_matrix_t; } key_matrix_t;
// Variables:
extern uint8_t DebounceTimePress, DebounceTimeRelease;
// Functions: // Functions:
void KeyMatrix_Init(key_matrix_t *keyMatrix); void KeyMatrix_Init(key_matrix_t *keyMatrix);

View File

@@ -19,12 +19,12 @@
// Variables: // Variables:
#define FIRMWARE_MAJOR_VERSION 8 #define FIRMWARE_MAJOR_VERSION 8
#define FIRMWARE_MINOR_VERSION 3 #define FIRMWARE_MINOR_VERSION 5
#define FIRMWARE_PATCH_VERSION 3 #define FIRMWARE_PATCH_VERSION 3
#define DEVICE_PROTOCOL_MAJOR_VERSION 4 #define DEVICE_PROTOCOL_MAJOR_VERSION 4
#define DEVICE_PROTOCOL_MINOR_VERSION 3 #define DEVICE_PROTOCOL_MINOR_VERSION 5
#define DEVICE_PROTOCOL_PATCH_VERSION 1 #define DEVICE_PROTOCOL_PATCH_VERSION 0
#define MODULE_PROTOCOL_MAJOR_VERSION 4 #define MODULE_PROTOCOL_MAJOR_VERSION 4
#define MODULE_PROTOCOL_MINOR_VERSION 0 #define MODULE_PROTOCOL_MINOR_VERSION 0