aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Ong <the.onga@gmail.com>2018-08-29 10:08:07 +1000
committerDrashna Jaelre <drashna@live.com>2018-08-28 17:08:07 -0700
commit9bd6d6112d698ea5823b268983809fe3b8d98b26 (patch)
treea47b90c36bc7c976bd57b5d69bdba0e905bcfd66
parentaf5f59636eea83f66db6510f61510d31ee9dade4 (diff)
downloadqmk_firmware-9bd6d6112d698ea5823b268983809fe3b8d98b26.tar.gz
qmk_firmware-9bd6d6112d698ea5823b268983809fe3b8d98b26.zip
Keyboard: xealous (#3731)
* Keyboard: HandWired/XeaL60 * Updated rules.mk * Mapping for layout was flipped * Figured out how to re-map bad pins. * Updated Keymap * Enabled audio, Forced NKRO * Added QMK_KEYS_PER_SCAN * Removed more unnecessary files, since split_keyboards are in main QMK branch already. * Simplified rules.mk in rev1 * Removed i2c from matrix.c * Re-formatted to 4 spaces per tab, * Changed note for NUMPAD * Added I2C support back! * Fixed keyboard mappings. Both sides work * Moved i2c configuration from keymaps/default/config.h to config.h * Changed SCL_CLOCK to 400000L * Added DEBUG_MATRIX_SCAN_RATE for future optimization efforts * Removed row2col code to clean up matrix.c * Scan rate from 2100 -> 4200 by using Nop instead of waiting 30us between columns. * Further optimized column reading via optimized_col_reader. * Immediate key-recognition * Switched back to own implementation of SPLIT_KEYBOARD. Will optimize so that slave interrupts master. * Moved scanrate debug messages to another file. * Made matrix_scanrate.c compile if CONSOLE_ENABLE is off. Updated to latest i2c.c * Latest i2c uses a few bytes for lighting information * Optimizations in i2c.h to determine buffer size. * Disabled a whole bunch of features. TODO: Test that keyboard still works fine. * Minimum #define NO_ACTION's with still working keyboard * Fixed matrix not working due to offsets not being respected * Added numlock button for keymap. * Use I2C_KEYMAP_START offset * Removed serial, Backlight and RGB support * Removed need for split_flags. * Added audio on and off for numlock. * Renamed from xeal60 to xealous, simplified build system. * Used more shared split_common code. * Updated audio code. * moved tone_qwerty and tone_numpad to config.h. Removed keymaps/default/config.h * Added more shortcut keys in _FN layer. Increased debounce to 6ms due to fencepost error. * DF used with incorrect argument. Custom_keycodes no longer required. * Fixed bug in update_debounce_counters which was resulting in no debouncing! * Removed unnecessary #include
-rw-r--r--keyboards/handwired/xealous/config.h48
-rw-r--r--keyboards/handwired/xealous/info.json91
-rw-r--r--keyboards/handwired/xealous/keymaps/default/keymap.c105
-rw-r--r--keyboards/handwired/xealous/matrix.c376
-rw-r--r--keyboards/handwired/xealous/matrix_scanrate.c39
-rw-r--r--keyboards/handwired/xealous/matrix_scanrate.h4
-rw-r--r--keyboards/handwired/xealous/readme.md166
-rw-r--r--keyboards/handwired/xealous/rev1/config.h90
-rw-r--r--keyboards/handwired/xealous/rev1/rev1.c6
-rw-r--r--keyboards/handwired/xealous/rev1/rev1.h32
-rw-r--r--keyboards/handwired/xealous/rev1/rules.mk0
-rw-r--r--keyboards/handwired/xealous/rules.mk73
12 files changed, 1030 insertions, 0 deletions
diff --git a/keyboards/handwired/xealous/config.h b/keyboards/handwired/xealous/config.h
new file mode 100644
index 000000000..415a0dcf5
--- /dev/null
+++ b/keyboards/handwired/xealous/config.h
@@ -0,0 +1,48 @@
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#pragma once
20#include "config_common.h"
21
22/* Use I2C or Serial, not both */
23
24// #define USE_SERIAL
25#define USE_I2C
26#define SCL_CLOCK 400000UL
27
28/* Select hand configuration */
29
30#define MASTER_LEFT
31// #define MASTER_RIGHT
32// #define EE_HANDS
33
34
35//#define DEBUG_MATRIX_SCAN_RATE //Use this to determine scan-rate.
36#define FORCE_NKRO
37
38#define QMK_KEYS_PER_SCAN 4 //if we press four keys simultaneously, lets process them simultaneously...
39#define DIODE_DIRECTION COL2ROW
40
41#ifdef AUDIO_ENABLE
42 #define C6_AUDIO
43 #define STARTUP_SONG SONG(STARTUP_SOUND)
44 #define NO_MUSIC_MODE
45 #define TONE_QWERTY SONG(Q__NOTE(_E4));
46 #define TONE_NUMPAD SONG(Q__NOTE(_D4));
47#endif
48
diff --git a/keyboards/handwired/xealous/info.json b/keyboards/handwired/xealous/info.json
new file mode 100644
index 000000000..6d7e30f44
--- /dev/null
+++ b/keyboards/handwired/xealous/info.json
@@ -0,0 +1,91 @@
1{
2 "keyboard_name": "Xealous",
3 "url": "",
4 "maintainer": "alex-ong",
5 "width": 15,
6 "height": 5,
7 "layouts": {
8 "LAYOUT_ANSI_DEFAULT": {
9 "key_count": 64,
10 "layout": [
11 {"label":"Esc", "x":0, "y":0},
12 {"label":"1", "x":1, "y":0},
13 {"label":"2", "x":2, "y":0},
14 {"label":"3", "x":3, "y":0},
15 {"label":"4", "x":4, "y":0},
16 {"label":"5", "x":5, "y":0},
17 {"label":"6", "x":6, "y":0},
18
19 {"label":"7", "x":7, "y":0},
20 {"label":"8", "x":8, "y":0},
21 {"label":"9", "x":9, "y":0},
22 {"label":"0", "x":10, "y":0},
23 {"label":"-", "x":11, "y":0},
24 {"label":"=", "x":12, "y":0},
25 {"label":"Backspace", "x":13, "y":0, "w":2.0},
26
27 {"label":"Tab", "x":0, "y":1, "w":1.5},
28 {"label":"Q", "x":1.5, "y":1},
29 {"label":"W", "x":2.5, "y":1},
30 {"label":"E", "x":3.5, "y":1},
31 {
32 "label": "R",
33 "x": 4.5,
34 "y": 1
35 },
36 {"label":"T", "x":5.5, "y":1},
37
38 {"label":"Y", "x":6.5, "y":1},
39 {"label":"U", "x":7.5, "y":1},
40 {"label":"I", "x":8.5, "y":1},
41 {"label":"O", "x":9.5, "y":1},
42 {"label":"P", "x":10.5, "y":1},
43 {"label":"[", "x":11.5, "y":1},
44 {"label":"]", "x":12.5, "y":1},
45 {"label":"\\", "x":13.5, "y":1, "w":1.5},
46
47 {"label":"CapsLock", "x":0, "y":2, "w":1.75},
48 {"label":"A", "x":1.75, "y":2},
49 {"label":"S", "x":2.75, "y":2},
50 {"label":"D", "x":3.75, "y":2},
51 {"label":"F", "x":4.75, "y":2},
52 {"label":"G", "x":5.75, "y":2},
53
54 {"label":"H", "x":6.75, "y":2},
55 {"label":"J", "x":7.75, "y":2},
56 {"label":"K", "x":8.75, "y":2},
57 {"label":"L", "x":9.75, "y":2},
58 {"label":";", "x":10.75, "y":2},
59 {"label":"'", "x":11.75, "y":2},
60 {"label":"Enter", "x":12.75, "y":2, "w":2.25},
61
62 {"label":"Shift", "x":0, "y":3, "w":2.25},
63 {"label":"Z", "x":2.25, "y":3},
64 {"label":"X", "x":3.25, "y":3},
65 {"label":"C", "x":4.25, "y":3},
66 {"label":"V", "x":5.25, "y":3},
67 {"label":"B", "x":6.25, "y":3},
68
69 {"label":"N", "x":7.25, "y":3},
70 {"label":"M", "x":8.25, "y":3},
71 {"label":",", "x":9.25, "y":3},
72 {"label":".", "x":10.25, "y":3},
73 {"label":"/", "x":11.25, "y":3},
74 {"label":"Shift", "x":12.25, "y":3, "w":2.75},
75
76 {"label":"Ctrl", "x":0, "y":4, "w":1.25},
77 {"label":"Win", "x":1.25, "y":4, "w":1.25},
78 {"label":"Alt", "x":2.5, "y":4, "w":1.25},
79 {"x":3.75, "y":4, "w":2.75},
80 {"x":6.5, "y":4, "w":1.25},
81
82 {"x":7.75, "y":4, "w":1.25},
83 {"x":9, "y":4, "w":2.0},
84 {"label":"Alt", "x":11, "y":4},
85 {"label":"Win", "x":12, "y":4},
86 {"label":"Menu", "x":13, "y":4},
87 {"label":"Ctrl", "x":14, "y":4}
88 ]
89 }
90 }
91}
diff --git a/keyboards/handwired/xealous/keymaps/default/keymap.c b/keyboards/handwired/xealous/keymaps/default/keymap.c
new file mode 100644
index 000000000..a07e64fd7
--- /dev/null
+++ b/keyboards/handwired/xealous/keymaps/default/keymap.c
@@ -0,0 +1,105 @@
1#include QMK_KEYBOARD_H
2
3extern keymap_config_t keymap_config;
4
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 _NUMPAD 1
12#define _FN 2
13
14// Fillers to make layering more clear
15#define _______ KC_TRNS
16#define XXXXXXX KC_NO
17#define FN MO(_FN)
18
19const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
20/*
21 * ,-----------------------------------------------------------.
22 * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
23 * |-----------------------------------------------------------|
24 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ |
25 * |-----------------------------------------------------------|
26 * |FN | A| S| D| F| G| H| J| K| L| ;| '|Return |
27 * |-----------------------------------------------------------|
28 * |Shift | Z| X| C| V| B| N| M| ,| .| /| Shift |
29 * |-----------------------------------------------------------|
30 * |Ctrl|Gui |Alt | NUM | Space | Space |Alt |FN |Menu |Ctrl |
31 * `-----------------------------------------------------------'
32 */
33 /* Layer 0: Qwerty */
34 [_QWERTY] = LAYOUT_split60( \
35 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, \
36 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, \
37 FN, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
38 KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, \
39 KC_LCTL, KC_LGUI, KC_LALT, DF(_NUMPAD), KC_SPC, KC_SPC, KC_RALT, FN, KC_APP, KC_RCTL \
40 ),
41
42/*
43 * ,-----------------------------------------------------------.
44 * | | | | | | | |Nlck| /| *| -| | | |
45 * |-----------------------------------------------------------|
46 * | | | | | | | | 7| 8| 9| +| | | |
47 * |-----------------------------------------------------------|
48 * | | | | | | | | 4| 5| 6|Bspc| |Return |
49 * |-----------------------------------------------------------|
50 * | | | | | | | | 1| 2| 3| .| |
51 * |-----------------------------------------------------------|
52 * | | | | QWE | | 0 | . |A_ON |A_OFF| |
53 * `-----------------------------------------------------------'
54 */
55
56 /* Layer 1: Numpad */
57 [_NUMPAD] = LAYOUT_split60( \
58 _______, _______, _______, _______, _______, _______, _______, KC_NLCK, KC_PSLS, KC_PAST, KC_MINUS, _______, _______, KC_BSPC, \
59 _______, _______, _______, _______, _______, _______, _______, KC_P7, KC_P8, KC_P9, KC_PLUS, _______, _______, KC_BSLS, \
60 _______, _______, _______, _______, _______, _______, _______, KC_P4, KC_P5, KC_P6, KC_BSPC, _______, _______, \
61 _______, _______, _______, _______, _______, _______, _______, KC_P1, KC_P2, KC_P3, KC_DOT, _______, \
62 _______, _______, _______,DF(_QWERTY), _______, KC_P0, KC_PDOT, AU_ON, AU_OFF, _______ \
63 ),
64
65/*
66 * ,-----------------------------------------------------------.
67 * | ` |F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| Delete|
68 * |-----------------------------------------------------------|
69 * | Caps|pUp| ^ |pDn| | | |pUp| ^ |pDn|PSR|SLK|Pau| |
70 * |-----------------------------------------------------------|
71 * | | < | v | > | |Hom|Hom| < | v | > |INS| DEL| |
72 * |-----------------------------------------------------------|
73 * | | | | | |End|End| |Vo-|Vo+|VoX| |
74 * |-----------------------------------------------------------|
75 * | | | | | | | | | | |
76 * `-----------------------------------------------------------'
77 */
78
79 /* Layer 2: RAISE */
80 [_FN] = LAYOUT_split60( \
81 KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
82 KC_CAPS, KC_PGUP, KC_UP, KC_PGDN, _______, _______, _______, KC_PGUP, KC_UP, KC_PGDN, KC_PSCR, KC_SLCK, KC_PAUS, _______, \
83 _______, KC_LEFT, KC_DOWN,KC_RIGHT, _______, KC_HOME, KC_HOME, KC_LEFT, KC_DOWN, KC_RIGHT, KC_INS, KC_DEL, _______, \
84 _______, _______, _______, _______, _______, KC_END, KC_END, AU_TOG, KC_VOLD, KC_VOLU, KC_MUTE, _______, \
85 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
86 )
87
88};
89
90#ifdef AUDIO_ENABLE
91float tone_qwerty[][2] = TONE_QWERTY;
92float tone_numpad[][2] = TONE_NUMPAD;
93
94uint32_t default_layer_state_set_kb(uint32_t state) {
95 if (state == 1UL<<_QWERTY) {
96 PLAY_SONG(tone_qwerty);
97 } else if (state == 1UL<<_NUMPAD) {
98 PLAY_SONG(tone_numpad);
99 }
100 return state;
101}
102#endif
103
104void led_set_keymap(uint8_t usb_led) {
105}
diff --git a/keyboards/handwired/xealous/matrix.c b/keyboards/handwired/xealous/matrix.c
new file mode 100644
index 000000000..27fad0008
--- /dev/null
+++ b/keyboards/handwired/xealous/matrix.c
@@ -0,0 +1,376 @@
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#ifdef DEBUG_MATRIX_SCAN_RATE
34 #include "matrix_scanrate.h"
35#endif
36
37
38
39#ifdef USE_I2C
40# include "i2c.h"
41#else // USE_SERIAL
42# error "only i2c supported"
43#endif
44
45#ifndef DEBOUNCING_DELAY
46# define DEBOUNCING_DELAY 5
47#endif
48
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
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];
71static matrix_row_t* debouncing_matrix_hand_offsetted; //pointer to matrix_debouncing for our hand
72static matrix_row_t* matrix_hand_offsetted; // pointer to matrix for our hand
73
74//Debouncing counters
75typedef uint8_t debounce_counter_t;
76#define DEBOUNCE_COUNTER_MODULO 250
77#define DEBOUNCE_COUNTER_INACTIVE 251
78static debounce_counter_t debounce_counters[MATRIX_ROWS * MATRIX_COLS];
79static debounce_counter_t *debounce_counters_hand_offsetted;
80
81
82#if (DIODE_DIRECTION == ROW2COL)
83 error "Only Col2Row supported";
84#endif
85static void init_cols(void);
86static void unselect_rows(void);
87static void select_row(uint8_t row);
88static void unselect_row(uint8_t row);
89static matrix_row_t optimized_col_reader(void);
90
91__attribute__ ((weak))
92void matrix_init_kb(void) {
93 matrix_init_user();
94}
95
96__attribute__ ((weak))
97void matrix_scan_kb(void) {
98 matrix_scan_user();
99}
100
101__attribute__ ((weak))
102void matrix_init_user(void) {
103}
104
105__attribute__ ((weak))
106void matrix_scan_user(void) {
107}
108
109__attribute__ ((weak))
110void matrix_slave_scan_user(void) {
111}
112
113inline
114uint8_t matrix_rows(void)
115{
116 return MATRIX_ROWS;
117}
118
119inline
120uint8_t matrix_cols(void)
121{
122 return MATRIX_COLS;
123}
124
125void matrix_init(void)
126{
127#ifdef DISABLE_JTAG
128 // JTAG disable for PORT F. write JTD bit twice within four cycles.
129 MCUCR |= (1<<JTD);
130 MCUCR |= (1<<JTD);
131#endif
132
133 debug_enable = true;
134 debug_matrix = false;
135 debug_mouse = false;
136 // initialize row and col
137 unselect_rows();
138 init_cols();
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 int my_hand_offset = isLeftHand ? 0 : (ROWS_PER_HAND);
148 debouncing_matrix_hand_offsetted = matrix_debouncing + my_hand_offset;
149 matrix_hand_offsetted = matrix + my_hand_offset;
150 debounce_counters_hand_offsetted = debounce_counters + my_hand_offset;
151
152 for (uint8_t i = 0; i < MATRIX_ROWS * MATRIX_COLS; i++) {
153 debounce_counters[i] = DEBOUNCE_COUNTER_INACTIVE;
154 }
155
156 matrix_init_quantum();
157
158}
159
160//#define TIMER_DIFF(a, b, max) ((a) >= (b) ? (a) - (b) : (max) - (b) + (a))
161void update_debounce_counters(uint8_t current_time)
162{
163 debounce_counter_t *debounce_pointer = debounce_counters_hand_offsetted;
164 for (uint8_t row = 0; row < ROWS_PER_HAND; row++)
165 {
166 for (uint8_t col = 0; col < MATRIX_COLS; col++)
167 {
168 if (*debounce_pointer != DEBOUNCE_COUNTER_INACTIVE)
169 {
170 if (TIMER_DIFF(current_time, *debounce_pointer, DEBOUNCE_COUNTER_MODULO) >=
171 DEBOUNCING_DELAY) {
172 *debounce_pointer = DEBOUNCE_COUNTER_INACTIVE;
173 }
174 }
175 debounce_pointer++;
176 }
177 }
178}
179
180void transfer_matrix_values(uint8_t current_time)
181{
182 //upload from debounce_matrix to final matrix;
183 debounce_counter_t *debounce_pointer = debounce_counters_hand_offsetted;
184 for (uint8_t row = 0; row < ROWS_PER_HAND; row++)
185 {
186 matrix_row_t row_value = matrix_hand_offsetted[row];
187 matrix_row_t debounce_value = debouncing_matrix_hand_offsetted[row];
188
189 for (uint8_t col = 0; col < MATRIX_COLS; col++)
190 {
191 bool final_value = debounce_value & (1 << col);
192 bool current_value = row_value & (1 << col);
193 if (*debounce_pointer == DEBOUNCE_COUNTER_INACTIVE
194 && (current_value != final_value))
195 {
196 *debounce_pointer = current_time;
197 row_value ^= (1 << col);
198 }
199 debounce_pointer++;
200 }
201 matrix_hand_offsetted[row] = row_value;
202 }
203}
204
205uint8_t _matrix_scan(void)
206{
207 uint8_t current_time = timer_read() % DEBOUNCE_COUNTER_MODULO;
208
209 // Set row, read cols
210 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
211 select_row(current_row);
212 asm volatile ("nop"); asm volatile("nop");
213
214 debouncing_matrix_hand_offsetted[current_row] = optimized_col_reader();
215 // Unselect row
216 unselect_row(current_row);
217 }
218
219 update_debounce_counters(current_time);
220 transfer_matrix_values(current_time);
221
222 return 1;
223}
224
225
226// Get rows from other half over i2c
227int i2c_transaction(void) {
228 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
229
230 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
231 if (err) goto i2c_error;
232
233 // start of matrix stored at 0x00
234 err = i2c_master_write(I2C_KEYMAP_START);
235 if (err) goto i2c_error;
236
237 // Start read
238 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
239 if (err) goto i2c_error;
240
241 if (!err) {
242 int i;
243 for (i = 0; i < ROWS_PER_HAND-1; ++i) {
244 matrix[slaveOffset+i] = i2c_master_read(I2C_ACK);
245 }
246 matrix[slaveOffset+i] = i2c_master_read(I2C_NACK);
247 i2c_master_stop();
248 } else {
249i2c_error: // the cable is disconnceted, or something else went wrong
250 i2c_reset_state();
251 return err;
252 }
253
254 return 0;
255}
256
257uint8_t matrix_scan(void)
258{
259#ifdef DEBUG_MATRIX_SCAN_RATE
260 matrix_check_scan_rate();
261 matrix_time_between_scans();
262#endif
263 uint8_t ret = _matrix_scan();
264
265 if( i2c_transaction() ) {
266 // turn on the indicator led when halves are disconnected
267 TXLED1;
268
269 error_count++;
270
271 if (error_count > ERROR_DISCONNECT_COUNT) {
272 // reset other half if disconnected
273 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
274 for (int i = 0; i < ROWS_PER_HAND; ++i) {
275 matrix[slaveOffset+i] = 0;
276 }
277 }
278 } else {
279 // turn off the indicator led on no error
280 TXLED0;
281 error_count = 0;
282 }
283 matrix_scan_quantum();
284 return ret;
285}
286
287void matrix_slave_scan(void) {
288 _matrix_scan();
289
290 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
291
292 for (int i = 0; i < ROWS_PER_HAND; ++i) {
293 i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
294 }
295
296 matrix_slave_scan_user();
297}
298
299inline
300bool matrix_is_on(uint8_t row, uint8_t col)
301{
302 return (matrix[row] & ((matrix_row_t)1<<col));
303}
304
305
306inline
307matrix_row_t matrix_get_row(uint8_t row)
308{
309 return matrix[row];
310}
311
312void matrix_print(void)
313{
314 print("\nr/c 0123456789ABCDEF\n");
315 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
316 phex(row); print(": ");
317 pbin_reverse16(matrix_get_row(row));
318 print("\n");
319 }
320}
321
322uint8_t matrix_key_count(void)
323{
324 uint8_t count = 0;
325 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
326 count += bitpop16(matrix[i]);
327 }
328 return count;
329}
330
331static void init_cols(void)
332{
333 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
334 uint8_t pin = col_pins[x];
335 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
336 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
337 }
338}
339
340inline
341static matrix_row_t optimized_col_reader(void) {
342 //MATRIX_COL_PINS { B6, B2, B3, B1, F7, F6, F5, F4 }
343 return (PINB & (1 << 6) ? 0 : (ROW_SHIFTER << 0)) |
344 (PINB & (1 << 2) ? 0 : (ROW_SHIFTER << 1)) |
345 (PINB & (1 << 3) ? 0 : (ROW_SHIFTER << 2)) |
346 (PINB & (1 << 1) ? 0 : (ROW_SHIFTER << 3)) |
347 (PINF & (1 << 7) ? 0 : (ROW_SHIFTER << 4)) |
348 (PINF & (1 << 6) ? 0 : (ROW_SHIFTER << 5)) |
349 (PINF & (1 << 5) ? 0 : (ROW_SHIFTER << 6)) |
350 (PINF & (1 << 4) ? 0 : (ROW_SHIFTER << 7));
351}
352
353
354static void select_row(uint8_t row)
355{
356 uint8_t pin = row_pins[row];
357 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
358 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
359}
360
361static void unselect_row(uint8_t row)
362{
363 uint8_t pin = row_pins[row];
364 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
365 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
366}
367
368static void unselect_rows(void)
369{
370 for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
371 uint8_t pin = row_pins[x];
372 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
373 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
374 }
375}
376
diff --git a/keyboards/handwired/xealous/matrix_scanrate.c b/keyboards/handwired/xealous/matrix_scanrate.c
new file mode 100644
index 000000000..f2c7cbe6e
--- /dev/null
+++ b/keyboards/handwired/xealous/matrix_scanrate.c
@@ -0,0 +1,39 @@
1#include <stdint.h>
2#include <stdbool.h>
3#include <avr/io.h>
4#include "wait.h"
5#include "print.h"
6#include "debug.h"
7#include "util.h"
8#include "matrix.h"
9#include "timer.h"
10
11#ifdef CONSOLE_ENABLE
12static uint16_t matrix_scan_count = 0;
13static uint32_t matrix_timer = 0;
14void matrix_check_scan_rate(void) {
15 matrix_scan_count++;
16 if (matrix_scan_count > 1000) {
17 uint32_t timer_now = timer_read32();
18 uint16_t ms_per_thousand = TIMER_DIFF_32(timer_now, matrix_timer);
19 uint16_t rate_per_second = 1000000UL / ms_per_thousand;
20 print("scan_rate: ");
21 pdec(rate_per_second);
22 print("\n");
23 matrix_timer = timer_now;
24 matrix_scan_count = 0;
25 }
26}
27
28static uint32_t last_scan_time = 0;
29void matrix_time_between_scans(void) {
30 if (timer_elapsed(last_scan_time) > 1)
31 {
32 print(">1ms elapsed since last scan: ");
33 pdec(timer_elapsed(last_scan_time));
34 print("\n");
35 }
36 last_scan_time = timer_read();
37
38}
39#endif
diff --git a/keyboards/handwired/xealous/matrix_scanrate.h b/keyboards/handwired/xealous/matrix_scanrate.h
new file mode 100644
index 000000000..18d56cd5b
--- /dev/null
+++ b/keyboards/handwired/xealous/matrix_scanrate.h
@@ -0,0 +1,4 @@
1__attribute__((weak))
2void matrix_check_scan_rate(void) {}
3__attribute__((weak))
4void matrix_time_between_scans(void) {}
diff --git a/keyboards/handwired/xealous/readme.md b/keyboards/handwired/xealous/readme.md
new file mode 100644
index 000000000..97bebbfe3
--- /dev/null
+++ b/keyboards/handwired/xealous/readme.md
@@ -0,0 +1,166 @@
1XeaL60
2======
3
4Split keyboard firmware for Arduino Pro Micro or other ATmega32u4
5based boards.
6
7
8## Build Guide
9
10A build guide for putting together the Xealous can be found here: https://github.com/alex-ong/Split60
11
12
13## First Time Setup
14
15Download 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:
16
17```
18$ make handwired/xeal60/rev1:default
19```
20
21You will see a lot of output and if everything worked correctly you will see the built hex file:
22
23```
24handwired_xeal60_rev1_default.hex
25```
26
27If 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:
28
29
30```
31$ make handwired/xeal60/rev1:YOUR_KEYMAP_NAME
32```
33
34If everything worked correctly you will see a file:
35
36```
37handwired_xeal60_rev1_YOUR_KEYMAP_NAME.hex
38```
39
40For 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.
41
42
43Features
44--------
45
46For the full Quantum Mechanical Keyboard feature list, see [the parent readme.md](/readme.md).
47
48Some features supported by the firmware:
49
50* Either half can connect to the computer via USB, or both halves can be used
51 independently.
52* I2C connection between the two halves if for some
53 reason you require a faster connection between the two halves. Note this
54 requires an extra wire between halves and pull-up resistors on the data lines.
55
56Required Hardware
57-----------------
58
59Apart from diodes and key switches for the keyboard matrix in each half, you
60will need:
61
62* 2 Arduino Pro Micros. You can find these on AliExpress for ≈3.50USD each.
63* 2 TRRS sockets and 1 TRRS cable, or 2 TRS sockets and 1 TRS cable
64
65Alternatively, you can use any sort of cable and socket that has at least 4
66wires. You will need a cable with at least 4 wires and 2x 4.7kΩ pull-up resistors
67
68Optional Hardware
69-----------------
70
71A speaker can be hooked-up to either side to the `5` (`C6`) pin and `GND`, and turned on via `AUDIO_ENABLE`.
72
73Wiring
74------
75
76The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and digital pin 3 (i.e.
77PD0 on the ATmega32u4) between the two Pro Micros.
78
79Next, wire your key matrix to any of the remaining 17 IO pins of the pro micro
80and modify the `matrix.c` accordingly.
81
82The wiring for serial:
83
84![serial wiring](https://i.imgur.com/C3D1GAQ.png)
85
86
87Notes on Software Configuration
88-------------------------------
89
90Configuring the firmware is similar to any other QMK project. One thing
91to note is that `MATRIX_ROWS` in `config.h` is the total number of rows between
92the two halves, i.e. if your split keyboard has 5 rows in each half, then use
93`MATRIX_ROWS=10`.
94
95Also, the current implementation assumes a maximum of 8 columns, but it would
96not be very difficult to adapt it to support more if required.
97
98Flashing
99-------
100From the top level `qmk_firmware` directory run `make KEYBOARD:KEYMAP:avrdude` for automatic serial port resolution and flashing.
101Example: `make handwired/xeal60/rev1:default:avrdude`
102
103
104Choosing which board to plug the USB cable into (choosing Master)
105--------
106Because the two boards are identical, the firmware has logic to differentiate the left and right board.
107
108It 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.
109
110The EEPROM approach requires additional setup (flashing the eeprom) but allows you to swap the usb cable to either side.
111
112The 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.
113
114### Setting the left hand as master
115If 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.
116
117### Setting the right hand as master
118If you always plug the usb cable into the right board, add an extra flag to your `config.h`
119```
120 #define MASTER_RIGHT
121```
122
123### Setting EE_hands to use either hands as master
124If you define `EE_HANDS` in your `config.h`, you will need to set the
125EEPROM for the left and right halves.
126
127The EEPROM is used to store whether the
128half is left handed or right handed. This makes it so that the same firmware
129file will run on both hands instead of having to flash left and right handed
130versions of the firmware to each half. To flash the EEPROM file for the left
131half run:
132```
133avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-lefthand.eep
134// or the equivalent in dfu-programmer
135
136```
137and similarly for right half
138```
139avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-righhand.eep
140// or the equivalent in dfu-programmer
141```
142
143NOTE: replace `$(COM_PORT)` with the port of your device (e.g. `/dev/ttyACM0`)
144
145After you have flashed the EEPROM, you then need to set `EE_HANDS` in your config.h, rebuild the hex files and reflash.
146
147Note that you need to program both halves, but you have the option of using
148different keymaps for each half. You could program the left half with a QWERTY
149layout and the right half with a Colemak layout using bootmagic's default layout option.
150Then if you connect the left half to a computer by USB the keyboard will use QWERTY and Colemak when the
151right half is connected.
152
153
154Notes on Using Pro Micro 3.3V
155-----------------------------
156
157Do update the `F_CPU` parameter in `rules.mk` to `8000000` which reflects
158the frequency on the 3.3V board.
159
160Also, if the slave board is producing weird characters in certain columns,
161update the following line in `matrix.c` to the following:
162
163```
164// _delay_us(30); // without this wait read unstable value.
165_delay_us(300); // without this wait read unstable value.
166```
diff --git a/keyboards/handwired/xealous/rev1/config.h b/keyboards/handwired/xealous/rev1/config.h
new file mode 100644
index 000000000..6fc769b5f
--- /dev/null
+++ b/keyboards/handwired/xealous/rev1/config.h
@@ -0,0 +1,90 @@
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. Pin names PD3, PD2, etc.
39//Usage| Name | Label Label| Name | Usage
40// PORT
41// | PD3 TX0 RAW |
42// | PD2 RX1 GND |SerGnd
43// | GND RESET |
44// | GND VCC |SerVCc
45// | PD1 2 A3 PF4 | Col7
46//Ser | PD0 3 A2 PF5 | Col6
47//Row4 | PD4 4 A1 PF6 | Col5
48//AUDIO| PC6 5 A0 PF7 | Col4
49//Row3 | PD7 6 15 PB1 | Col3
50//Row2 | PE6 7 14 PB3 | Col2
51//Row1 | PB4 8 13 PB2 | Col1
52//Row0 | PB5 9 10 PB6 | Col0
53
54// Note reservation of C6 for audio
55#define MATRIX_ROW_PINS { B5, B4, E6, D7, D4 }
56#define MATRIX_COL_PINS { B6, B2, B3, B1, F7, F6, F5, F4 }
57
58/* define if matrix has ghost */
59//#define MATRIX_HAS_GHOST
60
61/* number of backlight levels */
62// #define BACKLIGHT_LEVELS 3
63
64/* Set 0 if debouncing isn't needed */
65#define DEBOUNCING_DELAY 5
66
67/* key combination for command */
68#define IS_COMMAND() ( \
69 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
70)
71
72/*
73 * Feature disable options
74 * These options are also useful to firmware size reduction.
75 */
76
77/* disable debug print */
78// #define NO_DEBUG
79
80/* disable print */
81// #define NO_PRINT
82
83/* disable action features */
84//#define NO_ACTION_LAYER
85//#define NO_ACTION_TAPPING
86#define NO_ACTION_ONESHOT
87#define NO_ACTION_MACRO
88//#define NO_ACTION_FUNCTION
89#define IGNORE_MOD_TAP_INTERRUPT
90#endif
diff --git a/keyboards/handwired/xealous/rev1/rev1.c b/keyboards/handwired/xealous/rev1/rev1.c
new file mode 100644
index 000000000..3e51421d8
--- /dev/null
+++ b/keyboards/handwired/xealous/rev1/rev1.c
@@ -0,0 +1,6 @@
1#include "quantum.h"
2#include "rev1.h"
3
4void matrix_init_kb(void) {
5 matrix_init_user();
6}
diff --git a/keyboards/handwired/xealous/rev1/rev1.h b/keyboards/handwired/xealous/rev1/rev1.h
new file mode 100644
index 000000000..d195af49d
--- /dev/null
+++ b/keyboards/handwired/xealous/rev1/rev1.h
@@ -0,0 +1,32 @@
1#ifndef REV1_H
2#define REV1_H
3
4//void promicro_bootloader_jmp(bool program);
5#include "quantum.h"
6
7//void promicro_bootloader_jmp(bool program);
8#define XXX KC_NO
9
10#define LAYOUT( \
11 L00, L01, L02, L03, L04, L05, L06, R06, R05, R04, R03, R02, R01, R00, \
12 L10, L11, L12, L13, L14, L15, R17, R16, R15, R14, R13, R12, R11, R10, \
13 L20, L21, L22, L23, L24, L25, R26, R25, R24, R23, R22, R21, R20, \
14 L30, L31, L32, L33, L34, L35, R35, R34, R33, R32, R31, R30, \
15 L40, L41, L42, L43, L44, R44, R43, R42, R41, R40 \
16 ) \
17 { \
18 { XXX, L06, L05, L04, L03, L02, L01, L00 }, \
19 { XXX, XXX, L15, L14, L13, L12, L11, L10 }, \
20 { XXX, XXX, L25, L24, L23, L22, L21, L20 }, \
21 { XXX, XXX, L35, L34, L33, L32, L31, L30 }, \
22 { XXX, XXX, XXX, L44, L43, L42, L41, L40 }, \
23 { R00, R01, R02, R03, R04, R05, R06, XXX }, \
24 { R10, R11, R12, R13, R14, R15, R16, R17 }, \
25 { R20, R21, R22, R23, R24, R25, R26, XXX }, \
26 { R30, R31, R32, R33, R34, R35, XXX, XXX }, \
27 { R40, R41, R42, R43, R44, XXX, XXX, XXX } \
28 }
29
30#define LAYOUT_split60 LAYOUT
31
32#endif
diff --git a/keyboards/handwired/xealous/rev1/rules.mk b/keyboards/handwired/xealous/rev1/rules.mk
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/keyboards/handwired/xealous/rev1/rules.mk
diff --git a/keyboards/handwired/xealous/rules.mk b/keyboards/handwired/xealous/rules.mk
new file mode 100644
index 000000000..717895960
--- /dev/null
+++ b/keyboards/handwired/xealous/rules.mk
@@ -0,0 +1,73 @@
1SRC += matrix_scanrate.c matrix.c
2
3# MCU name
4MCU = atmega32u4
5
6# Processor frequency.
7# This will define a symbol, F_CPU, in all source code files equal to the
8# processor frequency in Hz. You can then use this symbol in your source code to
9# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
10# automatically to create a 32-bit value in your source code.
11#
12# This will be an integer division of F_USB below, as it is sourced by
13# F_USB after it has run through any CPU prescalers. Note that this value
14# does not *change* the processor frequency - it should merely be updated to
15# reflect the processor speed set externally so that the code can use accurate
16# software delays.
17F_CPU = 16000000
18
19#
20# LUFA specific
21#
22# Target architecture (see library "Board Types" documentation).
23ARCH = AVR8
24
25# Input clock frequency.
26# This will define a symbol, F_USB, in all source code files equal to the
27# input clock frequency (before any prescaling is performed) in Hz. This value may
28# differ from F_CPU if prescaling is used on the latter, and is required as the
29# raw input clock is fed directly to the PLL sections of the AVR for high speed
30# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
31# at the end, this will be done automatically to create a 32-bit value in your
32# source code.
33#
34# If no clock division is performed on the input clock inside the AVR (via the
35# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
36F_USB = $(F_CPU)
37
38# Bootloader
39# This definition is optional, and if your keyboard supports multiple bootloaders of
40# different sizes, comment this out, and the correct address will be loaded
41# automatically (+60). See bootloader.mk for all options.
42BOOTLOADER = caterina
43
44# Interrupt driven control endpoint task(+60)
45OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
46
47# Build Options
48# change to "no" to disable the options, or define them in the Makefile in
49# the appropriate keymap folder that will get included automatically
50#
51BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
52MOUSEKEY_ENABLE = no # Mouse keys(+4700)
53EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
54CONSOLE_ENABLE = yes # Console for debug(+400)
55COMMAND_ENABLE = yes # Commands for debug and configuration
56NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
57BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
58MIDI_ENABLE = no # MIDI controls
59AUDIO_ENABLE = yes # Audio output on port C6
60UNICODE_ENABLE = no # Unicode
61BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
62RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
63SPLIT_KEYBOARD = yes # Use shared split_common code
64SUBPROJECT_rev1 = yes
65
66# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
67SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
68
69CUSTOM_MATRIX = yes
70
71LAYOUTS = split60
72
73DEFAULT_FOLDER = handwired/xealous/rev1