aboutsummaryrefslogtreecommitdiff
path: root/keyboards/handwired/pterodactyl
diff options
context:
space:
mode:
authormyoung34 <myoung34@my.apsu.edu>2020-08-22 14:59:24 -0500
committerGitHub <noreply@github.com>2020-08-22 12:59:24 -0700
commite02f4798f97f7432e8df55846f8eb496b6ac45d1 (patch)
tree7551250fbca9c09199a9750cd0567520bdd2fe30 /keyboards/handwired/pterodactyl
parentcf4b493c247c1e4f02f10cf62bc499ce2d001380 (diff)
downloadqmk_firmware-e02f4798f97f7432e8df55846f8eb496b6ac45d1.tar.gz
qmk_firmware-e02f4798f97f7432e8df55846f8eb496b6ac45d1.zip
[Keyboard] Pterodactyl handwired (#9884)
* Working bluetooth fork of dactyl * Refactor thanks to zvecr * Final refactor per PR comments * Pragma once * Update keyboards/handwired/pterodactyl/pterodactyl.h * Update keyboards/handwired/pterodactyl/readme.md * Update keyboards/handwired/pterodactyl/rules.mk * Update keyboards/handwired/pterodactyl/rules.mk * Update keyboards/handwired/pterodactyl/config.h * Update keyboards/handwired/pterodactyl/pterodactyl.h * Update keyboards/handwired/pterodactyl/config.h * Update keyboards/handwired/pterodactyl/pterodactyl.h * update readme * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/info.json * Update keyboards/handwired/pterodactyl/readme.md * Update keyboards/handwired/pterodactyl/config.h * Update keyboards/handwired/pterodactyl/info.json * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/pterodactyl.h * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.c * Update keyboards/handwired/pterodactyl/matrix.c * Fix/add formatting and info/keymap.json * Update keyboards/handwired/pterodactyl/keymaps/default/keymap.json * lint default/keymap.json * format info.json
Diffstat (limited to 'keyboards/handwired/pterodactyl')
-rw-r--r--keyboards/handwired/pterodactyl/config.h66
-rw-r--r--keyboards/handwired/pterodactyl/info.json98
-rw-r--r--keyboards/handwired/pterodactyl/keymaps/default/keymap.c112
-rw-r--r--keyboards/handwired/pterodactyl/keymaps/default/keymap.json43
-rw-r--r--keyboards/handwired/pterodactyl/keymaps/default/readme.md14
-rw-r--r--keyboards/handwired/pterodactyl/matrix.c527
-rw-r--r--keyboards/handwired/pterodactyl/pterodactyl.c14
-rw-r--r--keyboards/handwired/pterodactyl/pterodactyl.h38
-rw-r--r--keyboards/handwired/pterodactyl/readme.md21
-rw-r--r--keyboards/handwired/pterodactyl/rules.mk31
10 files changed, 964 insertions, 0 deletions
diff --git a/keyboards/handwired/pterodactyl/config.h b/keyboards/handwired/pterodactyl/config.h
new file mode 100644
index 000000000..9f5f1412b
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/config.h
@@ -0,0 +1,66 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
4Copyright 2017 Erin Call <hello@erincall.com>
5Copyright 2020 Marcus Young <myoung34@my.apsu.edu>
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#pragma once
22#include "config_common.h"
23
24/* USB Device descriptor parameter */
25#define VENDOR_ID 0xFEED
26#define PRODUCT_ID 0x1308
27#define DEVICE_VER 0x0002
28#define MANUFACTURER myoung34
29#define PRODUCT Pterodactyl
30
31#define DIODE_DIRECTION COL2ROW
32#define MATRIX_ROWS 6
33#define MATRIX_COLS 12
34#define COL_EXPANDED { true, true, true, true, true, true, false, false, false, false, false, false}
35#define MATRIX_ONBOARD_ROW_PINS { F7, F6, F5, F4, F1, F0 }
36#define MATRIX_ONBOARD_COL_PINS { 0, 0, 0, 0, 0, 0, B6, B7, D6, D2, D3, C6 }
37#define EXPANDER_COL_REGISTER GPIOB
38#define EXPANDER_ROW_REGISTER GPIOA
39#define MATRIX_EXPANDER_COL_PINS {0, 1, 2, 3, 4, 5}
40#define MATRIX_EXPANDER_ROW_PINS {0, 1, 2, 3, 4, 5}
41
42#define MOUSEKEY_INTERVAL 20
43#define MOUSEKEY_DELAY 0
44#define MOUSEKEY_TIME_TO_MAX 60
45#define MOUSEKEY_MAX_SPEED 7
46#define MOUSEKEY_WHEEL_DELAY 0
47
48#define TAPPING_TOGGLE 1
49
50#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
51
52/* key combination for command */
53#define IS_COMMAND() ( \
54 get_mods() == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
55 get_mods() == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
56)
57
58/* fix space cadet rollover issue */
59#define DISABLE_SPACE_CADET_ROLLOVER
60
61/* Set 0 if debouncing isn't needed */
62#define DEBOUNCE 0
63
64#define AdafruitBleResetPin D4
65#define AdafruitBleCSPin B4
66#define AdafruitBleIRQPin E6
diff --git a/keyboards/handwired/pterodactyl/info.json b/keyboards/handwired/pterodactyl/info.json
new file mode 100644
index 000000000..5de1d369c
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/info.json
@@ -0,0 +1,98 @@
1{
2 "keyboard_name": "Pterodactyl",
3 "url": "https://marcyoung.us/post/pterodactyl/",
4 "maintainer": "Marcus Young",
5 "width": 17,
6 "height": 8,
7 "layouts": {
8 "LAYOUT_pterodactyl": {
9 "key_count": 70,
10 "layout": [
11 {"x":0, "y":0},
12 {"x":1, "y":0},
13 {"x":2, "y":0},
14 {"x":3, "y":0},
15 {"x":4, "y":0},
16 {"x":5, "y":0},
17
18 {"x":11, "y":0},
19 {"x":12, "y":0},
20 {"x":13, "y":0},
21 {"x":14, "y":0},
22 {"x":15, "y":0},
23 {"x":16, "y":0},
24
25 {"x":0, "y":1},
26 {"x":1, "y":1},
27 {"x":2, "y":1},
28 {"x":3, "y":1},
29 {"x":4, "y":1},
30 {"x":5, "y":1},
31
32 {"x":11, "y":1},
33 {"x":12, "y":1},
34 {"x":13, "y":1},
35 {"x":14, "y":1},
36 {"x":15, "y":1},
37 {"x":16, "y":1},
38
39 {"x":0, "y":2},
40 {"x":1, "y":2},
41 {"x":2, "y":2},
42 {"x":3, "y":2},
43 {"x":4, "y":2},
44 {"x":5, "y":2},
45
46 {"x":11, "y":2},
47 {"x":12, "y":2},
48 {"x":13, "y":2},
49 {"x":14, "y":2},
50 {"x":15, "y":2},
51 {"x":16, "y":2},
52
53 {"x":0, "y":3},
54 {"x":1, "y":3},
55 {"x":2, "y":3},
56 {"x":3, "y":3},
57 {"x":4, "y":3},
58 {"x":5, "y":3},
59
60 {"x":11, "y":3},
61 {"x":12, "y":3},
62 {"x":13, "y":3},
63 {"x":14, "y":3},
64 {"x":15, "y":3},
65 {"x":16, "y":3},
66
67 {"x":0, "y":4},
68 {"x":1, "y":4},
69 {"x":2, "y":4},
70 {"x":3, "y":4},
71 {"x":4, "y":4},
72
73 {"x":12, "y":4},
74 {"x":13, "y":4},
75 {"x":14, "y":4},
76 {"x":15, "y":4},
77 {"x":16, "y":4},
78
79 {"x":6, "y":5},
80 {"x":7, "y":5},
81
82 {"x":9, "y":5},
83 {"x":10, "y":5},
84
85 {"x":7, "y":6},
86 {"x":9, "y":6},
87
88 {"x":5, "y":6, "h":2},
89 {"x":6, "y":6, "h":2},
90 {"x":7, "y":7},
91
92 {"x":9, "y":7},
93 {"x":10, "y":6, "h":2},
94 {"x":11, "y":6, "h":2}
95 ]
96 }
97 }
98}
diff --git a/keyboards/handwired/pterodactyl/keymaps/default/keymap.c b/keyboards/handwired/pterodactyl/keymaps/default/keymap.c
new file mode 100644
index 000000000..058631818
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/keymaps/default/keymap.c
@@ -0,0 +1,112 @@
1#include QMK_KEYBOARD_H
2#include "version.h"
3
4#define BASE 0 // default layer
5enum
6{
7 _BL = 0,
8 _SYMB,
9 _MDIA,
10};
11
12const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
13/* Keymap 0: Basic layer
14 *
15 * ,-----------------------------------------. ,-----------------------------------------.
16 * | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
17 * |------+------+------+------+------+------| |------+------+------+------+------+------|
18 * | Del | Q | W | E | R | T | | Y | U | I | O | P | \ |
19 * |------+------+------+------+------+------| |------+------+------+------+------+------|
20 * | BkSp | A | S | D | F | G | | H | J | K | L |; / L2|'/Cmd |
21 * |------+------+------+------+------+------| |------+------+------+------+------+------|
22 * |LShift|Z/Ctrl| X | C | V | B | | N | M | , | . |//Ctrl|RShift|
23 * |------+------+------+------+------+------' `------+------+------+------+------+------|
24 * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
25 * `----------------------------------' `----------------------------------'
26 * ,-------------. ,-------------.
27 * | App | LGui | | Alt | ^/Esc|
28 * ,------|------|------| |------+------+------.
29 * | | | Home | | PgUp | | |
30 * | Space|Backsp|------| |------| Tab |Enter |
31 * | |ace | End | | PgDn | | |
32 * `--------------------' `--------------------'
33 */
34[_BL] = LAYOUT_pterodactyl( // layer 0 : default
35 // left hand
36 KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
37 KC_DEL, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
38 KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, LT(_MDIA, KC_SCLN), GUI_T(KC_QUOT),
39 KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
40 LT(_SYMB,KC_GRV), KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT, KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, TT(_SYMB),
41
42 ALT_T(KC_APP), KC_LGUI, KC_RALT, CTL_T(KC_ESC),
43 KC_HOME, KC_PGUP,
44 KC_SPC, KC_BSPC, KC_END, KC_PGDN, KC_TAB, KC_ENT
45),
46/* Keymap 1: Symbol Layer
47 *
48 * ,-----------------------------------------. ,-----------------------------------------.
49 * |Versn | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
50 * |------+------+------+------+------+------| |------+------+------+------+------+------|
51 * | | ! | @ | { | } | | | | Up | 7 | 8 | 9 | * | F12 |
52 * |------+------+------+------+------+------| |------+------+------+------+------+------|
53 * | | # | $ | ( | ) | ` | | Down | 4 | 5 | 6 | + | |
54 * |------+------+------+------+------+------| |------+------+------+------+------+------|
55 * | | % | ^ | [ | ] | ~ | | & | 1 | 2 | 3 | \ | |
56 * |------+------+------+------+------+------' `------+------+------+------+------+------|
57 * |RESET | | | | | | | . | 0 | = | |
58 * `----------------------------------' `----------------------------------'
59 * ,-------------. ,-------------.
60 * | | | | | |
61 * ,------|------|------| |------+------+------.
62 * | | | | | | | |
63 * | | |------| |------| | |
64 * | | | | | | | |
65 * `--------------------' `--------------------'
66 */
67// SYMBOLS
68[_SYMB] = LAYOUT_pterodactyl(
69 // left hand
70 KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
71 KC_TRNS, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
72 KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
73 KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
74 RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DOT, KC_0, KC_EQL, KC_TRNS,
75
76 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
77 KC_TRNS, KC_TRNS,
78 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
79),
80/* Keymap 2: Media and mouse keys
81 * ,-----------------------------------------. ,-----------------------------------------.
82 * | | | | | | | | | | | | | |
83 * |------+------+------+------+------+------| |------+------+------+------+------+------|
84 * | | | | MsUp | | | | | | | | | |
85 * |------+------+------+------+------+------| |------+------+------+------+------+------|
86 * | | |MsLeft|MsDown|MsRght| | | | | | | | Play |
87 * |------+------+------+------+------+------| |------+------+------+------+------+------|
88 * | | | | | | | | | | Prev | Next | | |
89 * |------+------+------+------+------+------' `------+------+------+------+------+------|
90 * | | | | Lclk | Rclk | | VolUp| VolDn| Mute | | |
91 * `----------------------------------' `----------------------------------'
92 * ,-------------. ,-------------.
93 * | | | | | |
94 * ,------|------|------| |------+------+------.
95 * | | | | | | |Brwser|
96 * | | |------| |------| |Back |
97 * | | | | | | | |
98 * `--------------------' `--------------------'
99 *
100 */
101// MEDIA AND MOUSE
102[_MDIA] = LAYOUT_pterodactyl(
103 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
104 KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
105 KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
106 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
107 KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
108 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
109 KC_TRNS, KC_TRNS,
110 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_WBAK
111),
112};
diff --git a/keyboards/handwired/pterodactyl/keymaps/default/keymap.json b/keyboards/handwired/pterodactyl/keymaps/default/keymap.json
new file mode 100644
index 000000000..1a4a1fa9b
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/keymaps/default/keymap.json
@@ -0,0 +1,43 @@
1{
2 "version": 1,
3 "notes": "",
4 "author": "Marcus Young",
5 "keyboard": "handwired/pterodactyl",
6 "keymap": "default",
7 "layout": "LAYOUT_pterodactyl",
8 "layers": [
9 [
10 "KC_EQL", "KC_1", "KC_2", "KC_3", "KC_4", "KC_5", "KC_6", "KC_7", "KC_8", "KC_9", "KC_0", "KC_MINS",
11 "KC_DEL", "KC_Q", "KC_W", "KC_E", "KC_R", "KC_T", "KC_Y", "KC_U", "KC_I", "KC_O", "KC_P", "KC_BSLS",
12 "KC_BSPC", "KC_A", "KC_S", "KC_D", "KC_F", "KC_G", "KC_H", "KC_J", "KC_K", "KC_L", "LT(2,KC_SCLN)", "LGUI_T(KC_QUOT)",
13 "KC_LSFT", "LCTL_T(KC_Z)", "KC_X", "KC_C", "KC_V", "KC_B", "KC_N", "KC_M", "KC_COMM", "KC_DOT", "LCTL_T(KC_SLSH)", "KC_RSFT",
14 "LT(1,KC_GRV)", "KC_QUOT", "LALT(KC_LSFT)", "KC_LEFT", "KC_RGHT", "KC_UP", "KC_DOWN", "KC_LBRC", "KC_RBRC", "TT(1)",
15
16 "LALT_T(KC_APP)", "KC_LGUI", "KC_RALT", "LCTL_T(KC_ESC)",
17 "KC_HOME", "KC_PGUP",
18 "KC_SPC", "KC_BSPC", "KC_END", "KC_PGDN", "KC_TAB", "KC_ENT"
19 ],
20 [
21 "KC_TRNS", "KC_F1", "KC_F2", "KC_F3", "KC_F4", "KC_F5", "KC_F6", "KC_F7", "KC_F8", "KC_F9", "KC_F10", "KC_F11",
22 "KC_TRNS", "KC_EXLM", "KC_AT", "KC_LCBR", "KC_RCBR", "KC_PIPE", "KC_UP", "KC_7", "KC_8", "KC_9", "KC_ASTR", "KC_F12",
23 "KC_TRNS", "KC_HASH", "KC_DLR", "KC_LPRN", "KC_RPRN", "KC_GRV", "KC_DOWN", "KC_4", "KC_5", "KC_6", "KC_PLUS", "KC_TRNS",
24 "KC_TRNS", "KC_PERC", "KC_CIRC", "KC_LBRC", "KC_RBRC", "KC_TILD", "KC_AMPR", "KC_1", "KC_2", "KC_3", "KC_BSLS", "KC_TRNS",
25 "RESET", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_DOT", "KC_0", "KC_EQL", "KC_TRNS",
26
27 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
28 "KC_TRNS", "KC_TRNS",
29 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS"
30 ],
31 [
32 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
33 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MS_U", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
34 "KC_TRNS", "KC_TRNS", "KC_MS_L", "KC_MS_D", "KC_MS_R", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPLY",
35 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_MPRV", "KC_MNXT", "KC_TRNS", "KC_TRNS",
36 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_BTN1", "KC_BTN2", "KC_VOLU", "KC_VOLD", "KC_MUTE", "KC_TRNS", "KC_TRNS",
37
38 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS",
39 "KC_TRNS", "KC_TRNS",
40 "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_TRNS", "KC_WBAK"
41 ]
42 ]
43}
diff --git a/keyboards/handwired/pterodactyl/keymaps/default/readme.md b/keyboards/handwired/pterodactyl/keymaps/default/readme.md
new file mode 100644
index 000000000..876416f00
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/keymaps/default/readme.md
@@ -0,0 +1,14 @@
1# Pterodactyl Default Configuration
2
3## Changelog
4
5* Nov 2017:
6 * Copied and adapted from the Ergodox EZ equivalent
7 * Notable differences:
8 - Don't try to have the columns that don't exist, naturally
9 - Removed RGB keys, since there are no RGB LEDs in the Dactyl (as designed, at least)
10* May 2020:
11 * Copied and adapted from dactyl base
12 * Notable differences:
13 - Support for Bluetooth via default Adafruit Feather 32u4
14 - Assumes processor lives in left half of split, not right
diff --git a/keyboards/handwired/pterodactyl/matrix.c b/keyboards/handwired/pterodactyl/matrix.c
new file mode 100644
index 000000000..5f13cb30b
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/matrix.c
@@ -0,0 +1,527 @@
1/*
2Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
3Copyright 2017 Erin Call <hello@erincall.com>
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include <stdint.h>
19#include <stdbool.h>
20#include <avr/io.h>
21#include "wait.h"
22#include "action_layer.h"
23#include "print.h"
24#include "debug.h"
25#include "util.h"
26#include "matrix.h"
27#include "pterodactyl.h"
28#include "i2c_master.h"
29#include "timer.h"
30
31#define I2C_TIMEOUT 100
32
33#define I2C_ADDR 0b0100000
34#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
35#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
36#define IODIRA 0x00 // i/o direction register
37#define IODIRB 0x01
38#define GPPUA 0x0C // GPIO pull-up resistor register
39#define GPPUB 0x0D
40#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
41#define GPIOB 0x13
42
43void init_expander(void);
44
45/* Set 0 if debouncing isn't needed */
46
47#ifndef DEBOUNCE
48# define DEBOUNCE 5
49#endif
50
51#if (DEBOUNCE > 0)
52 static uint16_t debouncing_time;
53 static bool debouncing = false;
54#endif
55
56#ifdef MATRIX_MASKED
57 extern const matrix_row_t matrix_mask[];
58#endif
59
60#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
61static const uint8_t onboard_row_pins[MATRIX_ROWS] = MATRIX_ONBOARD_ROW_PINS;
62static const uint8_t onboard_col_pins[MATRIX_COLS] = MATRIX_ONBOARD_COL_PINS;
63static const bool col_expanded[MATRIX_COLS] = COL_EXPANDED;
64#endif
65
66/* matrix state(1:on, 0:off) */
67static matrix_row_t matrix[MATRIX_ROWS];
68
69static matrix_row_t matrix_debouncing[MATRIX_ROWS];
70
71#if (DIODE_DIRECTION == COL2ROW)
72 static const uint8_t expander_col_pins[MATRIX_COLS] = MATRIX_EXPANDER_COL_PINS;
73 static void init_cols(void);
74 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
75 static void unselect_rows(void);
76 static void select_row(uint8_t row);
77 static void unselect_row(uint8_t row);
78#elif (DIODE_DIRECTION == ROW2COL)
79 static const uint8_t expander_row_pins[MATRIX_ROWS] = MATRIX_EXPANDER_ROW_PINS;
80 static void init_rows(void);
81 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
82 static void unselect_cols(void);
83 static void select_col(uint8_t col);
84 static void unselect_col(uint8_t col);
85#endif
86
87static uint8_t expander_reset_loop;
88uint8_t expander_status;
89uint8_t expander_input_pin_mask;
90bool i2c_initialized = false;
91
92#define ROW_SHIFTER ((matrix_row_t)1)
93
94__attribute__ ((weak))
95void matrix_init_user(void) {}
96
97__attribute__ ((weak))
98void matrix_scan_user(void) {}
99
100__attribute__ ((weak))
101void matrix_init_kb(void) {
102 matrix_init_user();
103}
104
105__attribute__ ((weak))
106void matrix_scan_kb(void) {
107 matrix_scan_user();
108}
109
110inline
111uint8_t matrix_rows(void)
112{
113 return MATRIX_ROWS;
114}
115
116inline
117uint8_t matrix_cols(void)
118{
119 return MATRIX_COLS;
120}
121
122void matrix_init(void)
123{
124 init_expander();
125
126#if (DIODE_DIRECTION == COL2ROW)
127 unselect_rows();
128 init_cols();
129#elif (DIODE_DIRECTION == ROW2COL)
130 unselect_cols();
131 init_rows();
132#endif
133
134 // initialize matrix state: all keys off
135 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
136 matrix[i] = 0;
137 matrix_debouncing[i] = 0;
138 }
139
140 matrix_init_quantum();
141}
142
143void init_expander(void) {
144 if (! i2c_initialized) {
145 i2c_init();
146 wait_us(1000000);
147 }
148
149 if (! expander_input_pin_mask) {
150#if (DIODE_DIRECTION == COL2ROW)
151 for (int col = 0; col < MATRIX_COLS; col++) {
152 if (col_expanded[col]) {
153 expander_input_pin_mask |= (1 << expander_col_pins[col]);
154 }
155 }
156#elif (DIODE_DIRECTION == ROW2COL)
157 for (int row = 0; row < MATRIX_ROWS; row++) {
158 expander_input_pin_mask |= (1 << expander_row_pins[row]);
159 }
160#endif
161 }
162
163 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
164 expander_status = i2c_write(IODIRA, I2C_TIMEOUT); if (expander_status) goto out;
165
166 /*
167 Pin direction and pull-up depends on both the diode direction
168 and on whether the column register is GPIOA or GPIOB
169 +-------+---------------+---------------+
170 | | ROW2COL | COL2ROW |
171 +-------+---------------+---------------+
172 | GPIOA | input, output | output, input |
173 +-------+---------------+---------------+
174 | GPIOB | output, input | input, output |
175 +-------+---------------+---------------+
176 */
177
178#if (EXPANDER_COL_REGISTER == GPIOA)
179# if (DIODE_DIRECTION == COL2ROW)
180 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
181 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
182# elif (DIODE_DIRECTION == ROW2COL)
183 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
184 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
185# endif
186#elif (EXPANDER_COL_REGISTER == GPIOB)
187# if (DIODE_DIRECTION == COL2ROW)
188 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
189 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
190# elif (DIODE_DIRECTION == ROW2COL)
191 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
192 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
193# endif
194#endif
195
196 i2c_stop();
197
198 // set pull-up
199 // - unused : off : 0
200 // - input : on : 1
201 // - driving : off : 0
202 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
203 expander_status = i2c_write(GPPUA, I2C_TIMEOUT); if (expander_status) goto out;
204#if (EXPANDER_COL_REGISTER == GPIOA)
205# if (DIODE_DIRECTION == COL2ROW)
206 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
207 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
208# elif (DIODE_DIRECTION == ROW2COL)
209 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
210 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
211# endif
212#elif (EXPANDER_COL_REGISTER == GPIOB)
213# if (DIODE_DIRECTION == COL2ROW)
214 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
215 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
216# elif (DIODE_DIRECTION == ROW2COL)
217 expander_status = i2c_write(expander_input_pin_mask, I2C_TIMEOUT); if (expander_status) goto out;
218 expander_status = i2c_write(0, I2C_TIMEOUT); if (expander_status) goto out;
219# endif
220#endif
221
222out:
223 i2c_stop();
224}
225
226uint8_t matrix_scan(void)
227{
228 if (expander_status) { // if there was an error
229 if (++expander_reset_loop == 0) {
230 // since expander_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
231 // this will be approx bit more frequent than once per second
232 print("trying to reset expander\n");
233 init_expander();
234 if (expander_status) {
235 print("left side not responding\n");
236 } else {
237 print("left side attached\n");
238 }
239 }
240 }
241
242#if (DIODE_DIRECTION == COL2ROW)
243 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
244# if (DEBOUNCE > 0)
245 bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
246
247 if (matrix_changed) {
248 debouncing = true;
249 debouncing_time = timer_read();
250 }
251# else
252 read_cols_on_row(matrix, current_row);
253# endif
254 }
255
256#elif (DIODE_DIRECTION == ROW2COL)
257 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
258# if (DEBOUNCE > 0)
259 bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
260
261 if (matrix_changed) {
262 debouncing = true;
263 debouncing_time = timer_read();
264 }
265# else
266 read_rows_on_col(matrix, current_col);
267# endif
268
269 }
270#endif
271
272# if (DEBOUNCE > 0)
273 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCE)) {
274 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
275 matrix[i] = matrix_debouncing[i];
276 }
277 debouncing = false;
278 }
279# endif
280
281 matrix_scan_quantum();
282 return 1;
283}
284
285bool matrix_is_modified(void) // deprecated and evidently not called.
286{
287#if (DEBOUNCE > 0)
288 if (debouncing) return false;
289#endif
290 return true;
291}
292
293inline
294bool matrix_is_on(uint8_t row, uint8_t col)
295{
296 return (matrix[row] & (ROW_SHIFTER << col));
297}
298
299inline
300matrix_row_t matrix_get_row(uint8_t row)
301{
302#ifdef MATRIX_MASKED
303 return matrix[row] & matrix_mask[row];
304#else
305 return matrix[row];
306#endif
307}
308
309void matrix_print(void)
310{
311 print("\nr/c 0123456789ABCDEF\n");
312 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
313 phex(row); print(": ");
314 pbin_reverse16(matrix_get_row(row));
315 print("\n");
316 }
317}
318
319uint8_t matrix_key_count(void)
320{
321 uint8_t count = 0;
322 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
323 count += bitpop16(matrix[i]);
324 }
325 return count;
326}
327
328#if (DIODE_DIRECTION == COL2ROW)
329
330static void init_cols(void) {
331 for (uint8_t x = 0; x < MATRIX_COLS; x++) {
332 if (! col_expanded[x]) {
333 uint8_t pin = onboard_col_pins[x];
334 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
335 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
336 }
337 }
338}
339
340static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
341 // Store last value of row prior to reading
342 matrix_row_t last_row_value = current_matrix[current_row];
343
344 // Clear data in matrix row
345 current_matrix[current_row] = 0;
346
347 // Select row and wait for row selection to stabilize
348 select_row(current_row);
349 wait_us(30);
350
351 // Read columns from expander, unless it's in an error state
352 if (! expander_status) {
353 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
354 expander_status = i2c_write(EXPANDER_COL_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
355 expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out;
356
357 current_matrix[current_row] |= (~i2c_read_nack(I2C_TIMEOUT)) & expander_input_pin_mask;
358
359 out:
360 i2c_stop();
361 }
362
363 // Read columns from onboard pins
364 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
365 if (! col_expanded[col_index]) {
366 uint8_t pin = onboard_col_pins[col_index];
367 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
368 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
369 }
370 }
371
372 unselect_row(current_row);
373
374 return (last_row_value != current_matrix[current_row]);
375}
376
377static void select_row(uint8_t row) {
378 // select on expander, unless it's in an error state
379 if (! expander_status) {
380 // set active row low : 0
381 // set other rows hi-Z : 1
382 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
383 expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
384 expander_status = i2c_write(0xFF & ~(1<<row), I2C_TIMEOUT); if (expander_status) goto out;
385 out:
386 i2c_stop();
387 }
388
389 // select on teensy
390 uint8_t pin = onboard_row_pins[row];
391 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
392 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
393}
394
395static void unselect_row(uint8_t row)
396{
397 // No need to explicitly unselect expander pins--their I/O state is
398 // set simultaneously, with a single bitmask sent to i2c_write. When
399 // select_row selects a single pin, it implicitly unselects all the
400 // other ones.
401
402 // unselect on teensy
403 uint8_t pin = onboard_row_pins[row];
404 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // OUT
405 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // LOW
406}
407
408static void unselect_rows(void) {
409 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
410 unselect_row(x);
411 }
412}
413
414#elif (DIODE_DIRECTION == ROW2COL)
415
416static void init_rows(void)
417{
418 for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
419 uint8_t pin = onboard_row_pins[x];
420 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
421 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
422 }
423}
424
425static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
426{
427 bool matrix_changed = false;
428
429 uint8_t column_state = 0;
430
431 //select col and wait for selection to stabilize
432 select_col(current_col);
433 wait_us(30);
434
435 if (current_col < 6) {
436 // read rows from expander
437 if (expander_status) {
438 // it's already in an error state; nothing we can do
439 return false;
440 }
441
442 expander_status = i2c_start(I2C_ADDR_WRITE, I2C_TIMEOUT); if (expander_status) goto out;
443 expander_status = i2c_write(EXPANDER_ROW_REGISTER, I2C_TIMEOUT); if (expander_status) goto out;
444 expander_status = i2c_start(I2C_ADDR_READ, I2C_TIMEOUT); if (expander_status) goto out;
445 column_state = i2c_read_nack(I2C_TIMEOUT);
446
447 out:
448 i2c_stop();
449
450 column_state = ~column_state;
451 } else {
452 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
453 if ((_SFR_IO8(onboard_row_pins[current_row] >> 4) & _BV(onboard_row_pins[current_row] & 0xF)) == 0) {
454 column_state |= (1 << current_row);
455 }
456 }
457 }
458
459 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
460 // Store last value of row prior to reading
461 matrix_row_t last_row_value = current_matrix[current_row];
462
463 if (column_state & (1 << current_row)) {
464 // key closed; set state bit in matrix
465 current_matrix[current_row] |= (ROW_SHIFTER << current_col);
466 } else {
467 // key open; clear state bit in matrix
468 current_matrix[current_row] &= ~(ROW_SHIFTER << current_col);
469 }
470
471 // Determine whether the matrix changed state
472 if ((last_row_value != current_matrix[current_row]) && !(matrix_changed))
473 {
474 matrix_changed = true;
475 }
476 }
477
478 unselect_col(current_col);
479
480 return matrix_changed;
481}
482
483static void select_col(uint8_t col)
484{
485 if (col_expanded[col]) {
486 // select on expander
487 if (expander_status) { // if there was an error
488 // do nothing
489 } else {
490 // set active col low : 0
491 // set other cols hi-Z : 1
492 expander_status = i2c_start(I2C_ADDR_WRITE); if (expander_status) goto out;
493 expander_status = i2c_write(EXPANDER_COL_REGISTER); if (expander_status) goto out;
494 expander_status = i2c_write(0xFF & ~(1<<col)); if (expander_status) goto out;
495 out:
496 i2c_stop();
497 }
498 } else {
499 // select on teensy
500 uint8_t pin = onboard_col_pins[col];
501 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
502 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
503 }
504}
505
506static void unselect_col(uint8_t col)
507{
508 if (col_expanded[col]) {
509 // No need to explicitly unselect expander pins--their I/O state is
510 // set simultaneously, with a single bitmask sent to i2c_write. When
511 // select_col selects a single pin, it implicitly unselects all the
512 // other ones.
513 } else {
514 // unselect on teensy
515 uint8_t pin = onboard_col_pins[col];
516 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
517 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
518 }
519}
520
521static void unselect_cols(void)
522{
523 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
524 unselect_col(x);
525 }
526}
527#endif
diff --git a/keyboards/handwired/pterodactyl/pterodactyl.c b/keyboards/handwired/pterodactyl/pterodactyl.c
new file mode 100644
index 000000000..736b0a62c
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/pterodactyl.c
@@ -0,0 +1,14 @@
1#include "pterodactyl.h"
2
3#ifdef SWAP_HANDS_ENABLE
4__attribute__ ((weak))
5// swap-hands action needs a matrix to define the swap
6const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
7 {{0,11}, {0,10}, {0,9}, {0,8}, {0,7}, {0,6}, {0,5}, {0,4}, {0,3}, {0,2}, {0,1}, {0,0}},
8 {{1,11}, {1,11}, {1,9}, {1,8}, {1,7}, {1,6}, {1,5}, {1,4}, {1,3}, {1,2}, {1,1}, {1,0}},
9 {{2,11}, {2,12}, {2,9}, {2,8}, {2,7}, {2,6}, {2,5}, {2,4}, {2,3}, {2,2}, {2,1}, {2,0}},
10 {{3,11}, {3,13}, {3,9}, {3,8}, {3,7}, {3,6}, {3,5}, {3,4}, {3,3}, {3,2}, {3,1}, {3,0}},
11 {{4,11}, {4,14}, {4,9}, {4,8}, {4,7}, {4,6}, {4,5}, {4,4}, {4,3}, {4,2}, {4,1}, {4,0}},
12 {{5,11}, {5,15}, {5,9}, {5,8}, {5,7}, {5,6}, {5,5}, {5,4}, {5,3}, {5,2}, {5,1}, {5,0}},
13};
14#endif
diff --git a/keyboards/handwired/pterodactyl/pterodactyl.h b/keyboards/handwired/pterodactyl/pterodactyl.h
new file mode 100644
index 000000000..7bdc3bc63
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/pterodactyl.h
@@ -0,0 +1,38 @@
1#pragma once
2
3#include "quantum.h"
4#include <stdint.h>
5#include <stdbool.h>
6#include "i2c_master.h"
7
8/*
9 * LEFT HAND: LINES 38-45
10 * RIGHT HAND: LINES 47-54
11 */
12#define LAYOUT_pterodactyl( \
13 \
14 k00,k01,k02,k03,k04,k05, k06,k07,k08,k09,k0A,k0B, \
15 k10,k11,k12,k13,k14,k15, k16,k17,k18,k19,k1A,k1B, \
16 k20,k21,k22,k23,k24,k25, k26,k27,k28,k29,k2A,k2B, \
17 k30,k31,k32,k33,k34,k35, k36,k37,k38,k39,k3A,k3B, \
18 k40,k41,k42,k43,k44, k47,k48,k49,k4A,k4B, \
19 k55,k50, k5B,k56, \
20 k54, k57, \
21 k53, k52,k51, k5A,k59,k58 ) \
22 \
23 /* matrix positions */ \
24 { \
25 { k0B, k0A, k09, k08, k07, k06, k05, k04, k03, k02, k01, k00 }, \
26 { k1B, k1A, k19, k18, k17, k16, k15, k14, k13, k12, k11, k10 }, \
27 { k2B, k2A, k29, k28, k27, k26, k25, k24, k23, k22, k21, k20 }, \
28 { k3B, k3A, k39, k38, k37, k36, k35, k34, k33, k32, k31, k30 }, \
29 { k4B, k4A, k49, k48, k47, k58, k53, k44, k43, k42, k41, k40 }, \
30 { k56, k5B, k57, k5A, k59, KC_NO, KC_NO, k52, k51, k54, k50, k55 }, \
31 }
32 /* for future comers:
33 * the weird ass ordering here is because the dactyl/ergo/etc are wired for the
34 * chip to be in the right side, mine is not built that way.
35 * that last line is not obvious but its due to the way my columns are wired
36 * and are different than the dactyl guide.
37 * this is to compensate for my build.
38 */
diff --git a/keyboards/handwired/pterodactyl/readme.md b/keyboards/handwired/pterodactyl/readme.md
new file mode 100644
index 000000000..3cc5e19c3
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/readme.md
@@ -0,0 +1,21 @@
1# Pterodactyl
2
3![](https://cdn.zappy.app/65bacc35e1fbeb19ba02d42d80bddb9b.png)
4
5A bluetooth fork of the dactyl
6
7* Keyboard Maintainer: [myoung34](https://github.com/myoung34)
8* Hardware Supported:
9 * [Feather 32u4](https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le)
10* Hardware Availability:
11 * [Feather 32u4](https://www.amazon.com/Adafruit-Feather-32u4-Bluefruit-ADA2829/dp/B01GJR9MNI)
12
13Make example for this keyboard (after setting up your build environment):
14
15 make handwired/pterodactyl:default
16
17Flashing example for this keyboard:
18
19 make handwired/pterodactyl:default:flash
20
21See 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).
diff --git a/keyboards/handwired/pterodactyl/rules.mk b/keyboards/handwired/pterodactyl/rules.mk
new file mode 100644
index 000000000..271b89606
--- /dev/null
+++ b/keyboards/handwired/pterodactyl/rules.mk
@@ -0,0 +1,31 @@
1# MCU name
2MCU = atmega32u4
3
4# Processor frequency
5F_CPU = 8000000
6
7# Bootloader selection
8BOOTLOADER = caterina
9
10# Build Options
11# change yes to no to disable
12#
13BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
14MOUSEKEY_ENABLE = no # Mouse keys
15EXTRAKEY_ENABLE = yes # Audio control and System control
16CONSOLE_ENABLE = yes # Console for debug
17COMMAND_ENABLE = no # Commands for debug and configuration
18# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
19SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
20# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
21NKRO_ENABLE = yes # USB Nkey Rollover
22BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
23RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
24BLUETOOTH_ENABLE = no # Enable Bluetooth
25AUDIO_ENABLE = no # Audio output
26BLUETOOTH = AdafruitBLE
27UNICODE_ENABLE = yes
28CUSTOM_MATRIX = yes
29
30SRC += matrix.c
31QUANTUM_LIB_SRC += i2c_master.c