aboutsummaryrefslogtreecommitdiff
path: root/keyboards/fortitude60
diff options
context:
space:
mode:
authorPekaso <pekaso34@gmail.com>2018-06-03 00:48:34 +0900
committerDrashna Jaelre <drashna@live.com>2018-06-02 08:48:34 -0700
commit2196dc9f868334beabd8c3585127a74bf42ce6b7 (patch)
treeed3f7f2edbfd1b36c7082282e5cc89fb2a3892e2 /keyboards/fortitude60
parent9fb1e5d171906e9f10f4489f61d456a9f29499e8 (diff)
downloadqmk_firmware-2196dc9f868334beabd8c3585127a74bf42ce6b7.tar.gz
qmk_firmware-2196dc9f868334beabd8c3585127a74bf42ce6b7.zip
Add support for staggerd column layout KB "Fortitude60" (#3090)
* modifying fortitude for working * add accurate keymap * backlight fix * Fix slave LED Backlight * Add readme.md * modified readme.md * Fixed make error * Commit including suggestions * Add dvorak and colemak layout and some fix
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 000000000..863722d7d
--- /dev/null
+++ b/keyboards/fortitude60/config.h
@@ -0,0 +1,23 @@
1/*
2Copyright 2017 Danny Nguyen <danny@hexwire.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef CONFIG_H
19#define CONFIG_H
20
21#include "config_common.h"
22
23#endif // CONFIG_H
diff --git a/keyboards/fortitude60/fortitude60.c b/keyboards/fortitude60/fortitude60.c
new file mode 100644
index 000000000..d35b286d1
--- /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 000000000..db2ce07a6
--- /dev/null
+++ b/keyboards/fortitude60/fortitude60.h
@@ -0,0 +1,26 @@
1#ifndef FORTITUDE60_H
2#define FORTITUDE60_H
3
4#ifdef KEYBOARD_fortitude60_rev1
5 #include "rev1.h"
6#endif
7
8#include "quantum.h"
9
10// Used to create a keymap using only KC_ prefixed keys
11#define LAYOUT_kc( \
12 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
13 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
14 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
15 L30, L31, L32, L33, L34, L35, LT5, RT5, R30, R31, R32, R33, R34, R35, \
16 LT0, LT1, LT2, LT3, LT4, RT4, RT3, RT2, RT1, RT0 \
17 ) \
18 LAYOUT( \
19 KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \
20 KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \
21 KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \
22 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, \
23 KC_##LT0, KC_##LT1, KC_##LT2, KC_##LT3, KC_##LT4, KC_##RT4, KC_##RT3, KC_##RT2, KC_##RT1, KC_##RT0 \
24 )
25
26#endif
diff --git a/keyboards/fortitude60/keymaps/default/config.h b/keyboards/fortitude60/keymaps/default/config.h
new file mode 100644
index 000000000..b356791fc
--- /dev/null
+++ b/keyboards/fortitude60/keymaps/default/config.h
@@ -0,0 +1,39 @@
1/*
2Copyright 2017 Danny Nguyen <danny@hexwire.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef CONFIG_USER_H
19#define CONFIG_USER_H
20
21#include "config_common.h"
22
23#define USE_SERIAL
24
25/* Select hand configuration */
26
27// #define MASTER_LEFT
28// #define MASTER_RIGHT
29#define EE_HANDS
30
31#define USE_SERIAL_PD2
32/* #undef RGBLED_NUM */
33/* #define RGBLIGHT_ANIMATIONS */
34/* #define RGBLED_NUM 12 */
35/* #define RGBLIGHT_HUE_STEP 8 */
36/* #define RGBLIGHT_SAT_STEP 8 */
37/* #define RGBLIGHT_VAL_STEP 8 */
38
39#endif
diff --git a/keyboards/fortitude60/keymaps/default/keymap.c b/keyboards/fortitude60/keymaps/default/keymap.c
new file mode 100644
index 000000000..18d2527e4
--- /dev/null
+++ b/keyboards/fortitude60/keymaps/default/keymap.c
@@ -0,0 +1,189 @@
1#include QMK_KEYBOARD_H
2#include "eeconfig.h"
3
4extern keymap_config_t keymap_config;
5
6// Each layer gets a name for readability, which is then used in the keymap matrix below.
7// The underscores don't mean anything - you can have a layer called STUFF or any other name.
8// Layer names don't all need to be of the same length, obviously, and you can also skip them
9// entirely and just use numbers.
10#define _QWERTY 0
11#define _COLEMAK 1
12#define _DVORAK 2
13#define _LOWER 3
14#define _RAISE 4
15#define _ADJUST 16
16
17enum custom_keycodes {
18 QWERTY = SAFE_RANGE,
19 COLEMAK,
20 DVORAK,
21 LOWER,
22 RAISE,
23 ADJUST,
24};
25
26// Fillers to make layering more clear
27#define _______ KC_TRNS
28#define XXXXXXX KC_NO
29#define LOWER MO(_LOWER)
30#define RAISE MO(_RAISE)
31
32const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
33
34/* Qwerty
35 * ,-----------------------------------------. ,-----------------------------------------.
36 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
37 * |------+------+------+------+------+------| |------+------+------+------+------+------|
38 * | Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
39 * |------+------+------+------+------+------| |------+------+------+------+------+------|
40 * | Esc | A | S | D | F | G | | H | J | K | L | ; | " |
41 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
42 * | Shift| Z | X | C | V | B | [ | ] | N | M | , | . | / |Enter |
43 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
44 * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
45 * `---------------------------------------------------------------------'
46 */
47[_QWERTY] = LAYOUT( \
48 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
49 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
50 KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
51 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 , \
52 KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
53),
54
55/* Colemak
56 * ,-----------------------------------------. ,-----------------------------------------.
57 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
58 * |------+------+------+------+------+------| |------+------+------+------+------+------|
59 * | Tab | Q | W | F | P | G | | J | L | U | Y | ; | Bksp |
60 * |------+------+------+------+------+------| |------+------+------+------+------+------|
61 * | Esc | A | R | S | T | D | | H | N | E | I | O | " |
62 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
63 * | Shift| Z | X | C | V | B | [ | ] | K | M | , | . | / |Enter |
64 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
65 * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
66 * `---------------------------------------------------------------------'
67 */
68[_COLEMAK] = LAYOUT( \
69 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
70 KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, \
71 KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, \
72 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 , \
73 KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
74),
75
76/* Dvorak
77 * ,-----------------------------------------. ,-----------------------------------------.
78 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
79 * |------+------+------+------+------+------| |------+------+------+------+------+------|
80 * | Tab | " | , | . | P | Y | | F | G | C | R | L | Bksp |
81 * |------+------+------+------+------+------| |------+------+------+------+------+------|
82 * | Esc | A | O | E | U | I | | D | H | T | N | S | / |
83 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
84 * | Shift| ; | Q | J | K | X | [ | ] | B | M | W | V | Z |Enter |
85 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
86 * | GUI | Ctrl |Lower |Space | Ctrl |Enter |Space |Raise | Alt | GUI |
87 * `---------------------------------------------------------------------'
88 */
89[_DVORAK] = LAYOUT( \
90 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
91 KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, \
92 KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, \
93 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 , \
94 KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_LCTL, KC_ENT, KC_SPC, RAISE, KC_RALT, KC_RGUI\
95),
96
97/* Lower
98 * ,-----------------------------------------. ,-----------------------------------------.
99 * | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | |
100 * |------+------+------+------+------+------| |------+------+------+------+------+------|
101 * | ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | Del |
102 * |------+------+------+------+------+------| |------+------+------+------+------+------|
103 * | Del | F1 | F2 | F3 | F4 | F5 | | F6 | _ | + | | \ | | |
104 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
105 * | | F7 | F8 | F9 | F10 | F11 | | | F12 |ISO ~ |ISO | | | | |
106 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
107 * | | | | | | | | | | |
108 * `---------------------------------------------------------------------'
109 */
110[_LOWER] = LAYOUT( \
111 KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, \
112 KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL, \
113 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
114 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______,\
115 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
116),
117
118/* Raise
119 * ,-----------------------------------------. ,-----------------------------------------.
120 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Del |
121 * |------+------+------+------+------+------. ,------+------+------+------+------+------|
122 * | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | Bksp |
123 * |------+------+------+------+------+------. ,------+------+------+------+------+------|
124 * | Del | F1 | F2 | F3 | F4 | F5 | | F6 | - | = | [ | ] | | |
125 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
126 * | | F7 | F8 | F9 | F10 | F11 | | | F12 |ISO # |ISO / | | | |
127 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
128 * | | | | | | | | | | |
129 * `---------------------------------------------------------------------'
130 */
131[_RAISE] = LAYOUT( \
132 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL, \
133 KC_GRV, KC_1, KC_UP, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \
134 KC_DEL, KC_LEFT, KC_DOWN, KC_RGHT, KC_F4, KC_F5, KC_F6,KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
135 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______, \
136 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
137),
138
139/* Adjust (Lower + Raise)
140 * ,-----------------------------------------. ,-----------------------------------------.
141 * | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
142 * |------+------+------+------+------+------. ,------+------+------+------+------+------|
143 * | | Reset|RGB Tg|RGB Md|Hue Up|Hue Dn| |Sat Up|Sat Dn|Val Up|Val Dn| | Bksp |
144 * |------+------+------+------+------+------. ,------+------+------+------+------+------|
145 * | | | |Aud on|Audoff|AGnorm| |AGswap| |BL TOG|BL STP| | |
146 * |------+------+------+------+------+------+-------------+------+------+------+------+------+------|
147 * |Qwerty|Colemk|Dvorak| | | | | | | | | | | |
148 * `-------------+------+------+------+------+------+------+------+------+------+------+-------------'
149 * | | | | | | | | | | |
150 * `---------------------------------------------------------------------'
151 */
152[_ADJUST] = LAYOUT( \
153 KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \
154 _______, RESET , RGB_TOG, RGB_MOD, RGB_HUD, RGB_HUI, RGB_SAD, RGB_SAI, RGB_VAD, RGB_VAI, _______, KC_BSPC, \
155 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, _______, BL_TOGG, BL_STEP, _______, _______, \
156 QWERTY, COLEMAK, DVORAK, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
157 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______\
158)
159
160
161};
162
163uint32_t layer_state_set_user(uint32_t state) {
164 return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
165}
166
167bool process_record_user(uint16_t keycode, keyrecord_t *record) {
168 switch (keycode) {
169 case QWERTY:
170 if (record->event.pressed) {
171 set_single_persistent_default_layer(_QWERTY);
172 }
173 return false;
174 break;
175 case COLEMAK:
176 if (record->event.pressed) {
177 set_single_persistent_default_layer(_COLEMAK);
178 }
179 return false;
180 break;
181 case DVORAK:
182 if (record->event.pressed) {
183 set_single_persistent_default_layer(_DVORAK);
184 }
185 return false;
186 break;
187 }
188 return true;
189}
diff --git a/keyboards/fortitude60/keymaps/default/rules.mk b/keyboards/fortitude60/keymaps/default/rules.mk
new file mode 100644
index 000000000..e0ed6f0c2
--- /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 000000000..565f417d8
--- /dev/null
+++ b/keyboards/fortitude60/matrix.c
@@ -0,0 +1,423 @@
1/*
2Copyright 2017 Danny Nguyen <danny@keeb.io>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * scan matrix
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#include <avr/io.h>
24#include "wait.h"
25#include "print.h"
26#include "debug.h"
27#include "util.h"
28#include "matrix.h"
29#include "split_util.h"
30#include "pro_micro.h"
31#include "config.h"
32#include "timer.h"
33
34#ifdef BACKLIGHT_ENABLE
35#include "backlight.h"
36extern backlight_config_t backlight_config;
37#endif
38
39#include "serial.h"
40
41#ifndef DEBOUNCING_DELAY
42# define DEBOUNCING_DELAY 5
43#endif
44
45#if (DEBOUNCING_DELAY > 0)
46 static uint16_t debouncing_time;
47 static bool debouncing = false;
48#endif
49
50#if (MATRIX_COLS <= 8)
51# define print_matrix_header() print("\nr/c 01234567\n")
52# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
53# define matrix_bitpop(i) bitpop(matrix[i])
54# define ROW_SHIFTER ((uint8_t)1)
55#else
56# error "Currently only supports 8 COLS"
57#endif
58static matrix_row_t matrix_debouncing[MATRIX_ROWS];
59
60#define ERROR_DISCONNECT_COUNT 5
61
62#define SERIAL_LED_ADDR 0x00
63
64#define ROWS_PER_HAND (MATRIX_ROWS/2)
65
66static uint8_t error_count = 0;
67
68static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
69static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
70
71/* matrix state(1:on, 0:off) */
72static matrix_row_t matrix[MATRIX_ROWS];
73static matrix_row_t matrix_debouncing[MATRIX_ROWS];
74
75#if (DIODE_DIRECTION == COL2ROW)
76 static void init_cols(void);
77 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
78 static void unselect_rows(void);
79 static void select_row(uint8_t row);
80 static void unselect_row(uint8_t row);
81#elif (DIODE_DIRECTION == ROW2COL)
82 static void init_rows(void);
83 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
84 static void unselect_cols(void);
85 static void unselect_col(uint8_t col);
86 static void select_col(uint8_t col);
87#endif
88
89
90__attribute__ ((weak))
91void matrix_init_kb(void) {
92 matrix_init_user();
93}
94
95__attribute__ ((weak))
96void matrix_scan_kb(void) {
97 matrix_scan_user();
98}
99
100__attribute__ ((weak))
101void matrix_init_user(void) {
102}
103
104__attribute__ ((weak))
105void matrix_scan_user(void) {
106}
107
108inline
109uint8_t matrix_rows(void)
110{
111 return MATRIX_ROWS;
112}
113
114inline
115uint8_t matrix_cols(void)
116{
117 return MATRIX_COLS;
118}
119
120void matrix_init(void)
121{
122 debug_enable = true;
123 debug_matrix = true;
124 debug_mouse = true;
125 // initialize row and col
126 unselect_rows();
127 init_cols();
128
129 TX_RX_LED_INIT;
130
131 // initialize matrix state: all keys off
132 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
133 matrix[i] = 0;
134 matrix_debouncing[i] = 0;
135 }
136
137 matrix_init_quantum();
138
139}
140
141uint8_t _matrix_scan(void)
142{
143 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
144#if (DIODE_DIRECTION == COL2ROW)
145 // Set row, read cols
146 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
147# if (DEBOUNCING_DELAY > 0)
148 bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
149
150 if (matrix_changed) {
151 debouncing = true;
152 debouncing_time = timer_read();
153 }
154
155# else
156 read_cols_on_row(matrix+offset, current_row);
157# endif
158
159 }
160
161#elif (DIODE_DIRECTION == ROW2COL)
162 // Set col, read rows
163 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
164# if (DEBOUNCING_DELAY > 0)
165 bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
166 if (matrix_changed) {
167 debouncing = true;
168 debouncing_time = timer_read();
169 }
170# else
171 read_rows_on_col(matrix+offset, current_col);
172# endif
173
174 }
175#endif
176
177# if (DEBOUNCING_DELAY > 0)
178 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
179 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
180 matrix[i+offset] = matrix_debouncing[i+offset];
181 }
182 debouncing = false;
183 }
184# endif
185
186 return 1;
187}
188
189int serial_transaction(void) {
190 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
191
192 if (serial_update_buffers()) {
193 return 1;
194 }
195
196 for (int i = 0; i < ROWS_PER_HAND; ++i) {
197 matrix[slaveOffset+i] = serial_slave_buffer[i];
198 }
199
200#ifdef BACKLIGHT_ENABLE
201 // Write backlight level for slave to read
202 serial_master_buffer[SERIAL_LED_ADDR] = backlight_config.enable ? backlight_config.level : 0;
203#endif
204 return 0;
205}
206
207
208uint8_t matrix_scan(void)
209{
210 uint8_t ret = _matrix_scan();
211
212 if( serial_transaction() ) {
213 // turn on the indicator led when halves are disconnected
214 TXLED1;
215
216 error_count++;
217
218 if (error_count > ERROR_DISCONNECT_COUNT) {
219 // reset other half if disconnected
220 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
221 for (int i = 0; i < ROWS_PER_HAND; ++i) {
222 matrix[slaveOffset+i] = 0;
223 }
224 }
225 } else {
226 // turn off the indicator led on no error
227 TXLED0;
228 error_count = 0;
229 }
230 matrix_scan_quantum();
231 return ret;
232}
233
234void matrix_slave_scan(void) {
235 _matrix_scan();
236
237 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
238
239 for (int i = 0; i < ROWS_PER_HAND; ++i) {
240 serial_slave_buffer[i] = matrix[offset+i];
241 }
242
243#ifdef BACKLIGHT_ENABLE
244 // Read backlight level sent from master and update level on slave
245 backlight_set(serial_master_buffer[SERIAL_LED_ADDR]);
246#endif
247}
248
249bool matrix_is_modified(void)
250{
251 if (debouncing) return false;
252 return true;
253}
254
255inline
256bool matrix_is_on(uint8_t row, uint8_t col)
257{
258 return (matrix[row] & ((matrix_row_t)1<<col));
259}
260
261inline
262matrix_row_t matrix_get_row(uint8_t row)
263{
264 return matrix[row];
265}
266
267void matrix_print(void)
268{
269 print("\nr/c 0123456789ABCDEF\n");
270 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
271 phex(row); print(": ");
272 pbin_reverse16(matrix_get_row(row));
273 print("\n");
274 }
275}
276
277uint8_t matrix_key_count(void)
278{
279 uint8_t count = 0;
280 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
281 count += bitpop16(matrix[i]);
282 }
283 return count;
284}
285
286#if (DIODE_DIRECTION == COL2ROW)
287
288static void init_cols(void)
289{
290 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
291 uint8_t pin = col_pins[x];
292 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
293 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
294 }
295}
296
297static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
298{
299 // Store last value of row prior to reading
300 matrix_row_t last_row_value = current_matrix[current_row];
301
302 // Clear data in matrix row
303 current_matrix[current_row] = 0;
304
305 // Select row and wait for row selecton to stabilize
306 select_row(current_row);
307 wait_us(30);
308
309 // For each col...
310 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
311
312 // Select the col pin to read (active low)
313 uint8_t pin = col_pins[col_index];
314 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
315
316 // Populate the matrix row with the state of the col pin
317 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
318 }
319
320 // Unselect row
321 unselect_row(current_row);
322
323 return (last_row_value != current_matrix[current_row]);
324}
325
326static void select_row(uint8_t row)
327{
328 uint8_t pin = row_pins[row];
329 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
330 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
331}
332
333static void unselect_row(uint8_t row)
334{
335 uint8_t pin = row_pins[row];
336 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
337 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
338}
339
340static void unselect_rows(void)
341{
342 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
343 uint8_t pin = row_pins[x];
344 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
345 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
346 }
347}
348
349#elif (DIODE_DIRECTION == ROW2COL)
350
351static void init_rows(void)
352{
353 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
354 uint8_t pin = row_pins[x];
355 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
356 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
357 }
358}
359
360static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
361{
362 bool matrix_changed = false;
363
364 // Select col and wait for col selecton to stabilize
365 select_col(current_col);
366 wait_us(30);
367
368 // For each row...
369 for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
370 {
371
372 // Store last value of row prior to reading
373 matrix_row_t last_row_value = current_matrix[row_index];
374
375 // Check row pin state
376 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
377 {
378 // Pin LO, set col bit
379 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
380 }
381 else
382 {
383 // Pin HI, clear col bit
384 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
385 }
386
387 // Determine if the matrix changed state
388 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
389 {
390 matrix_changed = true;
391 }
392 }
393
394 // Unselect col
395 unselect_col(current_col);
396
397 return matrix_changed;
398}
399
400static void select_col(uint8_t col)
401{
402 uint8_t pin = col_pins[col];
403 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
404 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
405}
406
407static void unselect_col(uint8_t col)
408{
409 uint8_t pin = col_pins[col];
410 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
411 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
412}
413
414static void unselect_cols(void)
415{
416 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
417 uint8_t pin = col_pins[x];
418 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
419 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
420 }
421}
422
423#endif
diff --git a/keyboards/fortitude60/readme.md b/keyboards/fortitude60/readme.md
new file mode 100644
index 000000000..58453ccc4
--- /dev/null
+++ b/keyboards/fortitude60/readme.md
@@ -0,0 +1,15 @@
1# Fortitude60
2
3![Fortitude60](https://i.imgur.com/Tbznwgg.jpg)
4
5👊A 60% (12x5) split keyboard with staggerd column layout.👊
6
7Keyboard Maintainer: [Pekaso](https://github.com/Pekaso) [@Pekaso](https://twitter.com/Pekaso)
8Hardware Supported: Fortitude60 PCB, Beetle 32u4
9Hardware Availability: [plustk2s.com](http://plustk2s.com)
10
11Make example for this keyboard (after setting up your build environment):
12
13 make fortitude60/rev1:default:avrdude
14
15See [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 000000000..4ba195ff8
--- /dev/null
+++ b/keyboards/fortitude60/rev1/config.h
@@ -0,0 +1,91 @@
1/*
2Copyright 2017 Danny Nguyen <danny@keeb.io>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef REV1_CONFIG_H
19#define REV1_CONFIG_H
20
21#include QMK_KEYBOARD_CONFIG_H
22
23/* USB Device descriptor parameter */
24#define VENDOR_ID 0xCB10
25#define PRODUCT_ID 0x1156
26#define DEVICE_VER 0x0100
27#define MANUFACTURER Pekaso
28#define PRODUCT The Fortitude60 Keyboard
29#define DESCRIPTION Split 60 keyboard.
30
31/* key matrix size */
32// Rows are doubled-up
33#define MATRIX_ROWS 10
34#define MATRIX_COLS 6
35
36// wiring of each half
37#define MATRIX_ROW_PINS { D1, D0, D3, B7, B6 }
38#define MATRIX_COL_PINS { F7, F6, F5, B3, B2, B1 }
39
40/* COL2ROW or ROW2COL */
41#define DIODE_DIRECTION COL2ROW
42
43/* define if matrix has ghost */
44//#define MATRIX_HAS_GHOST
45
46/* number of backlight levels */
47#ifdef BACKLIGHT_ENABLE
48 #define BACKLIGHT_PIN B5
49 #define BACKLIGHT_LEVELS 9
50// #define BACKLIGHT_BREATHING
51#endif
52
53/* Set 0 if debouncing isn't needed */
54#define DEBOUNCING_DELAY 5
55
56/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
57#define LOCKING_SUPPORT_ENABLE
58/* Locking resynchronize hack */
59#define LOCKING_RESYNC_ENABLE
60
61/* key combination for command */
62#define IS_COMMAND() ( \
63 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
64)
65
66/* ws2812 RGB LED */
67/* #define RGB_DI_PIN D3 */
68/* #define RGBLIGHT_TIMER */
69/* #define RGBLED_NUM 16 // Number of LEDs */
70/* #define ws2812_PORTREG PORTD */
71/* #define ws2812_DDRREG DDRD */
72
73/*
74 * Feature disable options
75 * These options are also useful to firmware size reduction.
76 */
77
78/* disable debug print */
79// #define NO_DEBUG
80
81/* disable print */
82// #define NO_PRINT
83
84/* disable action features */
85//#define NO_ACTION_LAYER
86//#define NO_ACTION_TAPPING
87//#define NO_ACTION_ONESHOT
88//#define NO_ACTION_MACRO
89//#define NO_ACTION_FUNCTION
90
91#endif
diff --git a/keyboards/fortitude60/rev1/rev1.c b/keyboards/fortitude60/rev1/rev1.c
new file mode 100644
index 000000000..5f4cd32f6
--- /dev/null
+++ b/keyboards/fortitude60/rev1/rev1.c
@@ -0,0 +1,22 @@
1#include "rev1.h"
2
3#ifdef SSD1306OLED
4void led_set_kb(uint8_t usb_led) {
5 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
6 led_set_user(usb_led);
7}
8#endif
9
10void matrix_init_kb(void) {
11
12 // // green led on
13 // DDRD |= (1<<5);
14 // PORTD &= ~(1<<5);
15
16 // // orange led on
17 // DDRB |= (1<<0);
18 // PORTB &= ~(1<<0);
19
20 matrix_init_user();
21};
22
diff --git a/keyboards/fortitude60/rev1/rev1.h b/keyboards/fortitude60/rev1/rev1.h
new file mode 100644
index 000000000..b941a6035
--- /dev/null
+++ b/keyboards/fortitude60/rev1/rev1.h
@@ -0,0 +1,44 @@
1#ifndef REV1_H
2#define REV1_H
3
4#include "fortitude60.h"
5
6//void promicro_bootloader_jmp(bool program);
7#include "quantum.h"
8
9
10#ifdef USE_I2C
11#include <stddef.h>
12#ifdef __AVR__
13 #include <avr/io.h>
14 #include <avr/interrupt.h>
15#endif
16#endif
17
18//void promicro_bootloader_jmp(bool program);
19
20// Standard Keymap
21// (TRRS jack on the left half is to the right, TRRS jack on the right half is to the left)
22#define LAYOUT( \
23 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
24 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
25 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
26 L30, L31, L32, L33, L34, L35, LT5, RT5, R30, R31, R32, R33, R34, R35, \
27 LT0, LT1, LT2, LT3, LT4, RT4, RT3, RT2, RT1, RT0 \
28 ) \
29 { \
30 { L00, L01, L02, L03, L04, L05 }, \
31 { L10, L11, L12, L13, L14, L15 }, \
32 { L20, L21, L22, L23, L24, L25 }, \
33 { L30, L31, L32, L33, L34, L35 }, \
34 { LT0, LT1, LT2, LT3, LT4, LT5 }, \
35 { R05, R04, R03, R02, R01, R00 }, \
36 { R15, R14, R13, R12, R11, R10 }, \
37 { R25, R24, R23, R22, R21, R20 }, \
38 { R35, R34, R33, R32, R31, R30 }, \
39 { RT0, RT1, RT2, RT3, RT4, RT5 } \
40 }
41
42#define LAYOUT_ortho_5x12 LAYOUT
43
44#endif
diff --git a/keyboards/fortitude60/rev1/rules.mk b/keyboards/fortitude60/rev1/rules.mk
new file mode 100644
index 000000000..bd518d8f2
--- /dev/null
+++ b/keyboards/fortitude60/rev1/rules.mk
@@ -0,0 +1 @@
BACKLIGHT_ENABLE = yes
diff --git a/keyboards/fortitude60/rules.mk b/keyboards/fortitude60/rules.mk
new file mode 100644
index 000000000..7b2557b70
--- /dev/null
+++ b/keyboards/fortitude60/rules.mk
@@ -0,0 +1,72 @@
1SRC += matrix.c \
2 split_util.c \
3 serial.c
4
5# MCU name
6#MCU = at90usb1287
7MCU = atmega32u4
8
9# Processor frequency.
10# This will define a symbol, F_CPU, in all source code files equal to the
11# processor frequency in Hz. You can then use this symbol in your source code to
12# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
13# automatically to create a 32-bit value in your source code.
14#
15# This will be an integer division of F_USB below, as it is sourced by
16# F_USB after it has run through any CPU prescalers. Note that this value
17# does not *change* the processor frequency - it should merely be updated to
18# reflect the processor speed set externally so that the code can use accurate
19# software delays.
20F_CPU = 16000000
21
22#
23# LUFA specific
24#
25# Target architecture (see library "Board Types" documentation).
26ARCH = AVR8
27
28# Input clock frequency.
29# This will define a symbol, F_USB, in all source code files equal to the
30# input clock frequency (before any prescaling is performed) in Hz. This value may
31# differ from F_CPU if prescaling is used on the latter, and is required as the
32# raw input clock is fed directly to the PLL sections of the AVR for high speed
33# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
34# at the end, this will be done automatically to create a 32-bit value in your
35# source code.
36#
37# If no clock division is performed on the input clock inside the AVR (via the
38# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
39F_USB = $(F_CPU)
40
41# Bootloader
42# This definition is optional, and if your keyboard supports multiple bootloaders of
43# different sizes, comment this out, and the correct address will be loaded
44# automatically (+60). See bootloader.mk for all options.
45BOOTLOADER = caterina
46
47# Interrupt driven control endpoint task(+60)
48OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
49
50# Build Options
51# change to "no" to disable the options, or define them in the Makefile in
52# the appropriate keymap folder that will get included automatically
53#
54BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
55MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
56EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
57CONSOLE_ENABLE = no # Console for debug(+400)
58COMMAND_ENABLE = yes # Commands for debug and configuration
59NKRO_ENABLE = no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
60BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
61MIDI_ENABLE = no # MIDI controls
62AUDIO_ENABLE = no # Audio output on port C6
63UNICODE_ENABLE = no # Unicode
64BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
65RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
66USE_SERIAL = yes # Serial support only on fortitude60
67# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
68SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
69
70CUSTOM_MATRIX = yes
71
72DEFAULT_FOLDER = fortitude60/rev1
diff --git a/keyboards/fortitude60/serial.c b/keyboards/fortitude60/serial.c
new file mode 100644
index 000000000..46dfad021
--- /dev/null
+++ b/keyboards/fortitude60/serial.c
@@ -0,0 +1,235 @@
1/*
2 * WARNING: be careful changing this code, it is very timing dependent
3 */
4
5#ifndef F_CPU
6#define F_CPU 16000000
7#endif
8
9#include <avr/io.h>
10#include <avr/interrupt.h>
11#include <util/delay.h>
12#include <stdbool.h>
13#include "serial.h"
14
15#ifndef USE_I2C
16
17// Serial pulse period in microseconds. Its probably a bad idea to lower this
18// value.
19#define SERIAL_DELAY 24
20
21uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
22uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
23
24#define SLAVE_DATA_CORRUPT (1<<0)
25volatile uint8_t status = 0;
26
27inline static
28void serial_delay(void) {
29 _delay_us(SERIAL_DELAY);
30}
31
32inline static
33void serial_output(void) {
34 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
35}
36
37// make the serial pin an input with pull-up resistor
38inline static
39void serial_input(void) {
40 SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
41 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
42}
43
44inline static
45uint8_t serial_read_pin(void) {
46 return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
47}
48
49inline static
50void serial_low(void) {
51 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
52}
53
54inline static
55void serial_high(void) {
56 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
57}
58
59void serial_master_init(void) {
60 serial_output();
61 serial_high();
62}
63
64void serial_slave_init(void) {
65 serial_input();
66
67#ifndef USE_SERIAL_PD2
68 // Enable INT0
69 EIMSK |= _BV(INT0);
70 // Trigger on falling edge of INT0
71 EICRA &= ~(_BV(ISC00) | _BV(ISC01));
72#else
73 // Enable INT2
74 EIMSK |= _BV(INT2);
75 // Trigger on falling edge of INT2
76 EICRA &= ~(_BV(ISC20) | _BV(ISC21));
77#endif
78}
79
80// Used by the master to synchronize timing with the slave.
81static
82void sync_recv(void) {
83 serial_input();
84 // This shouldn't hang if the slave disconnects because the
85 // serial line will float to high if the slave does disconnect.
86 while (!serial_read_pin());
87 serial_delay();
88}
89
90// Used by the slave to send a synchronization signal to the master.
91static
92void sync_send(void) {
93 serial_output();
94
95 serial_low();
96 serial_delay();
97
98 serial_high();
99}
100
101// Reads a byte from the serial line
102static
103uint8_t serial_read_byte(void) {
104 uint8_t byte = 0;
105 serial_input();
106 for ( uint8_t i = 0; i < 8; ++i) {
107 byte = (byte << 1) | serial_read_pin();
108 serial_delay();
109 _delay_us(1);
110 }
111
112 return byte;
113}
114
115// Sends a byte with MSB ordering
116static
117void serial_write_byte(uint8_t data) {
118 uint8_t b = 8;
119 serial_output();
120 while( b-- ) {
121 if(data & (1 << b)) {
122 serial_high();
123 } else {
124 serial_low();
125 }
126 serial_delay();
127 }
128}
129
130// interrupt handle to be used by the slave device
131ISR(SERIAL_PIN_INTERRUPT) {
132 sync_send();
133
134 uint8_t checksum = 0;
135 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
136 serial_write_byte(serial_slave_buffer[i]);
137 sync_send();
138 checksum += serial_slave_buffer[i];
139 }
140 serial_write_byte(checksum);
141 sync_send();
142
143 // wait for the sync to finish sending
144 serial_delay();
145
146 // read the middle of pulses
147 _delay_us(SERIAL_DELAY/2);
148
149 uint8_t checksum_computed = 0;
150 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
151 serial_master_buffer[i] = serial_read_byte();
152 sync_send();
153 checksum_computed += serial_master_buffer[i];
154 }
155 uint8_t checksum_received = serial_read_byte();
156 sync_send();
157
158 serial_input(); // end transaction
159
160 if ( checksum_computed != checksum_received ) {
161 status |= SLAVE_DATA_CORRUPT;
162 } else {
163 status &= ~SLAVE_DATA_CORRUPT;
164 }
165}
166
167inline
168bool serial_slave_DATA_CORRUPT(void) {
169 return status & SLAVE_DATA_CORRUPT;
170}
171
172// Copies the serial_slave_buffer to the master and sends the
173// serial_master_buffer to the slave.
174//
175// Returns:
176// 0 => no error
177// 1 => slave did not respond
178int serial_update_buffers(void) {
179 // this code is very time dependent, so we need to disable interrupts
180 cli();
181
182 // signal to the slave that we want to start a transaction
183 serial_output();
184 serial_low();
185 _delay_us(1);
186
187 // wait for the slaves response
188 serial_input();
189 serial_high();
190 _delay_us(SERIAL_DELAY);
191
192 // check if the slave is present
193 if (serial_read_pin()) {
194 // slave failed to pull the line low, assume not present
195 sei();
196 return 1;
197 }
198
199 // if the slave is present syncronize with it
200 sync_recv();
201
202 uint8_t checksum_computed = 0;
203 // receive data from the slave
204 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
205 serial_slave_buffer[i] = serial_read_byte();
206 sync_recv();
207 checksum_computed += serial_slave_buffer[i];
208 }
209 uint8_t checksum_received = serial_read_byte();
210 sync_recv();
211
212 if (checksum_computed != checksum_received) {
213 sei();
214 return 2;
215 }
216
217 uint8_t checksum = 0;
218 // send data to the slave
219 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
220 serial_write_byte(serial_master_buffer[i]);
221 sync_recv();
222 checksum += serial_master_buffer[i];
223 }
224 serial_write_byte(checksum);
225 sync_recv();
226
227 // always, release the line when not in use
228 serial_output();
229 serial_high();
230
231 sei();
232 return 0;
233}
234
235#endif
diff --git a/keyboards/fortitude60/serial.h b/keyboards/fortitude60/serial.h
new file mode 100644
index 000000000..361f1881b
--- /dev/null
+++ b/keyboards/fortitude60/serial.h
@@ -0,0 +1,32 @@
1#ifndef MY_SERIAL_H
2#define MY_SERIAL_H
3
4#include "config.h"
5#include <stdbool.h>
6
7/* TODO: some defines for interrupt setup */
8#define SERIAL_PIN_DDR DDRD
9#define SERIAL_PIN_PORT PORTD
10#define SERIAL_PIN_INPUT PIND
11
12#ifndef USE_SERIAL_PD2
13#define SERIAL_PIN_MASK _BV(PD0)
14#define SERIAL_PIN_INTERRUPT INT0_vect
15#else
16#define SERIAL_PIN_MASK _BV(PD2)
17#define SERIAL_PIN_INTERRUPT INT2_vect
18#endif
19
20#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
21#define SERIAL_MASTER_BUFFER_LENGTH 1
22
23// Buffers for master - slave communication
24extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
25extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
26
27void serial_master_init(void);
28void serial_slave_init(void);
29int serial_update_buffers(void);
30bool serial_slave_data_corrupt(void);
31
32#endif
diff --git a/keyboards/fortitude60/split_util.c b/keyboards/fortitude60/split_util.c
new file mode 100644
index 000000000..1adae7844
--- /dev/null
+++ b/keyboards/fortitude60/split_util.c
@@ -0,0 +1,85 @@
1#include <avr/io.h>
2#include <avr/wdt.h>
3#include <avr/power.h>
4#include <avr/interrupt.h>
5#include <util/delay.h>
6#include <avr/eeprom.h>
7#include "split_util.h"
8#include "matrix.h"
9#include "keyboard.h"
10#include "config.h"
11#include "timer.h"
12
13#include "serial.h"
14
15volatile bool isLeftHand = true;
16
17static void setup_handedness(void) {
18 #ifdef EE_HANDS
19 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
20 #else
21 // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
22 #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
23 isLeftHand = !has_usb();
24 #else
25 isLeftHand = has_usb();
26 #endif
27 #endif
28}
29
30static void keyboard_master_setup(void) {
31#ifdef USE_I2C
32 i2c_master_init();
33#ifdef SSD1306OLED
34 matrix_master_OLED_init ();
35#endif
36#else
37 serial_master_init();
38#endif
39}
40
41static void keyboard_slave_setup(void) {
42 timer_init();
43#ifdef USE_I2C
44 i2c_slave_init(SLAVE_I2C_ADDRESS);
45#else
46 serial_slave_init();
47#endif
48}
49
50bool has_usb(void) {
51 /* return (UDADDR & _BV(ADDEN)); */
52 USBCON |= (1 << OTGPADE); //enables VBUS pad
53 _delay_us(5);
54 return (USBSTA & (1<<VBUS)); //checks state of VBUS
55}
56
57void split_keyboard_setup(void) {
58 setup_handedness();
59
60 if (isLeftHand) {
61 /* if (has_usb()) { */
62 keyboard_master_setup();
63 } else {
64 keyboard_slave_setup();
65 }
66 sei();
67}
68
69void keyboard_slave_loop(void) {
70 matrix_init();
71
72 while (1) {
73 matrix_slave_scan();
74 }
75}
76
77// this code runs before the usb and keyboard is initialized
78void matrix_setup(void) {
79 split_keyboard_setup();
80
81 if (!isLeftHand) {
82 /* if (!has_usb()) { */
83 keyboard_slave_loop();
84 }
85}
diff --git a/keyboards/fortitude60/split_util.h b/keyboards/fortitude60/split_util.h
new file mode 100644
index 000000000..28fff3e79
--- /dev/null
+++ b/keyboards/fortitude60/split_util.h
@@ -0,0 +1,18 @@
1#ifndef SPLIT_KEYBOARD_UTIL_H
2#define SPLIT_KEYBOARD_UTIL_H
3
4#include <stdbool.h>
5#include "eeconfig.h"
6
7extern volatile bool isLeftHand;
8
9// slave version of matix scan, defined in matrix.c
10void matrix_slave_scan(void);
11
12void split_keyboard_setup(void);
13bool has_usb(void);
14void keyboard_slave_loop(void);
15
16void matrix_master_OLED_init (void);
17
18#endif