Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keymap introspection for Dip Switches #22543

Merged
merged 2 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,12 @@ ifeq ($(strip $(ENCODER_ENABLE)), yes)
endif
endif

ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
ifeq ($(strip $(DIP_SWITCH_MAP_ENABLE)), yes)
OPT_DEFS += -DDIP_SWITCH_MAP_ENABLE
endif
endif

VALID_WS2812_DRIVER_TYPES := bitbang custom i2c pwm spi vendor

WS2812_DRIVER ?= bitbang
Expand Down
21 changes: 21 additions & 0 deletions docs/feature_dip_switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@ or
#define DIP_SWITCH_MATRIX_GRID { {0,6}, {1,6}, {2,6} } // List of row and col pairs
```

## DIP Switch map :id=dip-switch-map

DIP Switch mapping may be added to your `keymap.c`, which replicates the normal keyswitch functionality, but with dip switches. Add this to your keymap's `rules.mk`:
```make
DIP_SWITCH_MAP_ENABLE = yes
```
Your `keymap.c` will then need a dip switch mapping defined (for two dip switches):
```c
#if defined(DIP_SWITCH_MAP_ENABLE)
const uint16_t PROGMEM dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES] = {
DIP_SWITCH_OFF_ON(DF(0), DF(1)),
DIP_SWITCH_OFF_ON(EC_NORM, EC_SWAP)
};
#endif
```
?> This should only be enabled at the keymap level.
## Callbacks
The callback functions can be inserted into your `<keyboard>.c`:
Expand Down
6 changes: 6 additions & 0 deletions keyboards/handwired/onekey/keymaps/dip_switch_map/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2023 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

// TODO: Remove reuse of pin
#define DIP_SWITCH_PINS { WS2812_DI_PIN }
14 changes: 14 additions & 0 deletions keyboards/handwired/onekey/keymaps/dip_switch_map/keymap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2023 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_ortho_1x1(KC_A),
[1] = LAYOUT_ortho_1x1(KC_B),
};

#if defined(DIP_SWITCH_MAP_ENABLE)
const uint16_t PROGMEM dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES] = {
DIP_SWITCH_OFF_ON(DF(0), DF(1))
};
#endif
2 changes: 2 additions & 0 deletions keyboards/handwired/onekey/keymaps/dip_switch_map/rules.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DIP_SWITCH_ENABLE = yes
DIP_SWITCH_MAP_ENABLE = yes
28 changes: 28 additions & 0 deletions quantum/dip_switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ __attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) {
return dip_switch_update_mask_user(state);
}

#ifdef DIP_SWITCH_MAP_ENABLE
# include "keymap_introspection.h"
# include "action.h"

# ifndef DIP_SWITCH_MAP_KEY_DELAY
# define DIP_SWITCH_MAP_KEY_DELAY TAP_CODE_DELAY
# endif

static void dip_switch_exec_mapping(uint8_t index, bool on) {
// The delays below cater for Windows and its wonderful requirements.
action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, true) : MAKE_DIPSWITCH_OFF_EVENT(index, true));
# if DIP_SWITCH_MAP_KEY_DELAY > 0
wait_ms(DIP_SWITCH_MAP_KEY_DELAY);
# endif // DIP_SWITCH_MAP_KEY_DELAY > 0

action_exec(on ? MAKE_DIPSWITCH_ON_EVENT(index, false) : MAKE_DIPSWITCH_OFF_EVENT(index, false));
# if DIP_SWITCH_MAP_KEY_DELAY > 0
wait_ms(DIP_SWITCH_MAP_KEY_DELAY);
# endif // DIP_SWITCH_MAP_KEY_DELAY > 0
}
#endif // DIP_SWITCH_MAP_ENABLE

void dip_switch_init(void) {
#ifdef DIP_SWITCH_PINS
# if defined(SPLIT_KEYBOARD) && defined(DIP_SWITCH_PINS_RIGHT)
Expand Down Expand Up @@ -109,11 +131,17 @@ void dip_switch_read(bool forced) {
dip_switch_mask |= dip_switch_state[i] << i;
if (last_dip_switch_state[i] != dip_switch_state[i] || forced) {
has_dip_state_changed = true;
#ifndef DIP_SWITCH_MAP_ENABLE
dip_switch_update_kb(i, dip_switch_state[i]);
#else
dip_switch_exec_mapping(i, dip_switch_state[i]);
#endif
}
}
if (has_dip_state_changed) {
#ifndef DIP_SWITCH_MAP_ENABLE
dip_switch_update_mask_kb(dip_switch_mask);
#endif
memcpy(last_dip_switch_state, dip_switch_state, sizeof(dip_switch_state));
}
}
Expand Down
7 changes: 7 additions & 0 deletions quantum/dip_switch.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,10 @@ void dip_switch_read(bool forced);

void dip_switch_init(void);
void dip_switch_task(void);

#ifdef DIP_SWITCH_MAP_ENABLE
# define NUM_DIP_STATES 2
# define DIP_SWITCH_OFF_ON(off, on) \
{ (off), (on) }
extern const uint16_t dip_switch_map[NUM_DIP_SWITCHES][NUM_DIP_STATES];
#endif // DIP_SWITCH_MAP_ENABLE
13 changes: 12 additions & 1 deletion quantum/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct {
uint8_t row;
} keypos_t;

typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4 } keyevent_type_t;
typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4, DIP_SWITCH_ON_EVENT = 5, DIP_SWITCH_OFF_EVENT = 6 } keyevent_type_t;

/* key event */
typedef struct {
Expand All @@ -48,6 +48,8 @@ typedef struct {
/* special keypos_t entries */
#define KEYLOC_ENCODER_CW 253
#define KEYLOC_ENCODER_CCW 252
#define KEYLOC_DIP_SWITCH_ON 251
#define KEYLOC_DIP_SWITCH_OFF 250

static inline bool IS_NOEVENT(const keyevent_t event) {
return event.type == TICK_EVENT;
Expand All @@ -64,6 +66,9 @@ static inline bool IS_COMBOEVENT(const keyevent_t event) {
static inline bool IS_ENCODEREVENT(const keyevent_t event) {
return event.type == ENCODER_CW_EVENT || event.type == ENCODER_CCW_EVENT;
}
static inline bool IS_DIPSWITCHEVENT(const keyevent_t event) {
return event.type == DIP_SWITCH_ON_EVENT || event.type == DIP_SWITCH_OFF_EVENT;
}

/* Common keypos_t object factory */
#define MAKE_KEYPOS(row_num, col_num) ((keypos_t){.row = (row_num), .col = (col_num)})
Expand Down Expand Up @@ -92,6 +97,12 @@ static inline bool IS_ENCODEREVENT(const keyevent_t event) {
# define MAKE_ENCODER_CCW_EVENT(enc_id, press) MAKE_EVENT(KEYLOC_ENCODER_CCW, (enc_id), (press), ENCODER_CCW_EVENT)
#endif // ENCODER_MAP_ENABLE

#ifdef DIP_SWITCH_MAP_ENABLE
/* Dip Switch events */
# define MAKE_DIPSWITCH_ON_EVENT(switch_id, press) MAKE_EVENT(KEYLOC_DIP_SWITCH_ON, (switch_id), (press), DIP_SWITCH_ON_EVENT)
# define MAKE_DIPSWITCH_OFF_EVENT(switch_id, press) MAKE_EVENT(KEYLOC_DIP_SWITCH_OFF, (switch_id), (press), DIP_SWITCH_OFF_EVENT)
#endif // DIP_SWITCH_MAP_ENABLE

/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
Expand Down
12 changes: 12 additions & 0 deletions quantum/keymap_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "encoder.h"
#endif

#ifdef DIP_SWITCH_MAP_ENABLE
# include "dip_switch.h"
#endif

#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
Expand Down Expand Up @@ -204,5 +208,13 @@ __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key
return keycode_at_encodermap_location(layer, key.col, false);
}
#endif // ENCODER_MAP_ENABLE
#ifdef DIP_SWITCH_MAP_ENABLE
else if (key.row == KEYLOC_DIP_SWITCH_ON && key.col < NUM_DIP_SWITCHES) {
return keycode_at_dip_switch_map_location(key.col, true);
} else if (key.row == KEYLOC_DIP_SWITCH_OFF && key.col < NUM_DIP_SWITCHES) {
return keycode_at_dip_switch_map_location(key.col, false);
}
#endif // DIP_SWITCH_MAP_ENABLE

return KC_NO;
}
18 changes: 18 additions & 0 deletions quantum/keymap_introspection.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ __attribute__((weak)) uint16_t keycode_at_encodermap_location(uint8_t layer_num,

#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Dip Switch mapping

#if defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE)

uint16_t keycode_at_dip_switch_map_location_raw(uint8_t switch_idx, bool on) {
if (switch_idx < NUM_DIP_SWITCHES) {
return pgm_read_word(&dip_switch_map[switch_idx][!!on]);
}
return KC_TRNS;
}

uint16_t keycode_at_dip_switch_map_location(uint8_t switch_idx, bool on) {
return keycode_at_dip_switch_map_location_raw(switch_idx, on);
}

#endif // defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Combos

Expand Down
12 changes: 12 additions & 0 deletions quantum/keymap_introspection.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ uint16_t keycode_at_encodermap_location(uint8_t layer_num, uint8_t encoder_idx,

#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Dip Switch mapping

#if defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE)

// Get the keycode for the dip_switch mapping location, stored in firmware rather than any other persistent storage
uint16_t keycode_at_dip_switch_map_location_raw(uint8_t switch_idx, bool on);
// Get the keycode for the dip_switch mapping location, potentially stored dynamically
uint16_t keycode_at_dip_switch_map_location(uint8_t switch_idx, bool on);

#endif // defined(DIP_SWITCH_ENABLE) && defined(DIP_SWITCH_MAP_ENABLE)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Combos

Expand Down