aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/handwired/xeal60/config.h24
-rw-r--r--keyboards/handwired/xeal60/info.json12
-rw-r--r--keyboards/handwired/xeal60/keymaps/default/config.h37
-rw-r--r--keyboards/handwired/xeal60/keymaps/default/keymap.c129
-rw-r--r--keyboards/handwired/xeal60/keymaps/default/rules.mk3
-rw-r--r--keyboards/handwired/xeal60/lets_split.c1
-rw-r--r--keyboards/handwired/xeal60/lets_split.h28
-rw-r--r--keyboards/handwired/xeal60/matrix.c470
-rw-r--r--keyboards/handwired/xeal60/readme.md187
-rw-r--r--keyboards/handwired/xeal60/rev1/config.h93
-rw-r--r--keyboards/handwired/xeal60/rev1/rev1.c15
-rw-r--r--keyboards/handwired/xeal60/rev1/rev1.h33
-rw-r--r--keyboards/handwired/xeal60/rev1/rules.mk1
-rw-r--r--keyboards/handwired/xeal60/rules.mk77
-rw-r--r--keyboards/handwired/xeal60/serial.c228
-rw-r--r--keyboards/handwired/xeal60/serial.h26
-rw-r--r--keyboards/handwired/xeal60/split_util.c86
-rw-r--r--keyboards/handwired/xeal60/split_util.h20
18 files changed, 0 insertions, 1470 deletions
diff --git a/keyboards/handwired/xeal60/config.h b/keyboards/handwired/xeal60/config.h
deleted file mode 100644
index c910d8f24..000000000
--- a/keyboards/handwired/xeal60/config.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2015 Jack Humbert
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
19#ifndef CONFIG_H
20#define CONFIG_H
21
22#include "config_common.h"
23
24#endif
diff --git a/keyboards/handwired/xeal60/info.json b/keyboards/handwired/xeal60/info.json
deleted file mode 100644
index aa1c3b8ef..000000000
--- a/keyboards/handwired/xeal60/info.json
+++ /dev/null
@@ -1,12 +0,0 @@
1{
2 "keyboard_name": "Let's Split",
3 "url": "",
4 "maintainer": "qmk",
5 "width": 13,
6 "height": 4,
7 "layouts": {
8 "LAYOUT": {
9 "layout": [{"x":0, "y":0}, {"x":1, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":7, "y":0}, {"x":8, "y":0}, {"x":9, "y":0}, {"x":10, "y":0}, {"x":11, "y":0}, {"x":12, "y":0}, {"x":0, "y":1}, {"x":1, "y":1}, {"x":2, "y":1}, {"x":3, "y":1}, {"x":4, "y":1}, {"x":5, "y":1}, {"x":7, "y":1}, {"x":8, "y":1}, {"x":9, "y":1}, {"x":10, "y":1}, {"x":11, "y":1}, {"x":12, "y":1}, {"x":0, "y":2}, {"x":1, "y":2}, {"x":2, "y":2}, {"x":3, "y":2}, {"x":4, "y":2}, {"x":5, "y":2}, {"x":7, "y":2}, {"x":8, "y":2}, {"x":9, "y":2}, {"x":10, "y":2}, {"x":11, "y":2}, {"x":12, "y":2}, {"x":0, "y":3}, {"x":1, "y":3}, {"x":2, "y":3}, {"x":3, "y":3}, {"x":4, "y":3}, {"x":5, "y":3}, {"x":7, "y":3}, {"x":8, "y":3}, {"x":9, "y":3}, {"x":10, "y":3}, {"x":11, "y":3}, {"x":12, "y":3}]
10 }
11 }
12}
diff --git a/keyboards/handwired/xeal60/keymaps/default/config.h b/keyboards/handwired/xeal60/keymaps/default/config.h
deleted file mode 100644
index 5a6261c4f..000000000
--- a/keyboards/handwired/xeal60/keymaps/default/config.h
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2This is the c configuration file for the keymap
3
4Copyright 2012 Jun Wako <wakojun@gmail.com>
5Copyright 2015 Jack Humbert
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#ifndef CONFIG_USER_H
22#define CONFIG_USER_H
23
24#include "../../config.h"
25
26/* Use I2C or Serial, not both */
27
28#define USE_SERIAL
29// #define USE_I2C
30
31/* Select hand configuration */
32
33#define MASTER_LEFT
34// #define MASTER_RIGHT
35// #define EE_HANDS
36
37#endif
diff --git a/keyboards/handwired/xeal60/keymaps/default/keymap.c b/keyboards/handwired/xeal60/keymaps/default/keymap.c
deleted file mode 100644
index d770d0c6a..000000000
--- a/keyboards/handwired/xeal60/keymaps/default/keymap.c
+++ /dev/null
@@ -1,129 +0,0 @@
1#include QMK_KEYBOARD_H
2
3extern keymap_config_t keymap_config;
4
5// Each layer gets a name for readability, which is then used in the keymap matrix below.
6// The underscores don't mean anything - you can have a layer called STUFF or any other name.
7// Layer names don't all need to be of the same length, obviously, and you can also skip them
8// entirely and just use numbers.
9#define _QWERTY 0
10#define _NUMPAD 1
11#define _RAISE 4
12
13enum custom_keycodes {
14 QWERTY = SAFE_RANGE,
15 NUMPAD,
16 RAISE
17};
18
19// Fillers to make layering more clear
20#define _______ KC_TRNS
21#define XXXXXXX KC_NO
22
23const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
24/*
25 * ,-----------------------------------------------------------.
26 * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
27 * |-----------------------------------------------------------|
28 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ |
29 * |-----------------------------------------------------------|
30 * |FN | A| S| D| F| G| H| J| K| L| ;| '|Return |
31 * |-----------------------------------------------------------|
32 * |Shift | Z| X| C| V| B| N| M| ,| .| /| Shift |
33 * |-----------------------------------------------------------|
34 * |Ctrl|Gui |Alt | NUM | Space | Space |Alt |FN |Menu |Ctrl |
35 * `-----------------------------------------------------------'
36 */
37 /* Layer 0: Qwerty */
38 [_QWERTY] = LAYOUT_split60( \
39 KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
40 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
41 RAISE, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
42 KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
43 KC_LCTL, KC_LGUI, KC_LALT, NUMPAD, KC_SPC, KC_SPC, KC_RALT, RAISE, KC_MENU, KC_RCTL \
44 ),
45
46/*
47 * ,-----------------------------------------------------------.
48 * | | | | | | | | | /| *| -| | | |
49 * |-----------------------------------------------------------|
50 * | | | | | | | | 7| 8| 9| +| | | |
51 * |-----------------------------------------------------------|
52 * | | | | | | | | 4| 5| 6|Bspc| |Return |
53 * |-----------------------------------------------------------|
54 * | | | | | | | | 1| 2| 3| .| |
55 * |-----------------------------------------------------------|
56 * | | | | QWE | | 0 | . | | | |
57 * `-----------------------------------------------------------'
58 */
59
60 /* Layer 1: Numpad */
61 [_NUMPAD] = LAYOUT_split60( \
62 _______, _______, _______, _______, _______, _______, _______, _______, KC_PSLS, KC_PAST, KC_MINUS, _______, _______, KC_BSPC, \
63 _______, _______, _______, _______, _______, _______, _______, KC_7, KC_8, KC_9, KC_PLUS, _______, _______, KC_BSLS, \
64 _______, _______, _______, _______, _______, _______, _______, KC_4, KC_5, KC_6, KC_BSPC, _______, _______, \
65 _______, _______, _______, _______, _______, _______, _______, KC_1, KC_2, KC_3, KC_DOT, _______, \
66 _______, _______, _______, QWERTY, KC_SPC, KC_0, KC_DOT, RAISE, _______, _______ \
67 ),
68
69/*
70 * ,-----------------------------------------------------------.
71 * | | | | | | | | | | | | | | |
72 * |-----------------------------------------------------------|
73 * | | | ^ | | | | |pUp| ^ |pDn| | | | |
74 * |-----------------------------------------------------------|
75 * | | < | v | > | | |Hom| < | v | > | | | |
76 * |-----------------------------------------------------------|
77 * | | | | | | |End| | | | | |
78 * |-----------------------------------------------------------|
79 * | | | | | | | | | | |
80 * `-----------------------------------------------------------'
81 */
82
83 /* Layer 2: RAISE */
84 [_RAISE] = LAYOUT_split60( \
85 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
86 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
87 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
88 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
89 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
90 )
91
92};
93
94#ifdef AUDIO_ENABLE
95float tone_qwerty[][2] = SONG(QWERTY_SOUND);
96float tone_numpad[][2] = SONG(DVORAK_SOUND);
97#endif
98
99bool process_record_user(uint16_t keycode, keyrecord_t *record) {
100 switch (keycode) {
101 case QWERTY:
102 if (record->event.pressed) {
103 #ifdef AUDIO_ENABLE
104 PLAY_SONG(tone_qwerty);
105 #endif
106 default_layer_set(1UL<<_QWERTY);
107 }
108 return false;
109 break;
110 case NUMPAD:
111 if (record->event.pressed) {
112 #ifdef AUDIO_ENABLE
113 PLAY_SONG(tone_numpad);
114 #endif
115 default_layer_set(1UL<<_NUMPAD);
116 }
117 return false;
118 break;
119 case RAISE:
120 if (record->event.pressed) {
121 layer_on(_RAISE);
122 } else {
123 layer_off(_RAISE);
124 }
125 return false;
126 break;
127 }
128 return true;
129}
diff --git a/keyboards/handwired/xeal60/keymaps/default/rules.mk b/keyboards/handwired/xeal60/keymaps/default/rules.mk
deleted file mode 100644
index 457a3d01d..000000000
--- a/keyboards/handwired/xeal60/keymaps/default/rules.mk
+++ /dev/null
@@ -1,3 +0,0 @@
1ifndef QUANTUM_DIR
2 include ../../../../Makefile
3endif
diff --git a/keyboards/handwired/xeal60/lets_split.c b/keyboards/handwired/xeal60/lets_split.c
deleted file mode 100644
index 3caa114c2..000000000
--- a/keyboards/handwired/xeal60/lets_split.c
+++ /dev/null
@@ -1 +0,0 @@
1#include "lets_split.h"
diff --git a/keyboards/handwired/xeal60/lets_split.h b/keyboards/handwired/xeal60/lets_split.h
deleted file mode 100644
index 0442982fa..000000000
--- a/keyboards/handwired/xeal60/lets_split.h
+++ /dev/null
@@ -1,28 +0,0 @@
1#ifndef LETS_SPLIT_H
2#define LETS_SPLIT_H
3
4#include "quantum.h"
5
6#ifdef KEYBOARD_lets_split_rev1
7 #include "rev1.h"
8#endif
9
10
11// Used to create a keymap using only KC_ prefixed keys
12#define LAYOUT_kc( \
13 L00, L01, L02, L03, L04, L05, L06, L07, R00, R01, R02, R03, R04, R05, R06, R07, \
14 L10, L11, L12, L13, L14, L15, L16, L17, R10, R11, R12, R13, R14, R15, R16, R17, \
15 L20, L21, L22, L23, L24, L25, L26, L27, R20, R21, R22, R23, R24, R25, R26, R27, \
16 L30, L31, L32, L33, L34, L35, L36, L37, R30, R31, R32, R33, R34, R35, R36, R37, \
17 L40, L41, L42, L43, L44, L45, L46, L47, R40, R41, R42, R43, R44, R45, R46, R47 \
18 ) \
19 LAYOUT( \
20 KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##L06, KC_##L07, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, KC_##R06, KC_##R07,\
21 KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##L16, KC_##L17, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, KC_##R16, KC_##R17,\
22 KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##L26, KC_##L27, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, KC_##R26, KC_##R27,\
23 KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##L34, KC_##L35, KC_##L36, KC_##L37, KC_##R30, KC_##R31, KC_##R32, KC_##R33, KC_##R34, KC_##R35, KC_##R36, KC_##R37 \
24 )
25
26#define LAYOUT_XEAL LAYOUT_kc
27
28#endif
diff --git a/keyboards/handwired/xeal60/matrix.c b/keyboards/handwired/xeal60/matrix.c
deleted file mode 100644
index f753d234a..000000000
--- a/keyboards/handwired/xeal60/matrix.c
+++ /dev/null
@@ -1,470 +0,0 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.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/*
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 USE_I2C
35# include "i2c.h"
36#else // USE_SERIAL
37# include "serial.h"
38#endif
39
40#ifndef DEBOUNCING_DELAY
41# define DEBOUNCING_DELAY 5
42#endif
43
44#if (DEBOUNCING_DELAY > 0)
45 static uint16_t debouncing_time;
46 static bool debouncing = false;
47#endif
48
49#if (MATRIX_COLS <= 8)
50# define print_matrix_header() print("\nr/c 01234567\n")
51# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
52# define matrix_bitpop(i) bitpop(matrix[i])
53# define ROW_SHIFTER ((uint8_t)1)
54#else
55# error "Currently only supports 8 COLS"
56#endif
57static matrix_row_t matrix_debouncing[MATRIX_ROWS];
58
59#define ERROR_DISCONNECT_COUNT 5
60
61#define ROWS_PER_HAND (MATRIX_ROWS/2)
62
63static uint8_t error_count = 0;
64
65static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
66static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
67
68/* matrix state(1:on, 0:off) */
69static matrix_row_t matrix[MATRIX_ROWS];
70static matrix_row_t matrix_debouncing[MATRIX_ROWS];
71
72#if (DIODE_DIRECTION == COL2ROW)
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 void init_rows(void);
80 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
81 static void unselect_cols(void);
82 static void unselect_col(uint8_t col);
83 static void select_col(uint8_t col);
84#endif
85
86__attribute__ ((weak))
87void matrix_init_kb(void) {
88 matrix_init_user();
89}
90
91__attribute__ ((weak))
92void matrix_scan_kb(void) {
93 matrix_scan_user();
94}
95
96__attribute__ ((weak))
97void matrix_init_user(void) {
98}
99
100__attribute__ ((weak))
101void matrix_scan_user(void) {
102}
103
104__attribute__ ((weak))
105void matrix_slave_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#ifdef DISABLE_JTAG
123 // JTAG disable for PORT F. write JTD bit twice within four cycles.
124 MCUCR |= (1<<JTD);
125 MCUCR |= (1<<JTD);
126#endif
127
128 debug_enable = true;
129 debug_matrix = true;
130 debug_mouse = true;
131 // initialize row and col
132#if (DIODE_DIRECTION == COL2ROW)
133 unselect_rows();
134 init_cols();
135#elif (DIODE_DIRECTION == ROW2COL)
136 unselect_cols();
137 init_rows();
138#endif
139
140 TX_RX_LED_INIT;
141
142 // initialize matrix state: all keys off
143 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
144 matrix[i] = 0;
145 matrix_debouncing[i] = 0;
146 }
147
148 matrix_init_quantum();
149
150}
151
152uint8_t _matrix_scan(void)
153{
154 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
155#if (DIODE_DIRECTION == COL2ROW)
156 // Set row, read cols
157 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
158# if (DEBOUNCING_DELAY > 0)
159 bool matrix_changed = read_cols_on_row(matrix_debouncing+offset, current_row);
160
161 if (matrix_changed) {
162 debouncing = true;
163 debouncing_time = timer_read();
164 }
165
166# else
167 read_cols_on_row(matrix+offset, current_row);
168# endif
169
170 }
171
172#elif (DIODE_DIRECTION == ROW2COL)
173 // Set col, read rows
174 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
175# if (DEBOUNCING_DELAY > 0)
176 bool matrix_changed = read_rows_on_col(matrix_debouncing+offset, current_col);
177 if (matrix_changed) {
178 debouncing = true;
179 debouncing_time = timer_read();
180 }
181# else
182 read_rows_on_col(matrix+offset, current_col);
183# endif
184
185 }
186#endif
187
188# if (DEBOUNCING_DELAY > 0)
189 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
190 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
191 matrix[i+offset] = matrix_debouncing[i+offset];
192 }
193 debouncing = false;
194 }
195# endif
196
197 return 1;
198}
199
200#ifdef USE_I2C
201
202// Get rows from other half over i2c
203int i2c_transaction(void) {
204 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
205
206 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
207 if (err) goto i2c_error;
208
209 // start of matrix stored at 0x00
210 err = i2c_master_write(0x00);
211 if (err) goto i2c_error;
212
213 // Start read
214 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
215 if (err) goto i2c_error;
216
217 if (!err) {
218 int i;
219 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
220 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
221 }
222 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
223 i2c_master_stop();
224 } else {
225i2c_error: // the cable is disconnceted, or something else went wrong
226 i2c_reset_state();
227 return err;
228 }
229
230 return 0;
231}
232
233#else // USE_SERIAL
234
235int serial_transaction(void) {
236 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
237
238 if (serial_update_buffers()) {
239 return 1;
240 }
241
242 for (int i = 0; i < ROWS_PER_HAND; ++i) {
243 matrix[slaveOffset+i] = serial_slave_buffer[i];
244 }
245 return 0;
246}
247#endif
248
249uint8_t matrix_scan(void)
250{
251 uint8_t ret = _matrix_scan();
252
253#ifdef USE_I2C
254 if( i2c_transaction() ) {
255#else // USE_SERIAL
256 if( serial_transaction() ) {
257#endif
258 // turn on the indicator led when halves are disconnected
259 TXLED1;
260
261 error_count++;
262
263 if (error_count > ERROR_DISCONNECT_COUNT) {
264 // reset other half if disconnected
265 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
266 for (int i = 0; i < ROWS_PER_HAND; ++i) {
267 matrix[slaveOffset+i] = 0;
268 }
269 }
270 } else {
271 // turn off the indicator led on no error
272 TXLED0;
273 error_count = 0;
274 }
275 matrix_scan_quantum();
276 return ret;
277}
278
279void matrix_slave_scan(void) {
280 _matrix_scan();
281
282 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
283
284#ifdef USE_I2C
285 for (int i = 0; i < ROWS_PER_HAND; ++i) {
286 i2c_slave_buffer[i] = matrix[offset+i];
287 }
288#else // USE_SERIAL
289 for (int i = 0; i < ROWS_PER_HAND; ++i) {
290 serial_slave_buffer[i] = matrix[offset+i];
291 }
292#endif
293 matrix_slave_scan_user();
294}
295
296bool matrix_is_modified(void)
297{
298 if (debouncing) return false;
299 return true;
300}
301
302inline
303bool matrix_is_on(uint8_t row, uint8_t col)
304{
305 return (matrix[row] & ((matrix_row_t)1<<col));
306}
307
308inline
309matrix_row_t matrix_get_row(uint8_t row)
310{
311 return matrix[row];
312}
313
314void matrix_print(void)
315{
316 print("\nr/c 0123456789ABCDEF\n");
317 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
318 phex(row); print(": ");
319 pbin_reverse16(matrix_get_row(row));
320 print("\n");
321 }
322}
323
324uint8_t matrix_key_count(void)
325{
326 uint8_t count = 0;
327 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
328 count += bitpop16(matrix[i]);
329 }
330 return count;
331}
332
333#if (DIODE_DIRECTION == COL2ROW)
334
335static void init_cols(void)
336{
337 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
338 uint8_t pin = col_pins[x];
339 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
340 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
341 }
342}
343
344static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
345{
346 // Store last value of row prior to reading
347 matrix_row_t last_row_value = current_matrix[current_row];
348
349 // Clear data in matrix row
350 current_matrix[current_row] = 0;
351
352 // Select row and wait for row selecton to stabilize
353 select_row(current_row);
354 wait_us(30);
355
356 // For each col...
357 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
358
359 // Select the col pin to read (active low)
360 uint8_t pin = col_pins[col_index];
361 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
362
363 // Populate the matrix row with the state of the col pin
364 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
365 }
366
367 // Unselect row
368 unselect_row(current_row);
369
370 return (last_row_value != current_matrix[current_row]);
371}
372
373static void select_row(uint8_t row)
374{
375 uint8_t pin = row_pins[row];
376 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
377 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
378}
379
380static void unselect_row(uint8_t row)
381{
382 uint8_t pin = row_pins[row];
383 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
384 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
385}
386
387static void unselect_rows(void)
388{
389 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
390 uint8_t pin = row_pins[x];
391 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
392 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
393 }
394}
395
396#elif (DIODE_DIRECTION == ROW2COL)
397
398static void init_rows(void)
399{
400 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
401 uint8_t pin = row_pins[x];
402 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
403 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
404 }
405}
406
407static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
408{
409 bool matrix_changed = false;
410
411 // Select col and wait for col selecton to stabilize
412 select_col(current_col);
413 wait_us(30);
414
415 // For each row...
416 for(uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++)
417 {
418
419 // Store last value of row prior to reading
420 matrix_row_t last_row_value = current_matrix[row_index];
421
422 // Check row pin state
423 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
424 {
425 // Pin LO, set col bit
426 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
427 }
428 else
429 {
430 // Pin HI, clear col bit
431 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
432 }
433
434 // Determine if the matrix changed state
435 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
436 {
437 matrix_changed = true;
438 }
439 }
440
441 // Unselect col
442 unselect_col(current_col);
443
444 return matrix_changed;
445}
446
447static void select_col(uint8_t col)
448{
449 uint8_t pin = col_pins[col];
450 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
451 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
452}
453
454static void unselect_col(uint8_t col)
455{
456 uint8_t pin = col_pins[col];
457 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
458 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
459}
460
461static void unselect_cols(void)
462{
463 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
464 uint8_t pin = col_pins[x];
465 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
466 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
467 }
468}
469
470#endif
diff --git a/keyboards/handwired/xeal60/readme.md b/keyboards/handwired/xeal60/readme.md
deleted file mode 100644
index 80fe08b93..000000000
--- a/keyboards/handwired/xeal60/readme.md
+++ /dev/null
@@ -1,187 +0,0 @@
1Let's Split
2======
3
4This readme and most of the code are from https://github.com/ahtn/tmk_keyboard/
5
6Split keyboard firmware for Arduino Pro Micro or other ATmega32u4
7based boards.
8
9**Hardware files for the Let's Split are now stored at http://qmk.fm/lets_split/**
10**Hardware files for the sockets version can be found at https://github.com/dumle29/let-s-Split-v2/tree/socket-reverseable**
11
12## Build Guide
13
14A build guide for putting together the Let's Split v2 can be found here: [An Overly Verbose Guide to Building a Let's Split Keyboard](https://github.com/nicinabox/lets-split-guide)
15
16There is additional information there about flashing and adding RGB underglow.
17
18A build guide for putting together the sockets version can be found here: *Guide will be made and linked here when the PCBs have been received and tested*
19
20## First Time Setup
21
22Download or clone the `qmk_firmware` repo and navigate to its top level directory. Once your build environment is setup, you'll be able to generate the default .hex using:
23
24```
25$ make lets_split/rev2:default
26```
27
28You will see a lot of output and if everything worked correctly you will see the built hex file:
29
30```
31lets_split_rev2_default.hex
32```
33
34If you would like to use one of the alternative keymaps, or create your own, copy one of the existing [keymaps](keymaps/) and run make like so:
35
36
37```
38$ make lets_split/rev2:YOUR_KEYMAP_NAME
39```
40
41If everything worked correctly you will see a file:
42
43```
44lets_split_rev2_YOUR_KEYMAP_NAME.hex
45```
46
47For more information on customizing keymaps, take a look at the primary documentation for [Customizing Your Keymap](/docs/faq_keymap.md) in the main readme.md.
48
49### Let's split 1.0
50If you have a first generation Let's Split you will need to use the revision 1 code. To do so, use `rev1` in all your commands instead.
51
52Features
53--------
54
55For the full Quantum Mechanical Keyboard feature list, see [the parent readme.md](/readme.md).
56
57Some features supported by the firmware:
58
59* Either half can connect to the computer via USB, or both halves can be used
60 independently.
61* You only need 3 wires to connect the two halves. Two for VCC and GND and one
62 for serial communication.
63* Optional support for I2C connection between the two halves if for some
64 reason you require a faster connection between the two halves. Note this
65 requires an extra wire between halves and pull-up resistors on the data lines.
66
67Required Hardware
68-----------------
69
70Apart from diodes and key switches for the keyboard matrix in each half, you
71will need:
72
73* 2 Arduino Pro Micros. You can find these on AliExpress for ≈3.50USD each.
74* 2 TRRS sockets and 1 TRRS cable, or 2 TRS sockets and 1 TRS cable
75
76Alternatively, you can use any sort of cable and socket that has at least 3
77wires. If you want to use I2C to communicate between halves, you will need a
78cable with at least 4 wires and 2x 4.7kΩ pull-up resistors
79
80Optional Hardware
81-----------------
82
83A speaker can be hooked-up to either side to the `5` (`C6`) pin and `GND`, and turned on via `AUDIO_ENABLE`.
84
85Wiring
86------
87
88The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and digital pin 3 (i.e.
89PD0 on the ATmega32u4) between the two Pro Micros.
90
91Next, wire your key matrix to any of the remaining 17 IO pins of the pro micro
92and modify the `matrix.c` accordingly.
93
94The wiring for serial:
95
96![serial wiring](https://i.imgur.com/C3D1GAQ.png)
97
98The wiring for i2c:
99
100![i2c wiring](https://i.imgur.com/Hbzhc6E.png)
101
102The pull-up resistors may be placed on either half. It is also possible
103to use 4 resistors and have the pull-ups in both halves, but this is
104unnecessary in simple use cases.
105
106You can change your configuration between serial and i2c by modifying your `config.h` file.
107
108Notes on Software Configuration
109-------------------------------
110
111Configuring the firmware is similar to any other QMK project. One thing
112to note is that `MATRIX_ROWS` in `config.h` is the total number of rows between
113the two halves, i.e. if your split keyboard has 4 rows in each half, then use
114`MATRIX_ROWS=8`.
115
116Also, the current implementation assumes a maximum of 8 columns, but it would
117not be very difficult to adapt it to support more if required.
118
119Flashing
120-------
121From the top level `qmk_firmware` directory run `make KEYBOARD:KEYMAP:avrdude` for automatic serial port resolution and flashing.
122Example: `make lets_split/rev2:default:avrdude`
123
124
125Choosing which board to plug the USB cable into (choosing Master)
126--------
127Because the two boards are identical, the firmware has logic to differentiate the left and right board.
128
129It uses two strategies to figure things out: looking at the EEPROM (memory on the chip) or looking if the current board has the usb cable.
130
131The EEPROM approach requires additional setup (flashing the eeprom) but allows you to swap the usb cable to either side.
132
133The USB cable approach is easier to setup and if you just want the usb cable on the left board, you do not need to do anything extra.
134
135### Setting the left hand as master
136If you always plug the usb cable into the left board, nothing extra is needed as this is the default. Comment out `EE_HANDS` and comment out `I2C_MASTER_RIGHT` or `MASTER_RIGHT` if for some reason it was set.
137
138### Setting the right hand as master
139If you always plug the usb cable into the right board, add an extra flag to your `config.h`
140```
141 #define MASTER_RIGHT
142```
143
144### Setting EE_hands to use either hands as master
145If you define `EE_HANDS` in your `config.h`, you will need to set the
146EEPROM for the left and right halves.
147
148The EEPROM is used to store whether the
149half is left handed or right handed. This makes it so that the same firmware
150file will run on both hands instead of having to flash left and right handed
151versions of the firmware to each half. To flash the EEPROM file for the left
152half run:
153```
154avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-lefthand.eep
155// or the equivalent in dfu-programmer
156
157```
158and similarly for right half
159```
160avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-righhand.eep
161// or the equivalent in dfu-programmer
162```
163
164NOTE: replace `$(COM_PORT)` with the port of your device (e.g. `/dev/ttyACM0`)
165
166After you have flashed the EEPROM, you then need to set `EE_HANDS` in your config.h, rebuild the hex files and reflash.
167
168Note that you need to program both halves, but you have the option of using
169different keymaps for each half. You could program the left half with a QWERTY
170layout and the right half with a Colemak layout using bootmagic's default layout option.
171Then if you connect the left half to a computer by USB the keyboard will use QWERTY and Colemak when the
172right half is connected.
173
174
175Notes on Using Pro Micro 3.3V
176-----------------------------
177
178Do update the `F_CPU` parameter in `rules.mk` to `8000000` which reflects
179the frequency on the 3.3V board.
180
181Also, if the slave board is producing weird characters in certain columns,
182update the following line in `matrix.c` to the following:
183
184```
185// _delay_us(30); // without this wait read unstable value.
186_delay_us(300); // without this wait read unstable value.
187```
diff --git a/keyboards/handwired/xeal60/rev1/config.h b/keyboards/handwired/xeal60/rev1/config.h
deleted file mode 100644
index 504b3fe8c..000000000
--- a/keyboards/handwired/xeal60/rev1/config.h
+++ /dev/null
@@ -1,93 +0,0 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2015 Jack Humbert
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
19#ifndef REV1_CONFIG_H
20#define REV1_CONFIG_H
21
22#include "config_common.h"
23
24/* USB Device descriptor parameter */
25#define VENDOR_ID 0x4131
26#define PRODUCT_ID 0x5141
27#define DEVICE_VER 0x0001
28#define MANUFACTURER XeaLouS
29#define PRODUCT XeaL60
30#define DESCRIPTION A split keyboard
31
32/* key matrix size */
33// Rows are doubled-up
34#define MATRIX_ROWS 10
35#define MATRIX_COLS 8
36
37// wiring of each half
38//ascii art of pro micro
39// PORT
40//PD3 TX0 RAW
41//PD2 RX1 GND
42// GND RESET
43// GND VCC
44//PD1 2 A3 PF4
45//PD0 3 A2 PF5
46//PD4 4 A1 PF6
47//PC6 5 A0 PF7
48//PD7 6 15 PB1
49//PE6 7 14 PB3
50//PB4 8 13 PB2
51//PB5 9 10 PB6
52
53#define MATRIX_ROW_PINS { B5, B4, E6, D7, C6 }
54#define MATRIX_COL_PINS { B6, B2, B3, B1, F7, F6, F5 }
55
56/* define if matrix has ghost */
57//#define MATRIX_HAS_GHOST
58
59/* number of backlight levels */
60// #define BACKLIGHT_LEVELS 3
61
62/* Set 0 if debouncing isn't needed */
63#define DEBOUNCING_DELAY 5
64
65/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
66#define LOCKING_SUPPORT_ENABLE
67/* Locking resynchronize hack */
68#define LOCKING_RESYNC_ENABLE
69
70/* key combination for command */
71#define IS_COMMAND() ( \
72 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
73)
74
75/*
76 * Feature disable options
77 * These options are also useful to firmware size reduction.
78 */
79
80/* disable debug print */
81// #define NO_DEBUG
82
83/* disable print */
84// #define NO_PRINT
85
86/* disable action features */
87//#define NO_ACTION_LAYER
88//#define NO_ACTION_TAPPING
89//#define NO_ACTION_ONESHOT
90//#define NO_ACTION_MACRO
91//#define NO_ACTION_FUNCTION
92
93#endif
diff --git a/keyboards/handwired/xeal60/rev1/rev1.c b/keyboards/handwired/xeal60/rev1/rev1.c
deleted file mode 100644
index c243f71bc..000000000
--- a/keyboards/handwired/xeal60/rev1/rev1.c
+++ /dev/null
@@ -1,15 +0,0 @@
1#include "lets_split.h"
2
3void matrix_init_kb(void) {
4
5 // // green led on
6 // DDRD |= (1<<5);
7 // PORTD &= ~(1<<5);
8
9 // // orange led on
10 // DDRB |= (1<<0);
11 // PORTB &= ~(1<<0);
12
13 matrix_init_user();
14};
15
diff --git a/keyboards/handwired/xeal60/rev1/rev1.h b/keyboards/handwired/xeal60/rev1/rev1.h
deleted file mode 100644
index 8f25d7d2f..000000000
--- a/keyboards/handwired/xeal60/rev1/rev1.h
+++ /dev/null
@@ -1,33 +0,0 @@
1#ifndef REV1_H
2#define REV1_H
3
4#include "lets_split.h"
5
6//void promicro_bootloader_jmp(bool program);
7#include "quantum.h"
8
9//void promicro_bootloader_jmp(bool program);
10
11#define LAYOUT( \
12 L00, L01, L02, L03, L04, L05, L06, R00, R01, R02, R03, R04, R05, R06, \
13 L10, L11, L12, L13, L14, L15, L16, L17, R11, R12, R13, R14, R15, R16, \
14 L20, L21, L22, L23, L24, L25, L26, R21, R22, R23, R24, R25, R26, \
15 L30, L31, L32, L33, L34, L35, R31, R32, R33, R34, R35, R36, \
16 L40, L41, L42, L43, L44, R42, R43, R44, R45, R46 \
17 ) \
18 { \
19 { L00, L01, L02, L03, L04, L05, L06 }, \
20 { L10, L11, L12, L13, L14, L15, L16, L17 }, \
21 { L20, L21, L22, L23, L24, L25, L26 }, \
22 { L30, L31, L32, L33, L34, L35 }, \
23 { L40, L41, L42, L43, L44 }, \
24 { R00, R01, R02, R03, R04, R05, R06}, \
25 { R11, R12, R13, R14, R15, R16 }, \
26 { R21, R22, R23, R24, R25, R26 }, \
27 { R31, R32, R33, R34, R35, R36 }, \
28 { R42, R43, R44, R45, R46 } \
29 }
30
31#define LAYOUT_split60 LAYOUT
32
33#endif
diff --git a/keyboards/handwired/xeal60/rev1/rules.mk b/keyboards/handwired/xeal60/rev1/rules.mk
deleted file mode 100644
index f84561674..000000000
--- a/keyboards/handwired/xeal60/rev1/rules.mk
+++ /dev/null
@@ -1 +0,0 @@
1BACKLIGHT_ENABLE = no \ No newline at end of file
diff --git a/keyboards/handwired/xeal60/rules.mk b/keyboards/handwired/xeal60/rules.mk
deleted file mode 100644
index 6dde257ec..000000000
--- a/keyboards/handwired/xeal60/rules.mk
+++ /dev/null
@@ -1,77 +0,0 @@
1SRC += matrix.c \
2 split_util.c \
3 serial.c \
4 ssd1306.c
5
6# MCU name
7#MCU = at90usb1287
8MCU = atmega32u4
9
10# Processor frequency.
11# This will define a symbol, F_CPU, in all source code files equal to the
12# processor frequency in Hz. You can then use this symbol in your source code to
13# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
14# automatically to create a 32-bit value in your source code.
15#
16# This will be an integer division of F_USB below, as it is sourced by
17# F_USB after it has run through any CPU prescalers. Note that this value
18# does not *change* the processor frequency - it should merely be updated to
19# reflect the processor speed set externally so that the code can use accurate
20# software delays.
21F_CPU = 16000000
22
23#
24# LUFA specific
25#
26# Target architecture (see library "Board Types" documentation).
27ARCH = AVR8
28
29# Input clock frequency.
30# This will define a symbol, F_USB, in all source code files equal to the
31# input clock frequency (before any prescaling is performed) in Hz. This value may
32# differ from F_CPU if prescaling is used on the latter, and is required as the
33# raw input clock is fed directly to the PLL sections of the AVR for high speed
34# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
35# at the end, this will be done automatically to create a 32-bit value in your
36# source code.
37#
38# If no clock division is performed on the input clock inside the AVR (via the
39# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
40F_USB = $(F_CPU)
41
42# Bootloader
43# This definition is optional, and if your keyboard supports multiple bootloaders of
44# different sizes, comment this out, and the correct address will be loaded
45# automatically (+60). See bootloader.mk for all options.
46BOOTLOADER = caterina
47
48# Interrupt driven control endpoint task(+60)
49OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
50
51# Build Options
52# change to "no" to disable the options, or define them in the Makefile in
53# the appropriate keymap folder that will get included automatically
54#
55BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
56MOUSEKEY_ENABLE = no # Mouse keys(+4700)
57EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
58CONSOLE_ENABLE = no # Console for debug(+400)
59COMMAND_ENABLE = yes # Commands for debug and configuration
60NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
61BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
62MIDI_ENABLE = no # MIDI controls
63AUDIO_ENABLE = no # Audio output on port C6
64UNICODE_ENABLE = no # Unicode
65BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
66RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
67SUBPROJECT_rev1 = yes
68USE_I2C = no
69
70# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
71SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
72
73CUSTOM_MATRIX = yes
74
75LAYOUTS = ortho_4x12
76
77DEFAULT_FOLDER = lets_split/rev2
diff --git a/keyboards/handwired/xeal60/serial.c b/keyboards/handwired/xeal60/serial.c
deleted file mode 100644
index 74bcbb6bf..000000000
--- a/keyboards/handwired/xeal60/serial.c
+++ /dev/null
@@ -1,228 +0,0 @@
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 // Enable INT0
68 EIMSK |= _BV(INT0);
69 // Trigger on falling edge of INT0
70 EICRA &= ~(_BV(ISC00) | _BV(ISC01));
71}
72
73// Used by the master to synchronize timing with the slave.
74static
75void sync_recv(void) {
76 serial_input();
77 // This shouldn't hang if the slave disconnects because the
78 // serial line will float to high if the slave does disconnect.
79 while (!serial_read_pin());
80 serial_delay();
81}
82
83// Used by the slave to send a synchronization signal to the master.
84static
85void sync_send(void) {
86 serial_output();
87
88 serial_low();
89 serial_delay();
90
91 serial_high();
92}
93
94// Reads a byte from the serial line
95static
96uint8_t serial_read_byte(void) {
97 uint8_t byte = 0;
98 serial_input();
99 for ( uint8_t i = 0; i < 8; ++i) {
100 byte = (byte << 1) | serial_read_pin();
101 serial_delay();
102 _delay_us(1);
103 }
104
105 return byte;
106}
107
108// Sends a byte with MSB ordering
109static
110void serial_write_byte(uint8_t data) {
111 uint8_t b = 8;
112 serial_output();
113 while( b-- ) {
114 if(data & (1 << b)) {
115 serial_high();
116 } else {
117 serial_low();
118 }
119 serial_delay();
120 }
121}
122
123// interrupt handle to be used by the slave device
124ISR(SERIAL_PIN_INTERRUPT) {
125 sync_send();
126
127 uint8_t checksum = 0;
128 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
129 serial_write_byte(serial_slave_buffer[i]);
130 sync_send();
131 checksum += serial_slave_buffer[i];
132 }
133 serial_write_byte(checksum);
134 sync_send();
135
136 // wait for the sync to finish sending
137 serial_delay();
138
139 // read the middle of pulses
140 _delay_us(SERIAL_DELAY/2);
141
142 uint8_t checksum_computed = 0;
143 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
144 serial_master_buffer[i] = serial_read_byte();
145 sync_send();
146 checksum_computed += serial_master_buffer[i];
147 }
148 uint8_t checksum_received = serial_read_byte();
149 sync_send();
150
151 serial_input(); // end transaction
152
153 if ( checksum_computed != checksum_received ) {
154 status |= SLAVE_DATA_CORRUPT;
155 } else {
156 status &= ~SLAVE_DATA_CORRUPT;
157 }
158}
159
160inline
161bool serial_slave_DATA_CORRUPT(void) {
162 return status & SLAVE_DATA_CORRUPT;
163}
164
165// Copies the serial_slave_buffer to the master and sends the
166// serial_master_buffer to the slave.
167//
168// Returns:
169// 0 => no error
170// 1 => slave did not respond
171int serial_update_buffers(void) {
172 // this code is very time dependent, so we need to disable interrupts
173 cli();
174
175 // signal to the slave that we want to start a transaction
176 serial_output();
177 serial_low();
178 _delay_us(1);
179
180 // wait for the slaves response
181 serial_input();
182 serial_high();
183 _delay_us(SERIAL_DELAY);
184
185 // check if the slave is present
186 if (serial_read_pin()) {
187 // slave failed to pull the line low, assume not present
188 sei();
189 return 1;
190 }
191
192 // if the slave is present syncronize with it
193 sync_recv();
194
195 uint8_t checksum_computed = 0;
196 // receive data from the slave
197 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
198 serial_slave_buffer[i] = serial_read_byte();
199 sync_recv();
200 checksum_computed += serial_slave_buffer[i];
201 }
202 uint8_t checksum_received = serial_read_byte();
203 sync_recv();
204
205 if (checksum_computed != checksum_received) {
206 sei();
207 return 1;
208 }
209
210 uint8_t checksum = 0;
211 // send data to the slave
212 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
213 serial_write_byte(serial_master_buffer[i]);
214 sync_recv();
215 checksum += serial_master_buffer[i];
216 }
217 serial_write_byte(checksum);
218 sync_recv();
219
220 // always, release the line when not in use
221 serial_output();
222 serial_high();
223
224 sei();
225 return 0;
226}
227
228#endif
diff --git a/keyboards/handwired/xeal60/serial.h b/keyboards/handwired/xeal60/serial.h
deleted file mode 100644
index 15fe4db7b..000000000
--- a/keyboards/handwired/xeal60/serial.h
+++ /dev/null
@@ -1,26 +0,0 @@
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#define SERIAL_PIN_MASK _BV(PD0)
12#define SERIAL_PIN_INTERRUPT INT0_vect
13
14#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
15#define SERIAL_MASTER_BUFFER_LENGTH 1
16
17// Buffers for master - slave communication
18extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
19extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
20
21void serial_master_init(void);
22void serial_slave_init(void);
23int serial_update_buffers(void);
24bool serial_slave_data_corrupt(void);
25
26#endif
diff --git a/keyboards/handwired/xeal60/split_util.c b/keyboards/handwired/xeal60/split_util.c
deleted file mode 100644
index 346cbc908..000000000
--- a/keyboards/handwired/xeal60/split_util.c
+++ /dev/null
@@ -1,86 +0,0 @@
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#ifdef USE_I2C
14# include "i2c.h"
15#else
16# include "serial.h"
17#endif
18
19volatile bool isLeftHand = true;
20
21static void setup_handedness(void) {
22 #ifdef EE_HANDS
23 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
24 #else
25 // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
26 #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
27 isLeftHand = !has_usb();
28 #else
29 isLeftHand = has_usb();
30 #endif
31 #endif
32}
33
34static void keyboard_master_setup(void) {
35#ifdef USE_I2C
36 i2c_master_init();
37#ifdef SSD1306OLED
38 matrix_master_OLED_init ();
39#endif
40#else
41 serial_master_init();
42#endif
43}
44
45static void keyboard_slave_setup(void) {
46 timer_init();
47#ifdef USE_I2C
48 i2c_slave_init(SLAVE_I2C_ADDRESS);
49#else
50 serial_slave_init();
51#endif
52}
53
54bool has_usb(void) {
55 USBCON |= (1 << OTGPADE); //enables VBUS pad
56 _delay_us(5);
57 return (USBSTA & (1<<VBUS)); //checks state of VBUS
58}
59
60void split_keyboard_setup(void) {
61 setup_handedness();
62
63 if (has_usb()) {
64 keyboard_master_setup();
65 } else {
66 keyboard_slave_setup();
67 }
68 sei();
69}
70
71void keyboard_slave_loop(void) {
72 matrix_init();
73
74 while (1) {
75 matrix_slave_scan();
76 }
77}
78
79// this code runs before the usb and keyboard is initialized
80void matrix_setup(void) {
81 split_keyboard_setup();
82
83 if (!has_usb()) {
84 keyboard_slave_loop();
85 }
86}
diff --git a/keyboards/handwired/xeal60/split_util.h b/keyboards/handwired/xeal60/split_util.h
deleted file mode 100644
index 595a0659e..000000000
--- a/keyboards/handwired/xeal60/split_util.h
+++ /dev/null
@@ -1,20 +0,0 @@
1#ifndef SPLIT_KEYBOARD_UTIL_H
2#define SPLIT_KEYBOARD_UTIL_H
3
4#include <stdbool.h>
5#include "eeconfig.h"
6
7#define SLAVE_I2C_ADDRESS 0x32
8
9extern volatile bool isLeftHand;
10
11// slave version of matix scan, defined in matrix.c
12void matrix_slave_scan(void);
13
14void split_keyboard_setup(void);
15bool has_usb(void);
16void keyboard_slave_loop(void);
17
18void matrix_master_OLED_init (void);
19
20#endif