Add Dip Switch as a core feature (#6140)
* Add Dip Switches as a core feature * Add documentation for Dip Switch feature * Update Preonic Rev3 to use new feature and remove custom matrix * Apply suggestions from code review Co-Authored-By: noroadsleft <18669334+noroadsleft@users.noreply.github.com> * Remove custom matrix line completely Rather than just disabling it Co-Authored-By: fauxpark <fauxpark@gmail.com> * DIP changes Co-Authored-By: fauxpark <fauxpark@gmail.com> * Use better check for DIP Switch configuration * Add to show features * Add bitmask callback for dip switch * Fix OLKB Boards dip switch config * Update docs to include bitmask example * Fix comments/documentation Co-Authored-By: fauxpark <fauxpark@gmail.com> * Fix issues with docs and use example from @tuzonghua * Fix wording Co-Authored-By: fauxpark <fauxpark@gmail.com> * Fix example to use proper formatting Bad, BAAAAAAD drashna!!! * Handle dip switch initialization better
This commit is contained in:
parent
9f46606dff
commit
dab4967f1b
@ -358,3 +358,9 @@ ifeq ($(strip $(SPACE_CADET_ENABLE)), yes)
|
|||||||
SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
|
SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
|
||||||
OPT_DEFS += -DSPACE_CADET_ENABLE
|
OPT_DEFS += -DSPACE_CADET_ENABLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
|
||||||
|
SRC += $(QUANTUM_DIR)/dip_switch.c
|
||||||
|
OPT_DEFS += -DDIP_SWITCH_ENABLE
|
||||||
|
endif
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
* [Combos](feature_combo.md)
|
* [Combos](feature_combo.md)
|
||||||
* [Command](feature_command.md)
|
* [Command](feature_command.md)
|
||||||
* [Debounce API](feature_debounce_type.md)
|
* [Debounce API](feature_debounce_type.md)
|
||||||
|
* [DIP Switch](feature_dip_switch.md)
|
||||||
* [Dynamic Macros](feature_dynamic_macros.md)
|
* [Dynamic Macros](feature_dynamic_macros.md)
|
||||||
* [Encoders](feature_encoders.md)
|
* [Encoders](feature_encoders.md)
|
||||||
* [Grave Escape](feature_grave_esc.md)
|
* [Grave Escape](feature_grave_esc.md)
|
||||||
|
90
docs/feature_dip_switch.md
Normal file
90
docs/feature_dip_switch.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# DIP Switches
|
||||||
|
|
||||||
|
DIP switches are supported by adding this to your `rules.mk`:
|
||||||
|
|
||||||
|
DIP_SWITCH_ENABLE = yes
|
||||||
|
|
||||||
|
and this to your `config.h`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define DIP_SWITCH_PINS { B14, A15, A10, B9 }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Callbacks
|
||||||
|
|
||||||
|
The callback functions can be inserted into your `<keyboard>.c`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void dip_switch_update_kb(uint8_t index, bool active) {
|
||||||
|
dip_switch_update_user(index, active);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
or `keymap.c`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void dip_switch_update_user(uint8_t index, bool active) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
if(active) { audio_on(); } else { audio_off(); }
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if(active) { clicky_on(); } else { clicky_off(); }
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(active) { music_on(); } else { music_off(); }
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (active) {
|
||||||
|
#ifdef AUDIO_ENABLE
|
||||||
|
PLAY_SONG(plover_song);
|
||||||
|
#endif
|
||||||
|
layer_on(_PLOVER);
|
||||||
|
} else {
|
||||||
|
#ifdef AUDIO_ENABLE
|
||||||
|
PLAY_SONG(plover_gb_song);
|
||||||
|
#endif
|
||||||
|
layer_off(_PLOVER);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, we support bit mask functions which allow for more complex handling.
|
||||||
|
|
||||||
|
|
||||||
|
```c
|
||||||
|
void dip_switch_update_mask_kb(uint32_t state) {
|
||||||
|
dip_switch_update_mask_user(state);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
or `keymap.c`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void dip_switch_update_mask_user(uint32_t state) {
|
||||||
|
if (state & (1UL<<0) && state & (1UL<<1)) {
|
||||||
|
layer_on(_ADJUST); // C on esc
|
||||||
|
} else {
|
||||||
|
layer_off(_ADJUST);
|
||||||
|
}
|
||||||
|
if (state & (1UL<<0)) {
|
||||||
|
layer_on(_TEST_A); // A on ESC
|
||||||
|
} else {
|
||||||
|
layer_off(_TEST_A);
|
||||||
|
}
|
||||||
|
if (state & (1UL<<1)) {
|
||||||
|
layer_on(_TEST_B); // B on esc
|
||||||
|
} else {
|
||||||
|
layer_off(_TEST_B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
One side of the DIP switch should be wired directly to the pin on the MCU, and the other side to ground. It should not matter which side is connected to which, as it should be functionally the same.
|
@ -12,6 +12,7 @@ QMK has a staggering number of features for building your keyboard. It can take
|
|||||||
* [Combos](feature_combo.md) - Custom actions for multiple key holds.
|
* [Combos](feature_combo.md) - Custom actions for multiple key holds.
|
||||||
* [Command](feature_command.md) - Runtime version of bootmagic (Formerly known as "Magic").
|
* [Command](feature_command.md) - Runtime version of bootmagic (Formerly known as "Magic").
|
||||||
* [Debounce API](feature_debounce_type.md) - Customization of debouncing algorithms, and the ability to add more/custom debouncing.
|
* [Debounce API](feature_debounce_type.md) - Customization of debouncing algorithms, and the ability to add more/custom debouncing.
|
||||||
|
* [DIP Switch](feature_dip_switch.md) - Toggle switches for customizing board function.
|
||||||
* [Dynamic Macros](feature_dynamic_macros.md) - Record and playback macros from the keyboard itself.
|
* [Dynamic Macros](feature_dynamic_macros.md) - Record and playback macros from the keyboard itself.
|
||||||
* [Encoders](feature_encoders.md) - Rotary encoders!
|
* [Encoders](feature_encoders.md) - Rotary encoders!
|
||||||
* [Grave Escape](feature_grave_esc.md) - Lets you use a single key for Esc and Grave.
|
* [Grave Escape](feature_grave_esc.md) - Lets you use a single key for Esc and Grave.
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
* [热改键](feature_bootmagic.md)
|
* [热改键](feature_bootmagic.md)
|
||||||
* [组合](feature_combo)
|
* [组合](feature_combo)
|
||||||
* [命令](feature_command.md)
|
* [命令](feature_command.md)
|
||||||
|
* [拨动开关](feature_dip_switch.md)
|
||||||
* [动态宏指令](feature_dynamic_macros.md)
|
* [动态宏指令](feature_dynamic_macros.md)
|
||||||
* [编码器](feature_encoders.md)
|
* [编码器](feature_encoders.md)
|
||||||
* [重音号Esc复合键](feature_grave_esc.md)
|
* [重音号Esc复合键](feature_grave_esc.md)
|
||||||
|
@ -289,7 +289,7 @@ void encoder_update(bool clockwise) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dip_update(uint8_t index, bool active) {
|
void dip_switch_update_user(uint8_t index, bool active) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
if (active) {
|
if (active) {
|
||||||
|
@ -37,15 +37,20 @@
|
|||||||
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
|
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
/* Note: These are not used for arm boards. They're here purely as documentation.
|
/* Note: These are not used for arm boards. They're here purely as documentation. */
|
||||||
* #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 }
|
#undef MATRIX_ROW_PINS
|
||||||
* #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 }
|
#undef MATRIX_COL_PINS
|
||||||
* #define UNUSED_PINS
|
|
||||||
*/
|
#define MATRIX_ROW_PINS { A10, A9, A8, B15, C13, C14, C15, A2 }
|
||||||
|
#define MATRIX_COL_PINS { B11, B10, B2, B1, A7, B0 }
|
||||||
|
|
||||||
|
#define UNUSED_PINS
|
||||||
|
|
||||||
#define ENCODERS_PAD_A { B12 }
|
#define ENCODERS_PAD_A { B12 }
|
||||||
#define ENCODERS_PAD_B { B13 }
|
#define ENCODERS_PAD_B { B13 }
|
||||||
|
|
||||||
|
#define DIP_SWITCH_PINS { B14, A15, A0, B9 }
|
||||||
|
|
||||||
#define MUSIC_MAP
|
#define MUSIC_MAP
|
||||||
#undef AUDIO_VOICES
|
#undef AUDIO_VOICES
|
||||||
#undef C6_AUDIO
|
#undef C6_AUDIO
|
||||||
|
@ -1,176 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "hal.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "wait.h"
|
|
||||||
#include "printf.h"
|
|
||||||
#include "backlight.h"
|
|
||||||
#include "matrix.h"
|
|
||||||
#include "action.h"
|
|
||||||
#include "keycode.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* col: { B11, B10, B2, B1, A7, B0 }
|
|
||||||
* row: { A10, A9, A8, B15, C13, C14, C15, A2 }
|
|
||||||
*/
|
|
||||||
/* matrix state(1:on, 0:off) */
|
|
||||||
static matrix_row_t matrix[MATRIX_ROWS];
|
|
||||||
static matrix_row_t matrix_debouncing[MATRIX_COLS];
|
|
||||||
static bool debouncing = false;
|
|
||||||
static uint16_t debouncing_time = 0;
|
|
||||||
|
|
||||||
static bool dip_switch[4] = {0, 0, 0, 0};
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_init_user(void) {}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_scan_user(void) {}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_scan_kb(void) {
|
|
||||||
matrix_scan_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init(void) {
|
|
||||||
printf("matrix init\n");
|
|
||||||
//debug_matrix = true;
|
|
||||||
|
|
||||||
// dip switch setup
|
|
||||||
palSetPadMode(GPIOB, 14, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP);
|
|
||||||
|
|
||||||
// actual matrix setup
|
|
||||||
palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
|
|
||||||
palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
|
|
||||||
|
|
||||||
memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
|
|
||||||
memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t));
|
|
||||||
|
|
||||||
|
|
||||||
matrix_init_quantum();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void dip_update(uint8_t index, bool active) { }
|
|
||||||
|
|
||||||
bool last_dip_switch[4] = {0};
|
|
||||||
|
|
||||||
uint8_t matrix_scan(void) {
|
|
||||||
// dip switch
|
|
||||||
dip_switch[0] = !palReadPad(GPIOB, 14);
|
|
||||||
dip_switch[1] = !palReadPad(GPIOA, 15);
|
|
||||||
dip_switch[2] = !palReadPad(GPIOA, 10);
|
|
||||||
dip_switch[3] = !palReadPad(GPIOB, 9);
|
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
|
||||||
if (last_dip_switch[i] ^ dip_switch[i])
|
|
||||||
dip_update(i, dip_switch[i]);
|
|
||||||
}
|
|
||||||
memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch));
|
|
||||||
|
|
||||||
// actual matrix
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
matrix_row_t data = 0;
|
|
||||||
|
|
||||||
// strobe col { B11, B10, B2, B1, A7, B0 }
|
|
||||||
switch (col) {
|
|
||||||
case 0: palSetPad(GPIOB, 11); break;
|
|
||||||
case 1: palSetPad(GPIOB, 10); break;
|
|
||||||
case 2: palSetPad(GPIOB, 2); break;
|
|
||||||
case 3: palSetPad(GPIOB, 1); break;
|
|
||||||
case 4: palSetPad(GPIOA, 7); break;
|
|
||||||
case 5: palSetPad(GPIOB, 0); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need wait to settle pin state
|
|
||||||
wait_us(20);
|
|
||||||
|
|
||||||
// read row data { A10, A9, A8, B15, C13, C14, C15, A2 }
|
|
||||||
data = (
|
|
||||||
(palReadPad(GPIOA, 10) << 0 ) |
|
|
||||||
(palReadPad(GPIOA, 9) << 1 ) |
|
|
||||||
(palReadPad(GPIOA, 8) << 2 ) |
|
|
||||||
(palReadPad(GPIOB, 15) << 3 ) |
|
|
||||||
(palReadPad(GPIOC, 13) << 4 ) |
|
|
||||||
(palReadPad(GPIOC, 14) << 5 ) |
|
|
||||||
(palReadPad(GPIOC, 15) << 6 ) |
|
|
||||||
(palReadPad(GPIOA, 2) << 7 )
|
|
||||||
);
|
|
||||||
|
|
||||||
// unstrobe col { B11, B10, B2, B1, A7, B0 }
|
|
||||||
switch (col) {
|
|
||||||
case 0: palClearPad(GPIOB, 11); break;
|
|
||||||
case 1: palClearPad(GPIOB, 10); break;
|
|
||||||
case 2: palClearPad(GPIOB, 2); break;
|
|
||||||
case 3: palClearPad(GPIOB, 1); break;
|
|
||||||
case 4: palClearPad(GPIOA, 7); break;
|
|
||||||
case 5: palClearPad(GPIOB, 0); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matrix_debouncing[col] != data) {
|
|
||||||
matrix_debouncing[col] = data;
|
|
||||||
debouncing = true;
|
|
||||||
debouncing_time = timer_read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
|
|
||||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
|
||||||
matrix[row] = 0;
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debouncing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix_scan_quantum();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool matrix_is_on(uint8_t row, uint8_t col) {
|
|
||||||
return (matrix[row] & (1<<col));
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix_row_t matrix_get_row(uint8_t row) {
|
|
||||||
return matrix[row];
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_print(void) {
|
|
||||||
printf("\nr/c 01234567\n");
|
|
||||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
|
||||||
printf("%X0: ", row);
|
|
||||||
matrix_row_t data = matrix_get_row(row);
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
if (data & (1<<col))
|
|
||||||
printf("1");
|
|
||||||
else
|
|
||||||
printf("0");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,3 +22,13 @@ void matrix_init_kb(void) {
|
|||||||
void matrix_scan_kb(void) {
|
void matrix_scan_kb(void) {
|
||||||
matrix_scan_user();
|
matrix_scan_user();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DIP_SWITCH_ENABLE
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_update(uint8_t index, bool active) {}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_user(uint8_t index, bool active) {
|
||||||
|
dip_update(index, active);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
# project specific files
|
# project specific files
|
||||||
SRC = matrix.c
|
|
||||||
LAYOUTS += ortho_4x12
|
LAYOUTS += ortho_4x12
|
||||||
|
|
||||||
# Cortex version
|
# Cortex version
|
||||||
@ -31,9 +30,9 @@ API_SYSEX_ENABLE = no
|
|||||||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||||
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
|
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
|
||||||
|
|
||||||
CUSTOM_MATRIX = yes # Custom matrix file
|
|
||||||
# SERIAL_LINK_ENABLE = yes
|
# SERIAL_LINK_ENABLE = yes
|
||||||
ENCODER_ENABLE = yes
|
ENCODER_ENABLE = yes
|
||||||
|
DIP_SWITCH_ENABLE = yes
|
||||||
|
|
||||||
LAYOUTS = ortho_4x12 planck_mit
|
LAYOUTS = ortho_4x12 planck_mit
|
||||||
LAYOUTS_HAS_RGB = no
|
LAYOUTS_HAS_RGB = no
|
||||||
|
@ -259,7 +259,7 @@ void encoder_update_user(uint8_t index, bool clockwise) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dip_update(uint8_t index, bool active) {
|
void dip_switch_update_user(uint8_t index, bool active) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
if (active) {
|
if (active) {
|
||||||
|
@ -27,25 +27,17 @@
|
|||||||
#define MATRIX_ROWS 10
|
#define MATRIX_ROWS 10
|
||||||
#define MATRIX_COLS 6
|
#define MATRIX_COLS 6
|
||||||
|
|
||||||
/*
|
#undef MATRIX_ROW_PINS
|
||||||
* Keyboard Matrix Assignments
|
#undef MATRIX_COL_PINS
|
||||||
*
|
#define MATRIX_ROW_PINS { A10, A9, A8, B15, C13, C14, C15, A2, A3, A6 }
|
||||||
* Change this to how you wired your keyboard
|
#define MATRIX_COL_PINS { B11, B10, B2, B1, A7, B0 }
|
||||||
* COLS: AVR pins used for columns, left to right
|
#define UNUSED_PINS
|
||||||
* ROWS: AVR pins used for rows, top to bottom
|
|
||||||
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
|
|
||||||
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/* Note: These are not used for arm boards. They're here purely as documentation.
|
|
||||||
* #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 }
|
|
||||||
* #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 }
|
|
||||||
* #define UNUSED_PINS
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ENCODERS_PAD_A { B12 }
|
#define ENCODERS_PAD_A { B12 }
|
||||||
#define ENCODERS_PAD_B { B13 }
|
#define ENCODERS_PAD_B { B13 }
|
||||||
|
|
||||||
|
#define DIP_SWITCH_PINS { B14, A15, A0, B9 }
|
||||||
|
|
||||||
#define MUSIC_MAP
|
#define MUSIC_MAP
|
||||||
#undef AUDIO_VOICES
|
#undef AUDIO_VOICES
|
||||||
#undef C6_AUDIO
|
#undef C6_AUDIO
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "hal.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "wait.h"
|
|
||||||
#include "printf.h"
|
|
||||||
#include "backlight.h"
|
|
||||||
#include "matrix.h"
|
|
||||||
#include "action.h"
|
|
||||||
#include "keycode.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* col: { B11, B10, B2, B1, A7, B0 }
|
|
||||||
* row: { A10, A9, A8, B15, C13, C14, C15, A2 }
|
|
||||||
*/
|
|
||||||
/* matrix state(1:on, 0:off) */
|
|
||||||
static matrix_row_t matrix[MATRIX_ROWS];
|
|
||||||
static matrix_col_t matrix_debouncing[MATRIX_COLS];
|
|
||||||
static bool debouncing = false;
|
|
||||||
static uint16_t debouncing_time = 0;
|
|
||||||
|
|
||||||
static bool dip_switch[4] = {0, 0, 0, 0};
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_init_user(void) {}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_scan_user(void) {}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_init_kb(void) {
|
|
||||||
matrix_init_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void matrix_scan_kb(void) {
|
|
||||||
matrix_scan_user();
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_init(void) {
|
|
||||||
printf("matrix init\n");
|
|
||||||
//debug_matrix = true;
|
|
||||||
|
|
||||||
// dip switch setup
|
|
||||||
palSetPadMode(GPIOB, 14, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP);
|
|
||||||
palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP);
|
|
||||||
|
|
||||||
// actual matrix setup
|
|
||||||
palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);
|
|
||||||
|
|
||||||
palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 3, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
palSetPadMode(GPIOA, 6, PAL_MODE_INPUT_PULLDOWN);
|
|
||||||
|
|
||||||
|
|
||||||
memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
|
|
||||||
memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_col_t));
|
|
||||||
|
|
||||||
|
|
||||||
matrix_init_quantum();
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void dip_update(uint8_t index, bool active) { }
|
|
||||||
|
|
||||||
__attribute__ ((weak))
|
|
||||||
void encoder_update(bool clockwise) { }
|
|
||||||
|
|
||||||
bool last_dip_switch[4] = {0};
|
|
||||||
|
|
||||||
#ifndef ENCODER_RESOLUTION
|
|
||||||
#define ENCODER_RESOLUTION 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t matrix_scan(void) {
|
|
||||||
// dip switch
|
|
||||||
dip_switch[0] = !palReadPad(GPIOB, 14);
|
|
||||||
dip_switch[1] = !palReadPad(GPIOA, 15);
|
|
||||||
dip_switch[2] = !palReadPad(GPIOA, 10);
|
|
||||||
dip_switch[3] = !palReadPad(GPIOB, 9);
|
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
|
||||||
if (last_dip_switch[i] ^ dip_switch[i])
|
|
||||||
dip_update(i, dip_switch[i]);
|
|
||||||
}
|
|
||||||
memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch));
|
|
||||||
|
|
||||||
// actual matrix
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
matrix_col_t data = 0;
|
|
||||||
|
|
||||||
// strobe col { B11, B10, B2, B1, A7, B0 }
|
|
||||||
switch (col) {
|
|
||||||
case 0: palSetPad(GPIOB, 11); break;
|
|
||||||
case 1: palSetPad(GPIOB, 10); break;
|
|
||||||
case 2: palSetPad(GPIOB, 2); break;
|
|
||||||
case 3: palSetPad(GPIOB, 1); break;
|
|
||||||
case 4: palSetPad(GPIOA, 7); break;
|
|
||||||
case 5: palSetPad(GPIOB, 0); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// need wait to settle pin state
|
|
||||||
wait_us(20);
|
|
||||||
|
|
||||||
// read row data { A10, A9, A8, B15, C13, C14, C15, A2 }
|
|
||||||
data = (
|
|
||||||
(palReadPad(GPIOA, 10) << 0 ) |
|
|
||||||
(palReadPad(GPIOA, 9) << 1 ) |
|
|
||||||
(palReadPad(GPIOA, 8) << 2 ) |
|
|
||||||
(palReadPad(GPIOB, 15) << 3 ) |
|
|
||||||
(palReadPad(GPIOC, 13) << 4 ) |
|
|
||||||
(palReadPad(GPIOC, 14) << 5 ) |
|
|
||||||
(palReadPad(GPIOC, 15) << 6 ) |
|
|
||||||
(palReadPad(GPIOA, 2) << 7 ) |
|
|
||||||
(palReadPad(GPIOA, 3) << 8 ) |
|
|
||||||
(palReadPad(GPIOA, 6) << 9 )
|
|
||||||
);
|
|
||||||
|
|
||||||
// unstrobe col { B11, B10, B2, B1, A7, B0 }
|
|
||||||
switch (col) {
|
|
||||||
case 0: palClearPad(GPIOB, 11); break;
|
|
||||||
case 1: palClearPad(GPIOB, 10); break;
|
|
||||||
case 2: palClearPad(GPIOB, 2); break;
|
|
||||||
case 3: palClearPad(GPIOB, 1); break;
|
|
||||||
case 4: palClearPad(GPIOA, 7); break;
|
|
||||||
case 5: palClearPad(GPIOB, 0); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matrix_debouncing[col] != data) {
|
|
||||||
matrix_debouncing[col] = data;
|
|
||||||
debouncing = true;
|
|
||||||
debouncing_time = timer_read();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
|
|
||||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
|
||||||
matrix[row] = 0;
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debouncing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix_scan_quantum();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool matrix_is_on(uint8_t row, uint8_t col) {
|
|
||||||
return (matrix[row] & (1<<col));
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix_row_t matrix_get_row(uint8_t row) {
|
|
||||||
return matrix[row];
|
|
||||||
}
|
|
||||||
|
|
||||||
void matrix_print(void) {
|
|
||||||
printf("\nr/c 01234567\n");
|
|
||||||
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
|
||||||
printf("%X0: ", row);
|
|
||||||
matrix_row_t data = matrix_get_row(row);
|
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
|
||||||
if (data & (1<<col))
|
|
||||||
printf("1");
|
|
||||||
else
|
|
||||||
printf("0");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,3 +22,13 @@ void matrix_init_kb(void) {
|
|||||||
void matrix_scan_kb(void) {
|
void matrix_scan_kb(void) {
|
||||||
matrix_scan_user();
|
matrix_scan_user();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DIP_SWITCH_ENABLE
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_update(uint8_t index, bool active) {}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_user(uint8_t index, bool active) {
|
||||||
|
dip_update(index, active);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# project specific files
|
|
||||||
SRC = matrix.c
|
|
||||||
|
|
||||||
# Cortex version
|
# Cortex version
|
||||||
MCU = STM32F303
|
MCU = STM32F303
|
||||||
|
|
||||||
@ -27,8 +24,8 @@ API_SYSEX_ENABLE = no
|
|||||||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||||
#SLEEP_LED_ENABLE = yes
|
#SLEEP_LED_ENABLE = yes
|
||||||
|
|
||||||
CUSTOM_MATRIX = yes # Custom matrix file
|
|
||||||
# SERIAL_LINK_ENABLE = yes
|
# SERIAL_LINK_ENABLE = yes
|
||||||
ENCODER_ENABLE = yes
|
ENCODER_ENABLE = yes
|
||||||
|
DIP_SWITCH_ENABLE = yes
|
||||||
|
|
||||||
LAYOUTS = ortho_5x12
|
LAYOUTS = ortho_5x12
|
||||||
|
71
quantum/dip_switch.c
Normal file
71
quantum/dip_switch.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
|
||||||
|
* Copyright 2019 Drashna Jaelre (Christopher Courtney) <drashna@live.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dip_switch.h"
|
||||||
|
|
||||||
|
// for memcpy
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(DIP_SWITCH_PINS)
|
||||||
|
# error "No DIP switch pads defined by DIP_SWITCH_PINS"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUMBER_OF_DIP_SWITCHES (sizeof(dip_switch_pad)/sizeof(pin_t))
|
||||||
|
static pin_t dip_switch_pad[] = DIP_SWITCH_PINS;
|
||||||
|
static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = { 0 };
|
||||||
|
static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = { 0 };
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_user(uint8_t index, bool active) {}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_kb(uint8_t index, bool active) { dip_switch_update_user(index, active); }
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_mask_user(uint32_t state) {}
|
||||||
|
|
||||||
|
__attribute__((weak))
|
||||||
|
void dip_switch_update_mask_kb(uint32_t state) { dip_switch_update_mask_user(state); }
|
||||||
|
|
||||||
|
void dip_switch_init(void) {
|
||||||
|
for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) {
|
||||||
|
setPinInputHigh(dip_switch_pad[i]);
|
||||||
|
}
|
||||||
|
dip_switch_read(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dip_switch_read(bool forced) {
|
||||||
|
bool has_dip_state_changed = false;
|
||||||
|
uint32_t dip_switch_mask = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < NUMBER_OF_DIP_SWITCHES; i++) {
|
||||||
|
dip_switch_state[i] = !readPin(dip_switch_pad[i]);
|
||||||
|
dip_switch_mask |= dip_switch_state[i] << i;
|
||||||
|
if (last_dip_switch_state[i] ^ dip_switch_state[i] || forced) {
|
||||||
|
has_dip_state_changed = true;
|
||||||
|
dip_switch_update_kb(i, dip_switch_state[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_dip_state_changed) {
|
||||||
|
dip_switch_update_mask_kb(dip_switch_mask);
|
||||||
|
}
|
||||||
|
memcpy(last_dip_switch_state, dip_switch_state, sizeof(&dip_switch_state));
|
||||||
|
}
|
29
quantum/dip_switch.h
Normal file
29
quantum/dip_switch.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Jack Humbert <jack.humb@gmail.com>
|
||||||
|
* Copyright 2018 Drashna Jaelre (Christopher Courtney) <drashna@live.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
void dip_switch_update_kb(uint8_t index, bool active);
|
||||||
|
void dip_switch_update_user(uint8_t index, bool active);
|
||||||
|
void dip_switch_update_mask_user(uint32_t state);
|
||||||
|
void dip_switch_update_mask_kb(uint32_t state);
|
||||||
|
|
||||||
|
void dip_switch_init(void);
|
||||||
|
void dip_switch_read(bool forced);
|
@ -967,6 +967,10 @@ void matrix_init_quantum() {
|
|||||||
#ifdef OUTPUT_AUTO_ENABLE
|
#ifdef OUTPUT_AUTO_ENABLE
|
||||||
set_output(OUTPUT_AUTO);
|
set_output(OUTPUT_AUTO);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DIP_SWITCH_ENABLE
|
||||||
|
dip_switch_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
matrix_init_kb();
|
matrix_init_kb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1003,6 +1007,10 @@ void matrix_scan_quantum() {
|
|||||||
haptic_task();
|
haptic_task();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DIP_SWITCH_ENABLE
|
||||||
|
dip_switch_read(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
matrix_scan_kb();
|
matrix_scan_kb();
|
||||||
}
|
}
|
||||||
#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
|
#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
|
||||||
|
@ -145,6 +145,11 @@ extern layer_state_t layer_state;
|
|||||||
# include "oled_driver.h"
|
# include "oled_driver.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DIP_SWITCH_ENABLE
|
||||||
|
#include "dip_switch.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Function substitutions to ease GPIO manipulation
|
// Function substitutions to ease GPIO manipulation
|
||||||
#if defined(__AVR__)
|
#if defined(__AVR__)
|
||||||
typedef uint8_t pin_t;
|
typedef uint8_t pin_t;
|
||||||
|
@ -31,7 +31,8 @@ HARDWARE_OPTION_NAMES = \
|
|||||||
LED_BREATHING_TABLE \
|
LED_BREATHING_TABLE \
|
||||||
LED_TABLES \
|
LED_TABLES \
|
||||||
POINTING_DEVICE_ENABLE \
|
POINTING_DEVICE_ENABLE \
|
||||||
VISUALIZER_ENABLE
|
VISUALIZER_ENABLE \
|
||||||
|
DIP_SWITCH_ENABLE
|
||||||
|
|
||||||
OTHER_OPTION_NAMES = \
|
OTHER_OPTION_NAMES = \
|
||||||
UNICODE_ENABLE \
|
UNICODE_ENABLE \
|
||||||
|
Loading…
Reference in New Issue
Block a user