Compare commits
75 Commits
0.7.38
...
led_matrix
Author | SHA1 | Date | |
---|---|---|---|
f8896d8b92 | |||
a5a31a5fc0 | |||
4da9d2ef6f | |||
9160405d39 | |||
23f89ff7cf | |||
e264f0151d | |||
b62ee65c6d | |||
68cf2725aa | |||
6d95082cbf | |||
6799937a3c | |||
51bf3ba3e6 | |||
c8fd015618 | |||
737bca8e51 | |||
d99f6e95e1 | |||
e214f2826e | |||
d60b193932 | |||
454c99d128 | |||
f87908228a | |||
2ee961c9e8 | |||
c44aff5f18 | |||
4b47abc737 | |||
0ab8edb523 | |||
80ded60cad | |||
f033d8113d | |||
267be40793 | |||
af03c5f7fa | |||
165020a670 | |||
97b8ade1aa | |||
1533483bb2 | |||
3dbf08b655 | |||
bc073b817a | |||
233a1e9bcd | |||
a41066beed | |||
a4c008fe90 | |||
4c90277236 | |||
3d53ea439c | |||
f64d9b0621 | |||
8baed70ed1 | |||
9bfacc7c76 | |||
c26faed2b6 | |||
b23f6011c3 | |||
1b1e0977e0 | |||
d263579781 | |||
5c1b7fb502 | |||
5b311965f8 | |||
22cc56bc97 | |||
de5cadd636 | |||
f66b2b1f27 | |||
5dc91ddc60 | |||
550435c1c9 | |||
abfd6ed961 | |||
e3a21348c3 | |||
7662ee71f0 | |||
881f27b461 | |||
81f36ab74d | |||
7677e8adde | |||
162dd3fe19 | |||
9b07098dbd | |||
f360c27f93 | |||
2fc3494fd9 | |||
63f4806d7a | |||
4522519079 | |||
feb116c4f3 | |||
5a3aefed8d | |||
eac6ccff98 | |||
2ac4197b73 | |||
cc5edb9eeb | |||
e1de0d74a6 | |||
6560dffc05 | |||
e796d7b49e | |||
2e7cd98c06 | |||
a48468590a | |||
23178d73fc | |||
bb43010170 | |||
7becbfb44a |
@ -116,7 +116,7 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom
|
VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom pins pinmatrix
|
||||||
|
|
||||||
LED_MATRIX_ENABLE ?= no
|
LED_MATRIX_ENABLE ?= no
|
||||||
ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
|
ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
|
||||||
@ -129,6 +129,20 @@ ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(LED_MATRIX_ENABLE)), pinmatrix)
|
||||||
|
CIE1931_CURVE = yes
|
||||||
|
OPT_DEFS += -DLED_MATRIX_PINMATRIX_ENABLE
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||||
|
SRC += led_matrix_pinmatrix.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(LED_MATRIX_ENABLE)), pins)
|
||||||
|
CIE1931_CURVE = yes
|
||||||
|
OPT_DEFS += -DLED_MATRIX_PINS_ENABLE
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||||
|
SRC += led_matrix_pins.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
|
ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
|
||||||
OPT_DEFS += -DIS31FL3731
|
OPT_DEFS += -DIS31FL3731
|
||||||
COMMON_VPATH += $(DRIVER_PATH)/issi
|
COMMON_VPATH += $(DRIVER_PATH)/issi
|
||||||
@ -150,7 +164,7 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||||
RGB_MATRIX_ENABLE = IS31FL3731
|
RGB_MATRIX_ENABLE = IS31FL3731
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
|
ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
|
||||||
@ -246,6 +260,11 @@ ifneq ($(strip $(BACKLIGHT_ENABLE)), no)
|
|||||||
CIE1931_CURVE = yes
|
CIE1931_CURVE = yes
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
COMMON_VPATH += $(QUANTUM_DIR)/backlight
|
||||||
|
SRC += $(QUANTUM_DIR)/backlight/backlight.c
|
||||||
|
OPT_DEFS += -DBACKLIGHT_ENABLE
|
||||||
|
|
||||||
ifeq ($(strip $(BACKLIGHT_ENABLE)), custom)
|
ifeq ($(strip $(BACKLIGHT_ENABLE)), custom)
|
||||||
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
||||||
endif
|
endif
|
||||||
@ -288,9 +307,9 @@ endif
|
|||||||
|
|
||||||
HAPTIC_ENABLE ?= no
|
HAPTIC_ENABLE ?= no
|
||||||
ifneq ($(strip $(HAPTIC_ENABLE)),no)
|
ifneq ($(strip $(HAPTIC_ENABLE)),no)
|
||||||
COMMON_VPATH += $(DRIVER_PATH)/haptic
|
COMMON_VPATH += $(DRIVER_PATH)/haptic
|
||||||
SRC += haptic.c
|
SRC += haptic.c
|
||||||
OPT_DEFS += -DHAPTIC_ENABLE
|
OPT_DEFS += -DHAPTIC_ENABLE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
|
ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
|
||||||
|
@ -125,14 +125,14 @@ This command examines your environment and alerts you to potential build or flas
|
|||||||
qmk doctor
|
qmk doctor
|
||||||
```
|
```
|
||||||
|
|
||||||
## `qmk list_keyboards`
|
## `qmk list-keyboards`
|
||||||
|
|
||||||
This command lists all the keyboards currently defined in `qmk_firmware`
|
This command lists all the keyboards currently defined in `qmk_firmware`
|
||||||
|
|
||||||
**Usage**:
|
**Usage**:
|
||||||
|
|
||||||
```
|
```
|
||||||
qmk list_keyboards
|
qmk list-keyboards
|
||||||
```
|
```
|
||||||
|
|
||||||
## `qmk new-keymap`
|
## `qmk new-keymap`
|
||||||
|
@ -31,17 +31,17 @@ Here is an example for easy reference:
|
|||||||
```c
|
```c
|
||||||
/* Enums for foo */
|
/* Enums for foo */
|
||||||
enum foo_state {
|
enum foo_state {
|
||||||
FOO_BAR,
|
FOO_BAR,
|
||||||
FOO_BAZ,
|
FOO_BAZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns a value */
|
/* Returns a value */
|
||||||
int foo(void) {
|
int foo(void) {
|
||||||
if (some_condition) {
|
if (some_condition) {
|
||||||
return FOO_BAR;
|
return FOO_BAR;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -310,13 +310,13 @@ This is a [make](https://www.gnu.org/software/make/manual/make.html) file that i
|
|||||||
Use these to enable or disable building certain features. The more you have enabled the bigger your firmware will be, and you run the risk of building a firmware too large for your MCU.
|
Use these to enable or disable building certain features. The more you have enabled the bigger your firmware will be, and you run the risk of building a firmware too large for your MCU.
|
||||||
|
|
||||||
* `BOOTMAGIC_ENABLE`
|
* `BOOTMAGIC_ENABLE`
|
||||||
* Virtual DIP switch configuration(+1000)
|
* Virtual DIP switch configuration
|
||||||
* `MOUSEKEY_ENABLE`
|
* `MOUSEKEY_ENABLE`
|
||||||
* Mouse keys(+4700)
|
* Mouse keys
|
||||||
* `EXTRAKEY_ENABLE`
|
* `EXTRAKEY_ENABLE`
|
||||||
* Audio control and System control(+450)
|
* Audio control and System control
|
||||||
* `CONSOLE_ENABLE`
|
* `CONSOLE_ENABLE`
|
||||||
* Console for debug(+400)
|
* Console for debug
|
||||||
* `COMMAND_ENABLE`
|
* `COMMAND_ENABLE`
|
||||||
* Commands for debug and configuration
|
* Commands for debug and configuration
|
||||||
* `COMBO_ENABLE`
|
* `COMBO_ENABLE`
|
||||||
@ -348,7 +348,7 @@ Use these to enable or disable building certain features. The more you have enab
|
|||||||
* `NO_USB_STARTUP_CHECK`
|
* `NO_USB_STARTUP_CHECK`
|
||||||
* Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master.
|
* Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master.
|
||||||
* `LINK_TIME_OPTIMIZATION_ENABLE`
|
* `LINK_TIME_OPTIMIZATION_ENABLE`
|
||||||
= Enables Link Time Optimization (`LTO`) when compiling the keyboard. This makes the process take longer, but can significantly reduce the compiled size (and since the firmware is small, the added time is not noticable). However, this will automatically disable the old Macros and Functions features automatically, as these break when `LTO` is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION`
|
= Enables Link Time Optimization (`LTO`) when compiling the keyboard. This makes the process take longer, but can significantly reduce the compiled size (and since the firmware is small, the added time is not noticable). However, this will automatically disable the old Macros and Functions features automatically, as these break when `LTO` is enabled. It does this by automatically defining `NO_ACTION_MACRO` and `NO_ACTION_FUNCTION`
|
||||||
|
|
||||||
## USB Endpoint Limitations
|
## USB Endpoint Limitations
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
QMK presents itself to the host as a regular HID keyboard device, and as such requires no special drivers. However, in order to flash your keyboard on Windows, the bootloader device that appears when you reset the board often *does*.
|
QMK presents itself to the host as a regular HID keyboard device, and as such requires no special drivers. However, in order to flash your keyboard on Windows, the bootloader device that appears when you reset the board often *does*.
|
||||||
|
|
||||||
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the Halfkay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
|
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
|
||||||
|
|
||||||
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with Msys2 or WSL, the `qmk_install.sh` script will have asked if you want it to install the drivers for you.
|
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2 or WSL, the `qmk_install.sh` script will have asked if you want it to install the drivers for you.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ Finally, unplug and replug the keyboard to make sure the new driver has been loa
|
|||||||
|
|
||||||
## Recovering from Installation to Wrong Device
|
## Recovering from Installation to Wrong Device
|
||||||
|
|
||||||
If you find that you can no longer type with the keyboard, you may have installed the driver onto the keyboard itself instead of the bootloader. You can easily confirm this in Zadig - a healthy keyboard has the `HidUsb` driver installed on all of its interfaces:
|
If you find that you can no longer type with the keyboard, you may have accidentally replaced the driver for the keyboard itself instead of for the bootloader. This can happen when the keyboard is not in the bootloader mode. You can easily confirm this in Zadig - a healthy keyboard has the `HidUsb` driver installed on all of its interfaces:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@ -44,3 +44,5 @@ Right-click it and hit **Uninstall device**. Make sure to tick **Delete the driv
|
|||||||

|

|
||||||
|
|
||||||
Click **Action → Scan for hardware changes**. At this point, you should be able to type again. Double check in Zadig that the keyboard device(s) are using the `HidUsb` driver. If so, you're all done, and your board should be functional again!
|
Click **Action → Scan for hardware changes**. At this point, you should be able to type again. Double check in Zadig that the keyboard device(s) are using the `HidUsb` driver. If so, you're all done, and your board should be functional again!
|
||||||
|
|
||||||
|
?> A full reboot of your computer may sometimes be necessary at this point, to get Windows to pick up the new driver.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
This is an integration of Peter Fleury's LCD library. This page will explain the basics. [For in depth documentation visit his page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
|
This is an integration of Peter Fleury's LCD library. This page will explain the basics. [For in depth documentation visit his page.](http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__lcd.html)
|
||||||
|
|
||||||
You can enable support for HD44780 Displays by setting the `HD44780_ENABLE` flag in your keyboards `rules.mk` to yes. This will use about 400 KB of extra space.
|
You can enable support for HD44780 Displays by setting the `HD44780_ENABLE` flag in your keyboards `rules.mk` to yes.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ Uncomment the section labled HD44780 and change the parameters as needed.
|
|||||||
#define LCD_DATA3_PORT LCD_PORT //< port for 4bit data bit 3
|
#define LCD_DATA3_PORT LCD_PORT //< port for 4bit data bit 3
|
||||||
#define LCD_DATA0_PIN 4 //< pin for 4bit data bit 0
|
#define LCD_DATA0_PIN 4 //< pin for 4bit data bit 0
|
||||||
#define LCD_DATA1_PIN 5 //< pin for 4bit data bit 1
|
#define LCD_DATA1_PIN 5 //< pin for 4bit data bit 1
|
||||||
#define LCD_DATA2_PIN 6 //< pin for 4bit data bit 2
|
#define LCD_DATA2_PIN 6 //< pin for 4bit data bit 2
|
||||||
#define LCD_DATA3_PIN 7 //< pin for 4bit data bit 3
|
#define LCD_DATA3_PIN 7 //< pin for 4bit data bit 3
|
||||||
#define LCD_RS_PORT LCD_PORT //< port for RS line
|
#define LCD_RS_PORT LCD_PORT //< port for RS line
|
||||||
#define LCD_RS_PIN 3 //< pin for RS line
|
#define LCD_RS_PIN 3 //< pin for RS line
|
||||||
@ -39,14 +39,14 @@ Uncomment the section labled HD44780 and change the parameters as needed.
|
|||||||
|
|
||||||
Should you need to configure other properties you can copy them from `quantum/hd44780.h` and set them in your `config.h`
|
Should you need to configure other properties you can copy them from `quantum/hd44780.h` and set them in your `config.h`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
To initialize your display, call `lcd_init()` with one of these parameters:
|
To initialize your display, call `lcd_init()` with one of these parameters:
|
||||||
````
|
````
|
||||||
LCD_DISP_OFF : display off
|
LCD_DISP_OFF : display off
|
||||||
LCD_DISP_ON : display on, cursor off
|
LCD_DISP_ON : display on, cursor off
|
||||||
LCD_DISP_ON_CURSOR : display on, cursor on
|
LCD_DISP_ON_CURSOR : display on, cursor on
|
||||||
LCD_DISP_ON_CURSOR_BLINK : display on, cursor on flashing
|
LCD_DISP_ON_CURSOR_BLINK : display on, cursor on flashing
|
||||||
````
|
````
|
||||||
This is best done in your keyboards `matrix_init_kb` or your keymaps `matrix_init_user`.
|
This is best done in your keyboards `matrix_init_kb` or your keymaps `matrix_init_user`.
|
||||||
It is advised to clear the display before use.
|
It is advised to clear the display before use.
|
||||||
|
@ -16,7 +16,7 @@ First, enable Key Lock by setting `KEY_LOCK_ENABLE = yes` in your `rules.mk`. Th
|
|||||||
|
|
||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
Key Lock is only able to hold standard action keys and [One Shot modifier](quantum_keycodes.md#one-shot-keys) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
|
Key Lock is only able to hold standard action keys and [One Shot modifier](feature_advanced_keycodes.md#one-shot-keys) keys (for example, if you have your Shift defined as `OSM(KC_LSFT)`).
|
||||||
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
|
This does not include any of the QMK special functions (except One Shot modifiers), or shifted versions of keys such as `KC_LPRN`. If it's in the [Basic Keycodes](keycodes_basic.md) list, it can be held.
|
||||||
|
|
||||||
Switching layers will not cancel the Key Lock.
|
Switching layers will not cancel the Key Lock.
|
||||||
|
@ -1,10 +1,66 @@
|
|||||||
# LED Matrix Lighting
|
# LED Matrix Lighting
|
||||||
|
|
||||||
This feature allows you to use LED matrices driven by external drivers. It hooks into the backlight system so you can use the same keycodes as backlighting to control it.
|
This feature allows you to use LED matrices driven by external drivers. It hooks into the [backlight subsystem](feature_backlight.md) so you can use the same keycodes as backlighting to control it. Many of the same configuration settings apply as well.
|
||||||
|
|
||||||
If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_rgb_matrix.md) instead.
|
If you want to use RGB LED's you should use the [RGB Matrix Subsystem](feature_rgb_matrix.md) instead.
|
||||||
|
|
||||||
## Driver configuration
|
LED Matrix supports LEDs that are connected directly to the MCU and LEDs connected to an external controller IC (such as the IS31FL3731 from ISSI.)
|
||||||
|
|
||||||
|
## Directly Connected LEDs
|
||||||
|
|
||||||
|
There are two ways that LEDs can be connected to the LED Matrix-
|
||||||
|
|
||||||
|
* Direct Pin: One pin per LED
|
||||||
|
* Direct Pin Matrix: LED matrix with rows and columns
|
||||||
|
|
||||||
|
### Direct Pin
|
||||||
|
|
||||||
|
This driver uses LEDs that are connected directly to to a pin on the PCB. If you are not familiar with how to wire an LED directly to a microcontroller you can [follow this guide](https://create.arduino.cc/projecthub/rowan07/make-a-simple-led-circuit-ce8308). The process is similar for every microcontroller that QMK supports.
|
||||||
|
|
||||||
|
You can configure the driver to either source or sink current, but that setting applies to all LEDs.
|
||||||
|
|
||||||
|
Settings needed in `rules.mk`:
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `BACKLIGHT_ENABLE = yes` | Turn on the backlight subsystem |
|
||||||
|
| `LED_MATRIX_ENABLE = pins` | Enable the LED Matrix subsystem and configure it for directly connected LEDs |
|
||||||
|
|
||||||
|
Settings needed in `config.h`:
|
||||||
|
|
||||||
|
| Variable | Description | Default |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `LED_MATRIX_PINS` | A list of pins with connected LEDs. | `{ }` |
|
||||||
|
| `LED_DRIVER_LED_COUNT` | The number of LEDs connected to pins |
|
||||||
|
|
||||||
|
### Direct Pin Matrix
|
||||||
|
|
||||||
|
This driver supports driving an LED matrix that is connected directly to the local controller in a common-row cathode orientation. For more general information on LED matrices and how to design them there are several useful outside resources:
|
||||||
|
|
||||||
|
* https://www.circuitspecialists.com/blog/build-8x8-led-matrix/
|
||||||
|
* https://www.instructables.com/id/Make-Your-Own-LED-Matrix-/
|
||||||
|
* https://appelsiini.net/2011/how-does-led-matrix-work/
|
||||||
|
|
||||||
|
Settings needed in `rules.mk`:
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `BACKLIGHT_ENABLE = yes` | Turn on the backlight subsystem |
|
||||||
|
| `LED_MATRIX_ENABLE = pinmatrix` | Enable the LED Matrix subsystem and configure it for a matrix |
|
||||||
|
|
||||||
|
Settings needed in `config.h`:
|
||||||
|
|
||||||
|
| Variable | Description | Default |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `LED_DRIVER_LED_COUNT` | (Required) How many LED lights are present | (none) |
|
||||||
|
| `LED_MATRIX_COLS` | (Required) The number of columns (current sources) your matrix has | (none) |
|
||||||
|
| `LED_MATRIX_COL_PINS` | (Required) A list of column pins, EG `{ B1, B2, B3, B4 }`| (none) |
|
||||||
|
| `LED_MATRIX_ROWS` | (Required) The number of rows (current sinks) your matrix has | (none) |
|
||||||
|
| `LED_MATRIX_ROW_PINS` | (Required) A list of row pins, EG `{ B5, B6, B7, B8 }` | (none) |
|
||||||
|
|
||||||
|
## LED Driver ICs
|
||||||
|
|
||||||
|
You can also use an LED driver chip. The IS31 series of ICs is popular and well supported in QMK.
|
||||||
|
|
||||||
### IS31FL3731
|
### IS31FL3731
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Terminal
|
# Terminal
|
||||||
|
|
||||||
> This feature is currently *huge* at 4400 bytes, and should probably only be put on boards with a lot of memory, or for fun.
|
> This feature is currently *huge*, and should probably only be put on boards with a lot of memory, or for fun.
|
||||||
|
|
||||||
The terminal feature is a command-line-like interface designed to communicate through a text editor with keystrokes. It's beneficial to turn off auto-indent features in your editor.
|
The terminal feature is a command-line-like interface designed to communicate through a text editor with keystrokes. It's beneficial to turn off auto-indent features in your editor.
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ Outputs the last 5 commands entered
|
|||||||
1. help
|
1. help
|
||||||
2. about
|
2. about
|
||||||
3. keymap 0
|
3. keymap 0
|
||||||
4. help
|
4. help
|
||||||
5. flush-buffer
|
5. flush-buffer
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ Tester votre clavier est normalement assez simple. Appuyez chaque touche de votr
|
|||||||
|
|
||||||
Note: ces programmes ne sont ni fournis ni approuvés par QMK.
|
Note: ces programmes ne sont ni fournis ni approuvés par QMK.
|
||||||
|
|
||||||
* [Switch Hitter](https://elitekeyboards.com/switchhitter.php) (Windows seulement)
|
* [QMK Configurator](https://config.qmk.fm/#/test/) (Web)
|
||||||
|
* [Switch Hitter](https://web.archive.org/web/20190413233743/https://elitekeyboards.com/switchhitter.php) (Windows seulement)
|
||||||
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Mac seulement)
|
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Mac seulement)
|
||||||
* [Keyboard Tester](http://www.keyboardtester.com) (Web)
|
* [Keyboard Tester](http://www.keyboardtester.com) (Web)
|
||||||
* [Keyboard Checker](http://keyboardchecker.com) (Web)
|
* [Keyboard Checker](http://keyboardchecker.com) (Web)
|
||||||
|
@ -41,8 +41,6 @@ Set these variables to `no` to disable them, and `yes` to enable them.
|
|||||||
|
|
||||||
This allows you to hold a key and the salt key (space by default) and have access to a various EEPROM settings that persist over power loss. It's advised you keep this disabled, as the settings are often changed by accident, and produce confusing results that makes it difficult to debug. It's one of the more common problems encountered in help sessions.
|
This allows you to hold a key and the salt key (space by default) and have access to a various EEPROM settings that persist over power loss. It's advised you keep this disabled, as the settings are often changed by accident, and produce confusing results that makes it difficult to debug. It's one of the more common problems encountered in help sessions.
|
||||||
|
|
||||||
Consumes about 1000 bytes.
|
|
||||||
|
|
||||||
`MOUSEKEY_ENABLE`
|
`MOUSEKEY_ENABLE`
|
||||||
|
|
||||||
This gives you control over cursor movements and clicks via keycodes/custom functions.
|
This gives you control over cursor movements and clicks via keycodes/custom functions.
|
||||||
@ -67,8 +65,6 @@ To see the text, open `hid_listen` and enjoy looking at your printed messages.
|
|||||||
|
|
||||||
**NOTE:** Do not include *uprint* messages in anything other than your keymap code. It must not be used within the QMK system framework. Otherwise, you will bloat other people's .hex files.
|
**NOTE:** Do not include *uprint* messages in anything other than your keymap code. It must not be used within the QMK system framework. Otherwise, you will bloat other people's .hex files.
|
||||||
|
|
||||||
Consumes about 400 bytes.
|
|
||||||
|
|
||||||
`COMMAND_ENABLE`
|
`COMMAND_ENABLE`
|
||||||
|
|
||||||
This enables magic commands, typically fired with the default magic key combo `LSHIFT+RSHIFT+KEY`. Magic commands include turning on debugging messages (`MAGIC+D`) or temporarily toggling NKRO (`MAGIC+N`).
|
This enables magic commands, typically fired with the default magic key combo `LSHIFT+RSHIFT+KEY`. Magic commands include turning on debugging messages (`MAGIC+D`) or temporarily toggling NKRO (`MAGIC+N`).
|
||||||
@ -125,11 +121,9 @@ Use this to debug changes to variable values, see the [tracing variables](unit_t
|
|||||||
|
|
||||||
This enables using the Quantum SYSEX API to send strings (somewhere?)
|
This enables using the Quantum SYSEX API to send strings (somewhere?)
|
||||||
|
|
||||||
This consumes about 5390 bytes.
|
|
||||||
|
|
||||||
`KEY_LOCK_ENABLE`
|
`KEY_LOCK_ENABLE`
|
||||||
|
|
||||||
This enables [key lock](feature_key_lock.md). This consumes an additional 260 bytes.
|
This enables [key lock](feature_key_lock.md).
|
||||||
|
|
||||||
`SPLIT_KEYBOARD`
|
`SPLIT_KEYBOARD`
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Keyboards with AVR Processors
|
# Keyboards with AVR Processors
|
||||||
|
|
||||||
This page describes the support for for AVR processors in QMK. AVR processors include the atmega32u4, atmega32u2, at90usb1286, and other processors from Atmel Corporation. AVR processors are 8-bit MCU's that are designed to be easy to work with. The most common AVR processors in keyboards have on-board USB and plenty of GPIO for supporting large keyboard matrices. They are the most popular MCU for use in keyboards today.
|
This page describes the support for for AVR processors in QMK. AVR processors include the atmega32u4, atmega32u2, at90usb1286, and other processors from Atmel Corporation. AVR processors are 8-bit MCUs that are designed to be easy to work with. The most common AVR processors in keyboards have on-board USB and plenty of GPIO for supporting large keyboard matrices. They are the most popular MCU for use in keyboards today.
|
||||||
|
|
||||||
If you have not yet you should read the [Keyboard Guidelines](hardware_keyboard_guidelines.md) to get a sense of how keyboards fit into QMK.
|
If you have not yet you should read the [Keyboard Guidelines](hardware_keyboard_guidelines.md) to get a sense of how keyboards fit into QMK.
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Support for SSD1306 based OLED displays. For more information see the [OLED Driv
|
|||||||
|
|
||||||
## uGFX
|
## uGFX
|
||||||
|
|
||||||
You can make use of uGFX within QMK to drive character and graphic LCD's, LED arrays, OLED, TFT, and other display technologies. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
|
You can make use of uGFX within QMK to drive character and graphic LCDs, LED arrays, OLED, TFT, and other display technologies. This needs to be better documented, if you are trying to do this and reading the code doesn't help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) and we can help you through the process.
|
||||||
|
|
||||||
## WS2812 (AVR Only)
|
## WS2812 (AVR Only)
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ Testing your keyboard is usually pretty straightforward. Press every single key
|
|||||||
|
|
||||||
Note: These programs are not provided by or endorsed by QMK.
|
Note: These programs are not provided by or endorsed by QMK.
|
||||||
|
|
||||||
* [Switch Hitter](https://elitekeyboards.com/switchhitter.php) (Windows Only)
|
* [QMK Configurator](https://config.qmk.fm/#/test/) (Web Based)
|
||||||
|
* [Switch Hitter](https://web.archive.org/web/20190413233743/https://elitekeyboards.com/switchhitter.php) (Windows Only)
|
||||||
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Mac Only)
|
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (Mac Only)
|
||||||
* [Keyboard Tester](http://www.keyboardtester.com) (Web Based)
|
* [Keyboard Tester](http://www.keyboardtester.com) (Web Based)
|
||||||
* [Keyboard Checker](http://keyboardchecker.com) (Web Based)
|
* [Keyboard Checker](http://keyboardchecker.com) (Web Based)
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
# Glossary of QMK Terms
|
# Glossary of QMK Terms
|
||||||
|
|
||||||
## ARM
|
## ARM
|
||||||
A line of 32-bit MCU's produced by a number of companies, such as Atmel, Cypress, Kinetis, NXP, ST, and TI.
|
A line of 32-bit MCUs produced by a number of companies, such as Atmel, Cypress, Kinetis, NXP, ST, and TI.
|
||||||
|
|
||||||
## AVR
|
## AVR
|
||||||
A line of 8-bit MCU's produced by [Atmel](http://www.microchip.com/). AVR was the original platform that TMK supported.
|
A line of 8-bit MCUs produced by [Atmel](http://www.microchip.com/). AVR was the original platform that TMK supported.
|
||||||
|
|
||||||
## AZERTY
|
## AZERTY
|
||||||
The standard Français (French) keyboard layout. Named for the first 6 keys on the keyboard.
|
The standard Français (French) keyboard layout. Named for the first 6 keys on the keyboard.
|
||||||
|
|
||||||
## Backlight
|
## Backlight
|
||||||
A generic term for lighting on a keyboard. The backlight is typically, but not always, an array of LED's that shine through keycaps and/or switches.
|
A generic term for lighting on a keyboard. The backlight is typically, but not always, an array of LEDs that shine through keycaps and/or switches.
|
||||||
|
|
||||||
## Bluetooth
|
## Bluetooth
|
||||||
A short range peer to peer wireless protocol. Most common wireless protocol for a keyboard.
|
A short range peer to peer wireless protocol. Most common wireless protocol for a keyboard.
|
||||||
@ -147,7 +147,7 @@ A feature that lets you assign multiple keycodes to the same key based on how ma
|
|||||||
A low-cost AVR development board that is commonly used for hand-wired builds. A teensy is often chosen despite costing a few dollars more due to its halfkay bootloader, which makes flashing very simple.
|
A low-cost AVR development board that is commonly used for hand-wired builds. A teensy is often chosen despite costing a few dollars more due to its halfkay bootloader, which makes flashing very simple.
|
||||||
|
|
||||||
## Underlight
|
## Underlight
|
||||||
A generic term for LEDs that light the underside of the board. These LED's typically shine away from the bottom of the PCB and towards the surface the keyboard rests on.
|
A generic term for LEDs that light the underside of the board. These LEDs typically shine away from the bottom of the PCB and towards the surface the keyboard rests on.
|
||||||
|
|
||||||
## Unicode
|
## Unicode
|
||||||
In the larger computer world Unicode is a set of encoding schemes for representing characters in any language. As it relates to QMK it means using various OS schemes to send unicode codepoints instead of scancodes.
|
In the larger computer world Unicode is a set of encoding schemes for representing characters in any language. As it relates to QMK it means using various OS schemes to send unicode codepoints instead of scancodes.
|
||||||
|
@ -22,7 +22,7 @@ This section of code is called "The Main Loop" because it's responsible for loop
|
|||||||
keyboard_task();
|
keyboard_task();
|
||||||
```
|
```
|
||||||
|
|
||||||
This is where all the keyboard specific functionality is dispatched. The source code for `keyboard_task()` can be found in [tmk_core/common/keyboard.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/keyboard.c#L216), and it is responsible for detecting changes in the matrix and turning status LED's on and off.
|
This is where all the keyboard specific functionality is dispatched. The source code for `keyboard_task()` can be found in [tmk_core/common/keyboard.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/keyboard.c#L216), and it is responsible for detecting changes in the matrix and turning status LEDs on and off.
|
||||||
|
|
||||||
Within `keyboard_task()` you'll find code to handle:
|
Within `keyboard_task()` you'll find code to handle:
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ Within `keyboard_task()` you'll find code to handle:
|
|||||||
* Mouse Handling
|
* Mouse Handling
|
||||||
* Serial Link(s)
|
* Serial Link(s)
|
||||||
* Visualizer
|
* Visualizer
|
||||||
* Keyboard status LED's (Caps Lock, Num Lock, Scroll Lock)
|
* Keyboard status LEDs (Caps Lock, Num Lock, Scroll Lock)
|
||||||
|
|
||||||
#### Matrix Scanning
|
#### Matrix Scanning
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ FIXME: This needs to be written
|
|||||||
|
|
||||||
FIXME: This needs to be written
|
FIXME: This needs to be written
|
||||||
|
|
||||||
#### Keyboard state LED's (Caps Lock, Num Lock, Scroll Lock)
|
#### Keyboard state LEDs (Caps Lock, Num Lock, Scroll Lock)
|
||||||
|
|
||||||
FIXME: This needs to be written
|
FIXME: This needs to be written
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
注意:这些程序不是由QMK提供或认可的。
|
注意:这些程序不是由QMK提供或认可的。
|
||||||
|
|
||||||
* [Switch Hitter](https://elitekeyboards.com/switchhitter.php) (仅Windows)
|
* [QMK Configurator](https://config.qmk.fm/#/test/) (网页版)
|
||||||
|
* [Switch Hitter](https://web.archive.org/web/20190413233743/https://elitekeyboards.com/switchhitter.php) (仅Windows)
|
||||||
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (仅Mac)
|
* [Keyboard Viewer](https://www.imore.com/how-use-keyboard-viewer-your-mac) (仅Mac)
|
||||||
* [Keyboard Tester](http://www.keyboardtester.com) (网页版)
|
* [Keyboard Tester](http://www.keyboardtester.com) (网页版)
|
||||||
* [Keyboard Checker](http://keyboardchecker.com) (网页版)
|
* [Keyboard Checker](http://keyboardchecker.com) (网页版)
|
||||||
|
@ -32,27 +32,17 @@
|
|||||||
|
|
||||||
static uint8_t i2c_address;
|
static uint8_t i2c_address;
|
||||||
|
|
||||||
// ChibiOS uses two initialization structure for v1 and v2/v3 i2c APIs.
|
|
||||||
// The F1 series uses the v1 api, which have to initialized this way.
|
|
||||||
#ifdef STM32F103xB
|
|
||||||
static const I2CConfig i2cconfig = {
|
|
||||||
OPMODE_I2C,
|
|
||||||
400000,
|
|
||||||
FAST_DUTY_CYCLE_2,
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
// This configures the I2C clock to 400khz assuming a 72Mhz clock
|
|
||||||
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
|
||||||
static const I2CConfig i2cconfig = {
|
static const I2CConfig i2cconfig = {
|
||||||
#ifdef USE_I2CV1
|
#ifdef USE_I2CV1
|
||||||
I2C1_OPMODE,
|
I2C1_OPMODE,
|
||||||
I2C1_CLOCK_SPEED,
|
I2C1_CLOCK_SPEED,
|
||||||
I2C1_DUTY_CYCLE,
|
I2C1_DUTY_CYCLE,
|
||||||
#else
|
#else
|
||||||
|
// This configures the I2C clock to 400khz assuming a 72Mhz clock
|
||||||
|
// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html
|
||||||
STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0
|
STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
static i2c_status_t chibios_to_qmk(const msg_t* status) {
|
static i2c_status_t chibios_to_qmk(const msg_t* status) {
|
||||||
switch (*status) {
|
switch (*status) {
|
||||||
|
103
drivers/led/led_matrix_pinmatrix.c
Normal file
103
drivers/led/led_matrix_pinmatrix.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* Copyright 2017 Jason Williams
|
||||||
|
* Copyright 2018 Jack Humbert
|
||||||
|
* Copyright 2019 Clueboard
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
# include <avr/interrupt.h>
|
||||||
|
# include <avr/io.h>
|
||||||
|
# include <util/delay.h>
|
||||||
|
# define led_wait_us(us) wait_us(us)
|
||||||
|
#else
|
||||||
|
# include "ch.h"
|
||||||
|
# include "hal.h"
|
||||||
|
# define led_wait_us(us) chSysPolledDelayX(US2RTC(STM32_SYSCLK, us))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "led_matrix_pinmatrix.h"
|
||||||
|
#include "led_tables.h"
|
||||||
|
#include "progmem.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* g_pwm_buffer is an array that represents the duty cycle (0-255) for each LED.
|
||||||
|
* FIXME: Map this from the wiring matrix to a physical location matrix at some point
|
||||||
|
*/
|
||||||
|
uint8_t g_pwm_buffer[LED_MATRIX_ROWS * LED_MATRIX_COLS];
|
||||||
|
const pin_t led_row_pins[LED_MATRIX_ROWS] = LED_MATRIX_ROW_PINS;
|
||||||
|
const pin_t led_col_pins[LED_MATRIX_COLS] = LED_MATRIX_COL_PINS;
|
||||||
|
|
||||||
|
|
||||||
|
void led_matrix_pinmatrix_init_pins(void) {
|
||||||
|
/* Set all pins to output, we are not interested in reading any information.
|
||||||
|
*/
|
||||||
|
for (uint8_t x = 0; x < LED_MATRIX_ROWS; x++) {
|
||||||
|
setPinOutput(led_row_pins[x]);
|
||||||
|
writePinLow(led_row_pins[x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t x = 0; x < LED_MATRIX_COLS; x++) {
|
||||||
|
setPinOutput(led_col_pins[x]);
|
||||||
|
writePinLow(led_col_pins[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pinmatrix_set_value(int index, uint8_t value) {
|
||||||
|
/* Set the brighness for a single LED.
|
||||||
|
*/
|
||||||
|
if (index >= 0 && index < LED_DRIVER_LED_COUNT) {
|
||||||
|
g_pwm_buffer[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pinmatrix_set_value_all(uint8_t value) {
|
||||||
|
/* Set the brighness for all LEDs.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < LED_DRIVER_LED_COUNT; i++) {
|
||||||
|
led_matrix_pinmatrix_set_value(i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pinmatrix_flush(void) {
|
||||||
|
/* This is a basic bit-banged pwm implementation.
|
||||||
|
*/
|
||||||
|
uint8_t led_count = 0;
|
||||||
|
for (uint8_t row = 0; row < LED_MATRIX_ROWS; row++) {
|
||||||
|
writePinLow(led_row_pins[row]);
|
||||||
|
for (uint8_t col = 0; col < LED_MATRIX_COLS; col++) {
|
||||||
|
/* We spend ~128us on each LED, dividing that time between lit and unlit.
|
||||||
|
*/
|
||||||
|
const uint8_t brightness = pgm_read_byte(&CIE1931_CURVE[g_pwm_buffer[led_count]]) / 2;
|
||||||
|
if (brightness > 0) {
|
||||||
|
writePinHigh(led_col_pins[col]);
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
if (i == brightness) {
|
||||||
|
writePinLow(led_col_pins[col]);
|
||||||
|
}
|
||||||
|
led_wait_us(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
led_wait_us(128);
|
||||||
|
}
|
||||||
|
led_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
drivers/led/led_matrix_pinmatrix.h
Normal file
30
drivers/led/led_matrix_pinmatrix.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* Copyright 2017 Jason Williams
|
||||||
|
* Copyright 2018 Jack Humbert
|
||||||
|
* Copyright 2019 Clueboard
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LED_MATRIX_PINMATRIX_DRIVER_H
|
||||||
|
#define LED_MATRIX_PINMATRIX_DRIVER_H
|
||||||
|
|
||||||
|
void led_matrix_pinmatrix_init_pins(void);
|
||||||
|
void led_matrix_pinmatrix_set_value(int index, uint8_t value);
|
||||||
|
void led_matrix_pinmatrix_set_value_all(uint8_t value);
|
||||||
|
void led_matrix_pinmatrix_flush(void);
|
||||||
|
void led_matrix_pinmatrix_select_row(uint8_t row);
|
||||||
|
void led_matrix_pinmatrix_unselect_row(uint8_t row);
|
||||||
|
void led_matrix_pinmatrix_unselect_rows(void);
|
||||||
|
|
||||||
|
#endif // LED_MATRIX_PINMATRIX_DRIVER_H
|
95
drivers/led/led_matrix_pins.c
Normal file
95
drivers/led/led_matrix_pins.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* Copyright 2017 Jason Williams
|
||||||
|
* Copyright 2018 Jack Humbert
|
||||||
|
* Copyright 2019 Clueboard
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
# include <avr/interrupt.h>
|
||||||
|
# include <avr/io.h>
|
||||||
|
# include <util/delay.h>
|
||||||
|
# define led_wait_us(us) wait_us(us)
|
||||||
|
#else
|
||||||
|
# include "ch.h"
|
||||||
|
# include "hal.h"
|
||||||
|
# define led_wait_us(us) chSysPolledDelayX(US2RTC(STM32_SYSCLK, us))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "led_matrix_pins.h"
|
||||||
|
#include "led_tables.h"
|
||||||
|
#include "progmem.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* g_pwm_buffer is an array that represents the duty cycle (0-255) for each LED.
|
||||||
|
*/
|
||||||
|
uint8_t g_pwm_buffer[LED_DRIVER_LED_COUNT];
|
||||||
|
const pin_t led_pins[LED_DRIVER_LED_COUNT] = LED_MATRIX_PINS;
|
||||||
|
|
||||||
|
#ifdef LED_MATRIX_PIN_SINK
|
||||||
|
# define led_pin_on(pin) writePinLow(pin)
|
||||||
|
# define led_pin_off(pin) writePinHigh(pin)
|
||||||
|
#else
|
||||||
|
# define led_pin_on(pin) writePinHigh(pin)
|
||||||
|
# define led_pin_off(pin) writePinLow(pin)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void led_matrix_pins_init_pins(void) {
|
||||||
|
/* Set all pins to output, we are not interested in reading any information.
|
||||||
|
*/
|
||||||
|
for (uint8_t x = 0; x < LED_DRIVER_LED_COUNT; x++) {
|
||||||
|
setPinOutput(led_pins[x]);
|
||||||
|
led_pin_off(led_pins[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pins_set_value(int index, uint8_t value) {
|
||||||
|
/* Set the brighness for a single LED.
|
||||||
|
*/
|
||||||
|
if (index >= 0 && index < LED_DRIVER_LED_COUNT) {
|
||||||
|
g_pwm_buffer[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pins_set_value_all(uint8_t value) {
|
||||||
|
/* Set the brighness for all LEDs.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < LED_DRIVER_LED_COUNT; i++) {
|
||||||
|
led_matrix_pins_set_value(i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_matrix_pins_flush(void) {
|
||||||
|
/* This is a basic bit-banged pwm implementation.
|
||||||
|
*/
|
||||||
|
for (uint8_t i = 0; i < LED_DRIVER_LED_COUNT; i++) {
|
||||||
|
/* We spend ~1.3ms on each LED, dividing that time between lit and unlit.
|
||||||
|
*/
|
||||||
|
if (g_pwm_buffer[i] > 0) {
|
||||||
|
uint8_t brightness = pgm_read_byte(&CIE1931_CURVE[g_pwm_buffer[i]]) / 2;
|
||||||
|
led_pin_on(led_pins[i]);
|
||||||
|
led_wait_us(brightness);
|
||||||
|
led_pin_off(led_pins[i]);
|
||||||
|
led_wait_us(128 - brightness);
|
||||||
|
} else {
|
||||||
|
led_wait_us(128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
drivers/led/led_matrix_pins.h
Normal file
30
drivers/led/led_matrix_pins.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* Copyright 2017 Jason Williams
|
||||||
|
* Copyright 2018 Jack Humbert
|
||||||
|
* Copyright 2019 Clueboard
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LED_MATRIX_PINS_DRIVER_H
|
||||||
|
#define LED_MATRIX_PINS_DRIVER_H
|
||||||
|
|
||||||
|
void led_matrix_pins_init_pins(void);
|
||||||
|
void led_matrix_pins_set_value(int index, uint8_t value);
|
||||||
|
void led_matrix_pins_set_value_all(uint8_t value);
|
||||||
|
void led_matrix_pins_flush(void);
|
||||||
|
void led_matrix_pins_select_row(uint8_t row);
|
||||||
|
void led_matrix_pins_unselect_row(uint8_t row);
|
||||||
|
void led_matrix_pins_unselect_rows(void);
|
||||||
|
|
||||||
|
#endif // LED_MATRIX_PINS_DRIVER_H
|
@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"LAYOUT_60_iso": {
|
"LAYOUT_60_iso": {
|
||||||
"layout": [{"label":"\u00ac", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"\"", "x":2, "y":0}, {"label":"\u00a3", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"Backspace", "x":13, "y":0, "w":2}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"Enter", "x":13.75, "y":1, "w":1.25, "h":2}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"@", "x":11.75, "y":2}, {"label":"~", "x":12.75, "y":2}, {"label":"Shift", "x":0, "y":3, "w":1.25}, {"label":"|", "x":1.25, "y":3}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":2.75}, {"label":"Ctrl", "x":0, "y":4, "w":1.25}, {"label":"Win", "x":1.25, "y":4, "w":1.25}, {"label":"Alt", "x":2.5, "y":4, "w":1.25}, {"x":3.75, "y":4, "w":6.25}, {"label":"AltGr", "x":10, "y":4, "w":1.25}, {"label":"Win", "x":11.25, "y":4, "w":1.25}, {"label":"Menu", "x":12.5, "y":4, "w":1.25}, {"label":"Ctrl", "x":13.75, "y":4, "w":1.25}]
|
"layout": [{"label":"\u00ac", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"\"", "x":2, "y":0}, {"label":"\u00a3", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"Backspace", "x":13, "y":0, "w":2}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"@", "x":11.75, "y":2}, {"label":"~", "x":12.75, "y":2}, {"label":"Enter", "x":13.75, "y":1, "w":1.25, "h":2}, {"label":"Shift", "x":0, "y":3, "w":1.25}, {"label":"|", "x":1.25, "y":3}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":2.75}, {"label":"Ctrl", "x":0, "y":4, "w":1.25}, {"label":"Win", "x":1.25, "y":4, "w":1.25}, {"label":"Alt", "x":2.5, "y":4, "w":1.25}, {"x":3.75, "y":4, "w":6.25}, {"label":"AltGr", "x":10, "y":4, "w":1.25}, {"label":"Win", "x":11.25, "y":4, "w":1.25}, {"label":"Menu", "x":12.5, "y":4, "w":1.25}, {"label":"Ctrl", "x":13.75, "y":4, "w":1.25}]
|
||||||
},
|
},
|
||||||
|
|
||||||
"LAYOUT_60_ansi_split_bs_rshift": {
|
"LAYOUT_60_ansi_split_bs_rshift": {
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
/* USB Device descriptor parameter */
|
/* USB Device descriptor parameter */
|
||||||
#define VENDOR_ID 0xFEED
|
#define VENDOR_ID 0xFEED
|
||||||
#define PRODUCT_ID 0x2010
|
|
||||||
#define DEVICE_VER 0x0001
|
|
||||||
#define MANUFACTURER 1up Keyboards
|
#define MANUFACTURER 1up Keyboards
|
||||||
#define PRODUCT Sweet16
|
#define PRODUCT Sweet16
|
||||||
#define DESCRIPTION 4x4 grid
|
#define DESCRIPTION 4x4 grid
|
||||||
@ -14,34 +12,11 @@
|
|||||||
#define MATRIX_ROWS 4
|
#define MATRIX_ROWS 4
|
||||||
#define MATRIX_COLS 4
|
#define MATRIX_COLS 4
|
||||||
|
|
||||||
/* key matrix pins */
|
|
||||||
#define MATRIX_ROW_PINS { F4, F5, F6, F7 }
|
|
||||||
#define MATRIX_COL_PINS { D1, D0, D4, C6 }
|
|
||||||
#define UNUSED_PINS
|
|
||||||
|
|
||||||
/* COL2ROW or ROW2COL */
|
|
||||||
#define DIODE_DIRECTION COL2ROW
|
|
||||||
|
|
||||||
/* number of backlight levels */
|
/* number of backlight levels */
|
||||||
|
#define BACKLIGHT_LEVELS 10
|
||||||
#ifdef BACKLIGHT_PIN
|
|
||||||
#define BACKLIGHT_LEVELS 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set 0 if debouncing isn't needed */
|
|
||||||
#define DEBOUNCE 5
|
|
||||||
|
|
||||||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
||||||
#define LOCKING_SUPPORT_ENABLE
|
#define LOCKING_SUPPORT_ENABLE
|
||||||
|
|
||||||
/* Locking resynchronize hack */
|
/* Locking resynchronize hack */
|
||||||
#define LOCKING_RESYNC_ENABLE
|
#define LOCKING_RESYNC_ENABLE
|
||||||
|
|
||||||
#define RGB_DI_PIN B1
|
|
||||||
#ifdef RGB_DI_PIN
|
|
||||||
#define RGBLIGHT_ANIMATIONS
|
|
||||||
#define RGBLED_NUM 1
|
|
||||||
#define RGBLIGHT_HUE_STEP 8
|
|
||||||
#define RGBLIGHT_SAT_STEP 8
|
|
||||||
#define RGBLIGHT_VAL_STEP 8
|
|
||||||
#endif
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"keyboard_name": "Sweet 16",
|
"keyboard_name": "Sweet 16",
|
||||||
"url": "",
|
"url": "",
|
||||||
"maintainer": "qmk",
|
"maintainer": "skullydazed",
|
||||||
"width": 4,
|
"width": 4,
|
||||||
"height": 4,
|
"height": 4,
|
||||||
"layouts": {
|
"layouts": {
|
||||||
|
@ -25,21 +25,15 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_set_user(uint8_t usb_led) {
|
#ifdef ENCODER_ENABLE
|
||||||
|
#include "encoder.h"
|
||||||
#ifndef CONVERT_TO_PROTON_C
|
void encoder_update_user(int8_t index, bool clockwise) {
|
||||||
/* Map RXLED to USB_LED_NUM_LOCK */
|
if (index == 0) { /* First encoder */
|
||||||
if (usb_led & (1 << USB_LED_NUM_LOCK)) {
|
if (clockwise) {
|
||||||
DDRB |= (1 << 0); PORTB &= ~(1 << 0);
|
tap_code(KC_VOLU);
|
||||||
} else {
|
} else {
|
||||||
DDRB &= ~(1 << 0); PORTB &= ~(1 << 0);
|
tap_code(KC_VOLD);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Map TXLED to USB_LED_CAPS_LOCK */
|
|
||||||
if (usb_led & (1 << USB_LED_CAPS_LOCK)) {
|
|
||||||
DDRD |= (1 << 5); PORTD &= ~(1 << 5);
|
|
||||||
} else {
|
|
||||||
DDRD &= ~(1 << 5); PORTD &= ~(1 << 5);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
39
keyboards/1upkeyboards/sweet16/keymaps/tester/keymap.c
Normal file
39
keyboards/1upkeyboards/sweet16/keymaps/tester/keymap.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum custom_keycodes {
|
||||||
|
UP_URL = SAFE_RANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
LAYOUT_ortho_4x4(
|
||||||
|
KC_0, KC_1, KC_2, KC_3,
|
||||||
|
KC_4, KC_5, KC_6, KC_7,
|
||||||
|
KC_8, KC_9, KC_A, KC_B,
|
||||||
|
KC_C, RESET, KC_E, BL_STEP
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
switch (keycode) {
|
||||||
|
case UP_URL:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
SEND_STRING("http://1upkeyboards.com");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENCODER_ENABLE
|
||||||
|
#include "encoder.h"
|
||||||
|
void encoder_update_user(int8_t index, bool clockwise) {
|
||||||
|
if (index == 0) { /* First encoder */
|
||||||
|
if (clockwise) {
|
||||||
|
tap_code(KC_VOLU);
|
||||||
|
} else {
|
||||||
|
tap_code(KC_VOLD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,13 +1,12 @@
|
|||||||
# Sweet 16 Macropad
|
# Sweet 16 Macropad
|
||||||
|
|
||||||
A 4x4 numpad/macro pad sold by 1up Keyboards - designed by Bishop Keyboards
|
A 4x4 numpad/macro pad sold by 1up Keyboards.
|
||||||
|
|
||||||
Keyboard Maintainer: QMK Community
|
* Keyboard Maintainer: skullydazed
|
||||||
Hardware Supported: Sweet16 Keyboard PCB
|
* Hardware Supported: Sweet16 Keyboard PCB
|
||||||
Hardware Availability: [1up Keyboards](https://1upkeyboards.com/)
|
* Hardware Availability: [1up Keyboards](https://1upkeyboards.com/)
|
||||||
|
|
||||||
Make example for this keyboard (after setting up your build environment):
|
Revisions:
|
||||||
|
* [v1](./v1/)- The original macropad, designed by Bishop Keyboards
|
||||||
make 1upkeyboards/sweet16:default
|
* [v2/promicro](./v2/promicro)- The second macropad built with a Pro Micro, designed by Clueboard
|
||||||
|
* [v2/proton_c](./v2/proton_c)- The second macropad built with a Proton C, designed by Clueboard
|
||||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
|
||||||
|
@ -1,27 +1,12 @@
|
|||||||
# MCU name
|
|
||||||
MCU = atmega32u4
|
|
||||||
|
|
||||||
# Bootloader selection
|
|
||||||
# Teensy halfkay
|
|
||||||
# Pro Micro caterina
|
|
||||||
# Atmel DFU atmel-dfu
|
|
||||||
# LUFA DFU lufa-dfu
|
|
||||||
# QMK DFU qmk-dfu
|
|
||||||
# ATmega32A bootloadHID
|
|
||||||
# ATmega328P USBasp
|
|
||||||
BOOTLOADER = caterina
|
|
||||||
|
|
||||||
# Build Options
|
# Build Options
|
||||||
# comment out to disable the options.
|
|
||||||
#
|
#
|
||||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
|
DEFAULT_FOLDER = 1upkeyboards/sweet16/v1
|
||||||
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
|
#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
|
||||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
|
MOUSEKEY_ENABLE = yes # Mouse keys
|
||||||
CONSOLE_ENABLE = no # Console for debug(+400)
|
EXTRAKEY_ENABLE = yes # Audio control and System control
|
||||||
|
CONSOLE_ENABLE = no # Console for debug
|
||||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||||
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||||
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
|
||||||
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
|
|
||||||
AUDIO_ENABLE = no
|
AUDIO_ENABLE = no
|
||||||
RGBLIGHT_ENABLE = yes
|
RGBLIGHT_ENABLE = no
|
||||||
EXTRAFLAGS += -flto
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
#include "sweet16.h"
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user