summaryrefslogtreecommitdiffstats
path: root/keyboards/fortitude60
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/fortitude60')
-rw-r--r--keyboards/fortitude60/config.h23
-rw-r--r--keyboards/fortitude60/fortitude60.c1
-rw-r--r--keyboards/fortitude60/fortitude60.h26
-rw-r--r--keyboards/fortitude60/keymaps/default/config.h39
-rw-r--r--keyboards/fortitude60/keymaps/default/keymap.c189
-rw-r--r--keyboards/fortitude60/keymaps/default/rules.mk1
-rw-r--r--keyboards/fortitude60/matrix.c423
-rw-r--r--keyboards/fortitude60/readme.md15
-rw-r--r--keyboards/fortitude60/rev1/config.h91
-rw-r--r--keyboards/fortitude60/rev1/rev1.c22
-rw-r--r--keyboards/fortitude60/rev1/rev1.h44
-rw-r--r--keyboards/fortitude60/rev1/rules.mk1
-rw-r--r--keyboards/fortitude60/rules.mk72
-rw-r--r--keyboards/fortitude60/serial.c235
-rw-r--r--keyboards/fortitude60/serial.h32
-rw-r--r--keyboards/fortitude60/split_util.c85
-rw-r--r--keyboards/fortitude60/split_util.h18
17 files changed, 1317 insertions, 0 deletions
diff --git a/keyboards/fortitude60/config.h b/keyboards/fortitude60/config.h
new file mode 100644
index 0000000000..863722d7d0
--- /dev/null
+++ b/keyboards/fortitude60/config.h
@@ -0,0 +1,23 @@
+/*
+Copyright 2017 Danny Nguyen <danny@hexwire.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+#endif // CONFIG_H
diff --git a/keyboards/fortitude60/fortitude60.c b/keyboards/fortitude60/fortitude60.c
new file mode 100644
index 0000000000..d35b286d11
--- /dev/null
+++ b/keyboards/fortitude60/fortitude60.c
@@ -0,0 +1 @@
+#include "fortitude60.h"
diff --git a/keyboards/fortitude60/fortitude60.h b/keyboards/fortitude60/fortitude60.h
new file mode 100644
index 0000000000..db2ce07a68
--- /dev/null
+++ b/keyboards/fortitude60/fortitude60.h
@@ -0,0 +1,26 @@
+#ifndef FORTITUDE60_H
+#define FORTITUDE60_H
+
+#ifdef KEYBOARD_fortitude60_rev1
+ #include "rev1.h"
+#endif
+
+#include "quantum.h"
+
+// Used to create a keymap using only KC_ prefixed keys
+#define LAYOUT_kc( \
+ L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
+ L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
+ L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
+ L30, L31, L32, L33, L34, L35, LT5, RT5, R30, R31, R32, R33, R34, R35, \
+ LT0, LT1, LT2, LT3, LT4, RT4, RT3, RT2, RT1, RT0 \
+ ) \
+ LAYOUT( \
+ KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \
+ KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \
+ KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \
+ KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##L34, KC_##L35, KC_##LT5, KC_##RT5, KC_##R30, KC_##R31, KC_##R32, KC_##R33, KC_##R34, KC_##R35, \
+ KC_##LT0, KC_##LT1, KC_##LT2, KC_##LT3, KC_##LT4, KC_##RT4, KC_##RT3, KC_##RT2, KC_##RT1, KC_##RT0 \
+ )
+
+#endif
diff --git a/keyboards/fortitude60/keymaps/default/config.h b/keyboards/fortitude60/keymaps/default/config.h
new file mode 100644
index 0000000000..b356791fc8
--- /dev/null
+++ b/keyboards/fortitude60/keymaps/default/config.h
@@ -0,0 +1,39 @@
+/*
+Copyright 2017 Danny Nguyen <danny@hexwire.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "config_common.h"
+
+#define USE_SERIAL
+
+/* Select hand configuration */
+
+// #define MASTER_LEFT
+// #define MASTER_RIGHT
+#define EE_HANDS
+
+#define USE_SERIAL_PD2
+/* #undef RGBLED_NUM */
+/* #define RGBLIGHT_ANIMATIONS */
+/* #define RGBLED_NUM 12 */
+/* #define RGBLIGHT_HUE_STEP 8 */
+/* #define RGBLIGHT_SAT_STEP 8 */
+/* #define RGBLIGHT_VAL_STEP 8 */
+
+#endif
diff --git a/keyboards/fortitude60/keymaps/default/keymap.c b/keyboards/fortitude60/keymaps/default/keymap.c
new file mode 100644
index 0000000000..18d2527e45
--- /dev/null
+++ b/keyboards/fortitude60/keymaps/default/keymap.c
@@ -0,0 +1,189 @@
+#include QMK_KEYBOARD_H
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _ADJUST 16
+
+enum custom_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ LOWER,
+ RAISE,
+ ADJUST,
+};
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+#define LOWER MO(_LOWER)
+#define RAISE MO(_RAISE)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | [ | ] | N | M | , | . | / |Enter |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
+ * `---------------------------------------------------------------------'
+ */
+[_QWERTY] = LAYOUT( \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
+ KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , \
+ KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
+),
+
+/* Colemak
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Tab | Q | W | F | P | G | | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | | H | N | E | I | O | " |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | [ | ] | K | M | , | . | / |Enter |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
+ * `---------------------------------------------------------------------'
+ */
+[_COLEMAK] = LAYOUT( \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, \
+ KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , \
+ KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
+),
+
+/* Dvorak
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Tab | " | , | . | P | Y | | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | | D | H | T | N | S | / |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | [ | ] | B | M | W | V | Z |Enter |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
+ * `---------------------------------------------------------------------'
+ */
+[_DVORAK] = LAYOUT( \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, \
+ KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, \
+ KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_LBRC, KC_RBRC, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT , \
+ KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
+),
+
+/* Lower
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | Del |
+ * |------+------+------+------+------+------| |------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | | F6 | _ | + | | \ | | |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | | | F12 |ISO ~ |ISO | | | | |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | | | | | | | | | | |
+ * `---------------------------------------------------------------------'
+ */
+[_LOWER] = LAYOUT( \
+ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, \
+ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL, \
+ KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______,\
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
+),
+
+/* Raise
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
+ * |------+------+------+------+------+------. ,------+------+------+------+------+------|
+ * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+------. ,------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | | F6 | - | = | [ | ] | | |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | | | F12 |ISO # |ISO / | | | |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | | | | | | | | | | |
+ * `---------------------------------------------------------------------'
+ */
+[_RAISE] = LAYOUT( \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
+ KC_GRV, KC_1, KC_UP, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \
+ KC_DEL, KC_LEFT, KC_DOWN, KC_RGHT, KC_F4, KC_F5, KC_F6,KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
+ _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
+),
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------. ,-----------------------------------------.
+ * | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
+ * |------+------+------+------+------+------. ,------+------+------+------+------+------|
+ * | | Reset|RGB Tg|RGB Md|Hue Up|Hue Dn| |Sat Up|Sat Dn|Val Up|Val Dn| | Bksp |
+ * |------+------+------+------+------+------. ,------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm| |AGswap| |BL TOG|BL STP| | |
+ * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
+ * |Qwerty|Colemk|Dvorak| | | | | | | | | | | |
+ * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
+ * | | | | | | | | | | |
+ * `---------------------------------------------------------------------'
+ */
+[_ADJUST] = LAYOUT( \
+ KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \
+ _______, RESET , RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, _______, KC_BSPC, \
+ _______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, _______, BL_TOGG, BL_STEP, _______, _______, \
+ QWERTY, COLEMAK, DVORAK, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
+)
+
+
+};
+
+uint32_t layer_state_set_user(uint32_t state) {
+ return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_QWERTY);
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_COLEMAK);
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(_DVORAK);
+ }
+ return false;
+ break;
+ }
+ return true;
+}
diff --git a/keyboards/fortitude60/keymaps/default/rules.mk b/keyboards/fortitude60/keymaps/default/rules.mk
new file mode 100644
index 0000000000..e0ed6f0c2d
--- /dev/null
+++ b/keyboards/fortitude60/keymaps/default/rules.mk
@@ -0,0 +1 @@
+RGBLIGHT_ENABLE = no
diff --git a/keyboards/fortitude60/matrix.c b/keyboards/fortitude60/matrix.c
new file mode 100644
index 0000000000..565f417d85
--- /dev/null
+++ b/keyboards/fortitude60/matrix.c
@@ -0,0 +1,423 @@
+/*
+Copyright 2017 Danny Nguyen <danny@keeb.io>
+
+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/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include "wait.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "split_util.h"
+#include "pro_micro.h"
+#include "config.h"
+#include "timer.h"
+
+#ifdef BACKLIGHT_ENABLE
+#include "backlight.h"
+extern backlight_config_t backlight_config;
+#endif
+
+#include "serial.h"
+
+#ifndef DEBOUNCING_DELAY
+# define DEBOUNCING_DELAY 5
+#endif
+
+#if (DEBOUNCING_DELAY > 0)
+ static uint16_t debouncing_time;
+ static bool debouncing = false;
+#endif
+
+#if (MATRIX_COLS <= 8)
+# define print_matrix_header() print("\nr/c 01234567\n")
+# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop(matrix[i])
+# define ROW_SHIFTER ((uint8_t)1)
+#else
+# error "Currently only supports 8 COLS"
+#endif
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+#define ERROR_DISCONNECT_COUNT 5
+
+#define SERIAL_LED_ADDR 0x00
+
+#define ROWS_PER_HAND (MATRIX_ROWS/2)
+
+static uint8_t error_count = 0;
+
+static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+#if (DIODE_DIRECTION == COL2ROW)
+ static void init_cols(void);
+ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
+ static void unselect_rows(void);
+ static void select_row(uint8_t row);
+ static void unselect_row(uint8_t row);
+#elif (DIODE_DIRECTION == ROW2COL)
+ static void init_rows(void);
+ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
+ static void unselect_cols(void);
+ static void unselect_col(uint8_t col);
+ static void select_col(uint8_t col);
+#endif
+
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+ matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+__attribute__ ((weak))
+void matrix_init_user(void) {
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+ debug_enable = true;
+ debug_matrix = true;
+ debug_mouse = true;
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ TX_RX_LED_INIT;
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ matrix_init_quantum();
+
+}
+
+uint8_t _matrix_scan(void)
+{
+ int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
+#if (DIODE_DIRECTION == COL2ROW)
+ // Set row, read cols
+ for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
+# if (DEBOUNCING_DELAY > 0)
+ bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
+
+ if (matrix_changed) {
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+
+# else
+ read_cols_on_row(matrix+offset, current_row);
+# endif
+
+ }
+
+#elif (DIODE_DIRECTION == ROW2COL)
+ // Set col, read rows
+ for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
+# if (DEBOUNCING_DELAY > 0)
+ bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
+ if (matrix_changed) {
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+# else
+ read_rows_on_col(matrix+offset, current_col);
+# endif
+
+ }
+#endif
+
+# if (DEBOUNCING_DELAY > 0)
+ if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
+ for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
+ matrix[i+offset] = matrix_debouncing[i+offset];
+ }
+ debouncing = false;
+ }
+# endif
+
+ return 1;
+}
+
+int serial_transaction(void) {
+ int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
+
+ if (serial_update_buffers()) {
+ return 1;
+ }
+
+ for (int i = 0; i < ROWS_PER_HAND; ++i) {
+ matrix[slaveOffset+i] = serial_slave_buffer[i];
+ }
+
+#ifdef BACKLIGHT_ENABLE
+ // Write backlight level for slave to read
+ serial_master_buffer[SERIAL_LED_ADDR] = backlight_config.enable ? backlight_config.level : 0;
+#endif
+ return 0;
+}
+
+
+uint8_t matrix_scan(void)
+{
+ uint8_t ret = _matrix_scan();
+
+ if( serial_transaction() ) {
+ // turn on the indicator led when halves are disconnected
+ TXLED1;
+
+ error_count++;
+
+ if (error_count > ERROR_DISCONNECT_COUNT) {
+ // reset other half if disconnected
+ int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
+ for (int i = 0; i < ROWS_PER_HAND; ++i) {
+ matrix[slaveOffset+i] = 0;
+ }
+ }
+ } else {
+ // turn off the indicator led on no error
+ TXLED0;
+ error_count = 0;
+ }
+ matrix_scan_quantum();
+ return ret;
+}
+
+void matrix_slave_scan(void) {
+ _matrix_scan();
+
+ int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
+
+ for (int i = 0; i < ROWS_PER_HAND; ++i) {
+ serial_slave_buffer[i] = matrix[offset+i];
+ }
+
+#ifdef BACKLIGHT_ENABLE
+ // Read backlight level sent from master and update level on slave
+ backlight_set(serial_master_buffer[SERIAL_LED_ADDR]);
+#endif
+}
+
+bool matrix_is_modified(void)
+{
+ if (debouncing) return false;
+ return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += bitpop16(matrix[i]);
+ }
+ return count;
+}
+
+#if (DIODE_DIRECTION == COL2ROW)
+
+static void init_cols(void)
+{
+ for(uint8_t x = 0; x < MATRIX_COLS; x++) {
+ uint8_t pin = col_pins[x];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ }
+}
+
+static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
+{
+ // Store last value of row prior to reading
+ matrix_row_t last_row_value = current_matrix[current_row];
+
+ // Clear data in matrix row
+ current_matrix[current_row] = 0;
+
+ // Select row and wait for row selecton to stabilize
+ select_row(current_row);
+ wait_us(30);
+
+ // For each col...
+ for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
+
+ // Select the col pin to read (active low)
+ uint8_t pin = col_pins[col_index];
+ uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
+
+ // Populate the matrix row with the state of the col pin
+ current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
+ }
+
+ // Unselect row
+ unselect_row(current_row);
+
+ return (last_row_value != current_matrix[current_row]);
+}
+
+static void select_row(uint8_t row)
+{
+ uint8_t pin = row_pins[row];
+ _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
+ _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+}
+
+static void unselect_row(uint8_t row)
+{
+ uint8_t pin = row_pins[row];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+}
+
+static void unselect_rows(void)
+{
+ for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
+ uint8_t pin = row_pins[x];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ }
+}
+
+#elif (DIODE_DIRECTION == ROW2COL)
+
+static void init_rows(void)
+{
+ for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
+ uint8_t pin = row_pins[x];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ }
+}
+
+static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
+{
+ bool matrix_changed = false;
+
+ // Select col and wait for col selecton to stabilize
+ select_col(current_col);
+ wait_us(30);
+
+ // For each row...
+ for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
+ {
+
+ // Store last value of row prior to reading
+ matrix_row_t last_row_value = current_matrix[row_index];
+
+ // Check row pin state
+ if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
+ {
+ // Pin LO, set col bit
+ current_matrix[row_index] |= (ROW_SHIFTER << current_col);
+ }
+ else
+ {
+ // Pin HI, clear col bit
+ current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ }
+
+ // Determine if the matrix changed state
+ if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
+ {
+ matrix_changed = true;
+ }
+ }
+
+ // Unselect col
+ unselect_col(current_col);
+
+ return matrix_changed;
+}
+
+static void select_col(uint8_t col)
+{
+ uint8_t pin = col_pins[col];
+ _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
+ _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+}
+
+static void unselect_col(uint8_t col)
+{
+ uint8_t pin = col_pins[col];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+}
+
+static void unselect_cols(void)
+{
+ for(uint8_t x = 0; x < MATRIX_COLS; x++) {
+ uint8_t pin = col_pins[x];
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ }
+}
+
+#endif
diff --git a/keyboards/fortitude60/readme.md b/keyboards/fortitude60/readme.md
new file mode 100644
index 0000000000..58453ccc47
--- /dev/null
+++ b/keyboards/fortitude60/readme.md
@@ -0,0 +1,15 @@
+# Fortitude60
+
+![Fortitude60](https://i.imgur.com/Tbznwgg.jpg)
+
+👊A 60% (12x5) split keyboard with staggerd column layout.👊
+
+Keyboard Maintainer: [Pekaso](https://github.com/Pekaso) [@Pekaso](https://twitter.com/Pekaso)
+Hardware Supported: Fortitude60 PCB, Beetle 32u4
+Hardware Availability: [plustk2s.com](http://plustk2s.com)
+
+Make example for this keyboard (after setting up your build environment):
+
+ make fortitude60/rev1:default:avrdude
+
+See [build environment setup](https://docs.qmk.fm/build_environment_setup.html) then the [make instructions](https://docs.qmk.fm/make_instructions.html) for more information. \ No newline at end of file
diff --git a/keyboards/fortitude60/rev1/config.h b/keyboards/fortitude60/rev1/config.h
new file mode 100644
index 0000000000..4ba195ff8e
--- /dev/null
+++ b/keyboards/fortitude60/rev1/config.h
@@ -0,0 +1,91 @@
+/*
+Copyright 2017 Danny Nguyen <danny@keeb.io>
+
+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 REV1_CONFIG_H
+#define REV1_CONFIG_H
+
+#include QMK_KEYBOARD_CONFIG_H
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xCB10
+#define PRODUCT_ID 0x1156
+#define DEVICE_VER 0x0100
+#define MANUFACTURER Pekaso
+#define PRODUCT The Fortitude60 Keyboard
+#define DESCRIPTION Split 60 keyboard.
+
+/* key matrix size */
+// Rows are doubled-up
+#define MATRIX_ROWS 10
+#define MATRIX_COLS 6
+
+// wiring of each half
+#define MATRIX_ROW_PINS { D1, D0, D3, B7, B6 }
+#define MATRIX_COL_PINS { F7, F6, F5, B3, B2, B1 }
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#ifdef BACKLIGHT_ENABLE
+ #define BACKLIGHT_PIN B5
+ #define BACKLIGHT_LEVELS 9
+// #define BACKLIGHT_BREATHING
+#endif
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* ws2812 RGB LED */
+/* #define RGB_DI_PIN D3 */
+/* #define RGBLIGHT_TIMER */
+/* #define RGBLED_NUM 16 // Number of LEDs */
+/* #define ws2812_PORTREG PORTD */
+/* #define ws2812_DDRREG DDRD */
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+// #define NO_DEBUG
+
+/* disable print */
+// #define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/fortitude60/rev1/rev1.c b/keyboards/fortitude60/rev1/rev1.c
new file mode 100644
index 0000000000..5f4cd32f69
--- /dev/null
+++ b/keyboards/fortitude60/rev1/rev1.c
@@ -0,0 +1,22 @@
+#include "rev1.h"
+
+#ifdef SSD1306OLED
+void led_set_kb(uint8_t usb_led) {
+ // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
+ led_set_user(usb_led);
+}
+#endif
+
+void matrix_init_kb(void) {
+
+ // // green led on
+ // DDRD |= (1<<5);
+ // PORTD &= ~(1<<5);
+
+ // // orange led on
+ // DDRB |= (1<<0);
+ // PORTB &= ~(1<<0);
+
+ matrix_init_user();
+};
+
diff --git a/keyboards/fortitude60/rev1/rev1.h b/keyboards/fortitude60/rev1/rev1.h
new file mode 100644
index 0000000000..b941a60354
--- /dev/null
+++ b/keyboards/fortitude60/rev1/rev1.h