aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Roberts <miker@miker.org>2019-05-11 21:12:06 -0400
committerMechMerlin <30334081+mechmerlin@users.noreply.github.com>2019-05-11 18:12:06 -0700
commitf542c0589bec06501a3990070c08638a9124f055 (patch)
tree82fa658c9b6a16bde2f8b3a91239c085af09763a
parentd53cbd2dc6ec6877f2815c546c03b39fac7a8afa (diff)
downloadqmk_firmware-f542c0589bec06501a3990070c08638a9124f055.tar.gz
qmk_firmware-f542c0589bec06501a3990070c08638a9124f055.zip
NEK Type A (#5175)
* project creation and config.h import * fix name * cleanup * layout for left * working left with feather pins * full keymap * ? * let's do this * non working twimaster version * it fucking works! * bluetooth! * cleanup * use auto output for ADAFRUIT_BLE * remove auto from custom matrix * better ble auto * fix f1 * revert * fix ble * update readme * Update readme.md * Update readme.md
-rw-r--r--keyboards/nek_type_a/config.h55
-rw-r--r--keyboards/nek_type_a/info.json0
-rw-r--r--keyboards/nek_type_a/keymaps/default/config.h19
-rw-r--r--keyboards/nek_type_a/keymaps/default/keymap.c39
-rw-r--r--keyboards/nek_type_a/keymaps/default/readme.md3
-rw-r--r--keyboards/nek_type_a/matrix.c412
-rw-r--r--keyboards/nek_type_a/mcp23017.c107
-rw-r--r--keyboards/nek_type_a/mcp23017.h71
-rw-r--r--keyboards/nek_type_a/nek_type_a.c43
-rw-r--r--keyboards/nek_type_a/nek_type_a.h58
-rw-r--r--keyboards/nek_type_a/readme.md30
-rw-r--r--keyboards/nek_type_a/rules.mk33
12 files changed, 870 insertions, 0 deletions
diff --git a/keyboards/nek_type_a/config.h b/keyboards/nek_type_a/config.h
new file mode 100644
index 000000000..782b91d0e
--- /dev/null
+++ b/keyboards/nek_type_a/config.h
@@ -0,0 +1,55 @@
1/*
2Copyright 2018 Mike Roberts
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#pragma once
19
20#include "config_common.h"
21
22/* USB Device descriptor parameter */
23#define VENDOR_ID 0xFEED
24#define PRODUCT_ID 0x0000
25#define DEVICE_VER 0x0001
26#define MANUFACTURER miker
27#define PRODUCT nek_type_a
28#define DESCRIPTION NEK Type A
29
30/* key matrix size */
31#define MATRIX_ROWS 6
32#define MATRIX_COLS 18
33
34/* left columns are all onboard, right columns all on expander */
35#define COL_EXPANDED { false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true}
36#define MATRIX_COL_PINS { C6, D7, B5, B6, B7, D6, D3, GPA0, GPA1, GPA2, GPA3, GPA4, GPA5, GPA6, GPA7, GPB0, GPB1, GPB2 }
37#define MATRIX_ROW_PINS { F7, F6, F5, F4, F1, F0 }
38
39#define DIODE_DIRECTION ROW2COL
40
41/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
42#define DEBOUNCING_DELAY 5
43
44/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
45#define LOCKING_SUPPORT_ENABLE
46
47/* Locking resynchronize hack */
48#define LOCKING_RESYNC_ENABLE
49
50/* key combination for magic key command */
51#define IS_COMMAND() ( \
52 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
53)
54
55
diff --git a/keyboards/nek_type_a/info.json b/keyboards/nek_type_a/info.json
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/keyboards/nek_type_a/info.json
diff --git a/keyboards/nek_type_a/keymaps/default/config.h b/keyboards/nek_type_a/keymaps/default/config.h
new file mode 100644
index 000000000..5c2aaa2f3
--- /dev/null
+++ b/keyboards/nek_type_a/keymaps/default/config.h
@@ -0,0 +1,19 @@
1/* Copyright 2018 Mike Roberts
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19// place overrides here
diff --git a/keyboards/nek_type_a/keymaps/default/keymap.c b/keyboards/nek_type_a/keymaps/default/keymap.c
new file mode 100644
index 000000000..627aa4590
--- /dev/null
+++ b/keyboards/nek_type_a/keymaps/default/keymap.c
@@ -0,0 +1,39 @@
1/* Copyright 2018 Mike Roberts
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include QMK_KEYBOARD_H
17
18const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
19 [0] = LAYOUT(
20 KC_ESC, 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__MUTE, KC__VOLDOWN, KC__VOLUP, \
21 KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, KC_EQUAL, KC_BSPACE, KC_INSERT, KC_HOME, KC_PGUP, \
22 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRACKET, KC_RBRACKET, KC_BSLASH, KC_DELETE, KC_END, KC_PGDOWN, \
23 KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCOLON, KC_QUOTE, KC_ENTER, \
24 KC_LSHIFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMMA, KC_DOT, KC_SLASH, KC_RSHIFT, KC_UP, \
25 KC_LCTRL, KC_LALT, KC_LCMD, KC_SPC, KC_SPC, KC_RCMD, KC_RALT, KC_RCTRL, KC_APP, KC_LEFT, KC_DOWN, KC_RIGHT \
26 ),
27};
28
29void matrix_init_user(void) {
30
31}
32
33void matrix_scan_user(void) {
34
35}
36
37void led_set_user(uint8_t usb_led) {
38
39}
diff --git a/keyboards/nek_type_a/keymaps/default/readme.md b/keyboards/nek_type_a/keymaps/default/readme.md
new file mode 100644
index 000000000..763125cea
--- /dev/null
+++ b/keyboards/nek_type_a/keymaps/default/readme.md
@@ -0,0 +1,3 @@
1![NEK Type A Layout](https://i.imgur.com/ElEVvze.png)
2
3# Default NEK Type A Keymap
diff --git a/keyboards/nek_type_a/matrix.c b/keyboards/nek_type_a/matrix.c
new file mode 100644
index 000000000..525296b1f
--- /dev/null
+++ b/keyboards/nek_type_a/matrix.c
@@ -0,0 +1,412 @@
1/*
2Copyright 2012-2018 Jun Wako, Jack Humbert, Mike Roberts
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 * This matrix.c has been hacked up to support some columns being on an ex pander in ROW2COL mode.
20 * The columns are only ever selected and unselected, never read. Unselecting a single column via the expander is not
21 * implemented because updating one column costs the same as updating all the columns in a bank. Currently both banks
22 * are unselected but two i2c transactions could be removed if we only unselect the the proper half.
23 */
24
25#include <stdint.h>
26#include <stdbool.h>
27#if defined(__AVR__)
28#include <avr/io.h>
29#endif
30#include "wait.h"
31#include "print.h"
32#include "debug.h"
33#include "util.h"
34#include "matrix.h"
35#include "timer.h"
36#include "mcp23017.h"
37#include "outputselect.h"
38
39/* Set 0 if debouncing isn't needed */
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#elif (MATRIX_COLS <= 16)
56# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
57# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
58# define matrix_bitpop(i) bitpop16(matrix[i])
59# define ROW_SHIFTER ((uint16_t)1)
60#elif (MATRIX_COLS <= 32)
61# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
62# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
63# define matrix_bitpop(i) bitpop32(matrix[i])
64# define ROW_SHIFTER ((uint32_t)1)
65#endif
66
67#ifdef MATRIX_MASKED
68 extern const matrix_row_t matrix_mask[];
69#endif
70
71#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
72static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
73static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
74static const bool col_expanded[MATRIX_COLS] = COL_EXPANDED;
75#endif
76
77/* matrix state(1:on, 0:off) */
78static matrix_row_t matrix[MATRIX_ROWS];
79
80static matrix_row_t matrix_debouncing[MATRIX_ROWS];
81
82
83#if (DIODE_DIRECTION == COL2ROW)
84 static void init_cols(void);
85 static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
86 static void unselect_rows(void);
87 static void select_row(uint8_t row);
88 static void unselect_row(uint8_t row);
89#elif (DIODE_DIRECTION == ROW2COL)
90 static void init_rows(void);
91 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
92 static void unselect_cols(void);
93 static void unselect_col(uint8_t col);
94 static void select_col(uint8_t col);
95#endif
96
97__attribute__ ((weak))
98void matrix_init_quantum(void) {
99 expander_init();
100 matrix_init_kb();
101}
102
103__attribute__ ((weak))
104void matrix_scan_quantum(void) {
105 matrix_scan_kb();
106}
107
108__attribute__ ((weak))
109void matrix_init_kb(void) {
110 matrix_init_user();
111}
112
113__attribute__ ((weak))
114void matrix_scan_kb(void) {
115 matrix_scan_user();
116}
117
118__attribute__ ((weak))
119void matrix_init_user(void) {
120}
121
122__attribute__ ((weak))
123void matrix_scan_user(void) {
124}
125
126inline
127uint8_t matrix_rows(void) {
128 return MATRIX_ROWS;
129}
130
131inline
132uint8_t matrix_cols(void) {
133 return MATRIX_COLS;
134}
135
136void matrix_init(void) {
137 // initialize row and col
138#if (DIODE_DIRECTION == COL2ROW)
139 unselect_rows();
140 init_cols();
141#elif (DIODE_DIRECTION == ROW2COL)
142 unselect_cols();
143 init_rows();
144#endif
145
146 // initialize matrix state: all keys off
147 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
148 matrix[i] = 0;
149 matrix_debouncing[i] = 0;
150 }
151
152 matrix_init_quantum();
153 set_output(OUTPUT_AUTO);
154}
155
156uint8_t matrix_scan(void)
157{
158
159#if (DIODE_DIRECTION == COL2ROW)
160
161 // Set row, read cols
162 for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
163# if (DEBOUNCING_DELAY > 0)
164 bool matrix_changed = read_cols_on_row(matrix_debouncing, current_row);
165
166 if (matrix_changed) {
167 debouncing = true;
168 debouncing_time = timer_read();
169 }
170
171# else
172 read_cols_on_row(matrix, current_row);
173# endif
174
175 }
176
177#elif (DIODE_DIRECTION == ROW2COL)
178
179 // Set col, read rows
180 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
181# if (DEBOUNCING_DELAY > 0)
182 bool matrix_changed = read_rows_on_col(matrix_debouncing, current_col);
183 if (matrix_changed) {
184 debouncing = true;
185 debouncing_time = timer_read();
186 }
187# else
188 read_rows_on_col(matrix, current_col);
189# endif
190
191 }
192
193#endif
194
195# if (DEBOUNCING_DELAY > 0)
196 if (debouncing && (timer_elapsed(debouncing_time) > DEBOUNCING_DELAY)) {
197 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
198 matrix[i] = matrix_debouncing[i];
199 }
200 debouncing = false;
201 }
202# endif
203
204 matrix_scan_quantum();
205 return 1;
206}
207
208bool matrix_is_modified(void)
209{
210#if (DEBOUNCING_DELAY > 0)
211 if (debouncing) return false;
212#endif
213 return true;
214}
215
216inline
217bool matrix_is_on(uint8_t row, uint8_t col)
218{
219 return (matrix[row] & ((matrix_row_t)1<col));
220}
221
222inline
223matrix_row_t matrix_get_row(uint8_t row)
224{
225 // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
226 // switch blocker installed and the switch is always pressed.
227#ifdef MATRIX_MASKED
228 return matrix[row] & matrix_mask[row];
229#else
230 return matrix[row];
231#endif
232}
233
234void matrix_print(void)
235{
236 print_matrix_header();
237
238 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
239 phex(row); print(": ");
240 print_matrix_row(row);
241 print("\n");
242 }
243}
244
245uint8_t matrix_key_count(void)
246{
247 uint8_t count = 0;
248 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
249 count += matrix_bitpop(i);
250 }
251 return count;
252}
253
254
255
256#if (DIODE_DIRECTION == COL2ROW)
257
258static void init_cols(void)
259{
260 for(uint8_t x = 0; x < MATRIX_COLS; x++) {
261 uint8_t pin = col_pins[x];
262 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
263 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
264 }
265}
266
267static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
268{
269 // Store last value of row prior to reading
270 matrix_row_t last_row_value = current_matrix[current_row];
271
272 // Clear data in matrix row
273 current_matrix[current_row] = 0;
274
275 // Select row and wait for row selecton to stabilize
276 select_row(current_row);
277 wait_us(30);
278
279 // For each col...
280 for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
281
282 // Select the col pin to read (active low)
283 uint8_t pin = col_pins[col_index];
284 uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
285
286 // Populate the matrix row with the state of the col pin
287 current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
288 }
289
290 // Unselect row
291 unselect_row(current_row);
292
293 return (last_row_value != current_matrix[current_row]);
294}
295
296static void select_row(uint8_t row)
297{
298 uint8_t pin = row_pins[row];
299 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
300 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
301}
302
303static void unselect_row(uint8_t row)
304{
305 uint8_t pin = row_pins[row];
306 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
307 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
308}
309
310static void unselect_rows(void)
311{
312 for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
313 uint8_t pin = row_pins[x];
314 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
315 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
316 }
317}
318
319#elif (DIODE_DIRECTION == ROW2COL)
320
321static void init_rows(void)
322{
323 for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
324 uint8_t pin = row_pins[x];
325 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
326 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
327 }
328}
329
330static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
331{
332 bool matrix_changed = false;
333
334 // Select col and wait for col selecton to stabilize
335 select_col(current_col);
336 wait_us(30);
337
338 // For each row...
339 for(uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++)
340 {
341 // Store last value of row prior to reading
342 matrix_row_t last_row_value = current_matrix[row_index];
343
344 // Check row pin state
345 if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
346 {
347 // Pin LO, set col bit
348 current_matrix[row_index] |= (ROW_SHIFTER << current_col);
349 }
350 else
351 {
352 // Pin HI, clear col bit
353 current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
354 }
355
356 // Determine if the matrix changed state
357 if ((last_row_value != current_matrix[row_index]) && !(matrix_changed))
358 {
359 matrix_changed = true;
360 }
361 }
362
363 // Unselect col
364 unselect_col(current_col);
365
366 return matrix_changed;
367}
368
369static void select_col(uint8_t col)
370{
371 uint8_t pin = col_pins[col];
372 if (col_expanded[col])
373 {
374 expander_select(pin);
375 }
376 else
377 {
378 _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
379 _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
380 }
381}
382
383
384static void unselect_col(uint8_t col)
385{
386 uint8_t pin = col_pins[col];
387 if (col_expanded[col])
388 {
389 expander_unselect_all();
390 }
391 else
392 {
393 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
394 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
395 }
396}
397
398static void unselect_cols(void)
399{
400 expander_unselect_all();
401
402 for(uint8_t col = 0; col < MATRIX_COLS; col++) {
403 uint8_t pin = col_pins[col];
404 if (!col_expanded[col])
405 {
406 _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
407 _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
408 }
409 }
410}
411
412#endif
diff --git a/keyboards/nek_type_a/mcp23017.c b/keyboards/nek_type_a/mcp23017.c
new file mode 100644
index 000000000..e24231680
--- /dev/null
+++ b/keyboards/nek_type_a/mcp23017.c
@@ -0,0 +1,107 @@
1/* Copyright 2018 Mike Roberts
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include <stdbool.h>
17#include "action.h"
18#include "lib/lufa/LUFA/Drivers/Peripheral/TWI.h"
19#include "lib/lufa/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c"
20#include "mcp23017.h"
21#include "debug.h"
22#include "wait.h"
23
24uint8_t bit_for_pin(uint8_t pin);
25
26uint8_t expander_write(uint8_t reg, uint8_t data);
27
28uint8_t expander_read(uint8_t reg, uint8_t *data);
29
30void expander_config(void);
31
32static const char *twi_err_str(uint8_t res) {
33 switch (res) {
34 case TWI_ERROR_NoError:
35 return "OK";
36 case TWI_ERROR_BusFault:
37 return "BUSFAULT";
38 case TWI_ERROR_BusCaptureTimeout:
39 return "BUSTIMEOUT";
40 case TWI_ERROR_SlaveResponseTimeout:
41 return "SLAVETIMEOUT";
42 case TWI_ERROR_SlaveNotReady:
43 return "SLAVENOTREADY";
44 case TWI_ERROR_SlaveNAK:
45 return "SLAVENAK";
46 default:
47 return "UNKNOWN";
48 }
49}
50
51void expander_init(void) {
52 TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 400000));
53}
54
55// set IN and HI
56void expander_unselect_all() {
57 expander_write(EXPANDER_REG_IODIRA, 0xff);
58 expander_write(EXPANDER_REG_IODIRB, 0xff);
59 expander_write(EXPANDER_REG_OLATA, 0xff);
60 expander_write(EXPANDER_REG_OLATB, 0xff);
61 wait_us(EXPANDER_PAUSE);
62}
63
64// set OUT and LOW
65void expander_select(uint8_t pin) {
66 const uint8_t mask = 0xff & ~(1 << bit_for_pin(pin));
67 if (pin < 8) {
68 expander_write(EXPANDER_REG_IODIRA, mask);
69 expander_write(EXPANDER_REG_OLATA, mask);
70 } else {
71 expander_write(EXPANDER_REG_IODIRB, mask);
72 expander_write(EXPANDER_REG_OLATB, mask);
73 }
74 wait_us(EXPANDER_PAUSE);
75}
76
77void expander_config() {
78 // set everything to input
79 expander_write(EXPANDER_REG_IODIRA, 0xff);
80 expander_write(EXPANDER_REG_IODIRB, 0xff);
81
82 // turn on pull-ups
83 expander_write(EXPANDER_REG_GPPUA, 0xff);
84 expander_write(EXPANDER_REG_GPPUB, 0xff);
85
86 // disable interrupts
87 expander_write(EXPANDER_REG_GPINTENA, 0x0);
88 expander_write(EXPANDER_REG_GPINTENB, 0x0);
89
90 // polarity
91 expander_write(EXPANDER_REG_IPOLA, 0x0);
92 expander_write(EXPANDER_REG_IPOLB, 0x0);
93}
94
95uint8_t bit_for_pin(uint8_t pin) {
96 return pin % 8;
97}
98
99uint8_t expander_write(uint8_t reg, unsigned char val) {
100 uint8_t addr = reg;
101 uint8_t result = TWI_WritePacket(EXPANDER_ADDR << 1, I2C_TIMEOUT, &addr, sizeof(addr), &val, sizeof(val));
102 if (result) {
103 xprintf("mcp: set_register %d = %d failed: %s\n", reg, val, twi_err_str(result));
104 }
105 return result == 0;
106}
107
diff --git a/keyboards/nek_type_a/mcp23017.h b/keyboards/nek_type_a/mcp23017.h
new file mode 100644
index 000000000..41c747bea
--- /dev/null
+++ b/keyboards/nek_type_a/mcp23017.h
@@ -0,0 +1,71 @@
1/* Copyright 2018 Mike Roberts
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef MAP23017_H
17#define MAP23017_H
18
19#define EXPANDER_ADDR 0x27
20#define I2C_TIMEOUT 200 // milliseconds
21#define EXPANDER_PAUSE 0 // microseconds
22
23enum EXPANDER_REGISTERS {
24 EXPANDER_REG_IODIRA = 0x00,
25 EXPANDER_REG_IODIRB = 0x01,
26 EXPANDER_REG_IPOLA = 0x02,
27 EXPANDER_REG_IPOLB = 0x03,
28 EXPANDER_REG_GPINTENA = 0x04,
29 EXPANDER_REG_GPINTENB = 0x05,
30 EXPANDER_REG_DEFVALA = 0x06,
31 EXPANDER_REG_DEFVALB = 0x07,
32 EXPANDER_REG_INTCONA = 0x08,
33 EXPANDER_REG_INTCONB = 0x09,
34 EXPANDER_REG_IOCONA = 0x0A,
35 EXPANDER_REG_IOCONB = 0x0B,
36 EXPANDER_REG_GPPUA = 0x0C,
37 EXPANDER_REG_GPPUB = 0x0D,
38 EXPANDER_REG_INTFA = 0x0E,
39 EXPANDER_REG_INTFB = 0x0F,
40 EXPANDER_REG_INTCAPA = 0x10,
41 EXPANDER_REG_INTCAPB = 0x11,
42 EXPANDER_REG_GPIOA = 0x12,
43 EXPANDER_REG_GPIOB = 0x13,
44 EXPANDER_REG_OLATA = 0x14,
45 EXPANDER_REG_OLATB = 0x15
46};
47
48#define GPA0 0x0
49#define GPA1 0x1
50#define GPA2 0x2
51#define GPA3 0x3
52#define GPA4 0x4
53#define GPA5 0x5
54#define GPA6 0x6
55#define GPA7 0x7
56#define GPB0 0x8
57#define GPB1 0x9
58#define GPB2 0xA
59#define GPB3 0xB
60#define GPB4 0xC
61#define GPB5 0xD
62#define GPB6 0xE
63#define GPB7 0xF
64
65
66void expander_init(void);
67void expander_select(uint8_t pin);
68void expander_unselect(uint8_t pin);
69void expander_unselect_all(void);
70
71#endif \ No newline at end of file
diff --git a/keyboards/nek_type_a/nek_type_a.c b/keyboards/nek_type_a/nek_type_a.c
new file mode 100644
index 000000000..ec76a209b
--- /dev/null
+++ b/keyboards/nek_type_a/nek_type_a.c
@@ -0,0 +1,43 @@
1/* Copyright 2018 Mike Roberts
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#include "nek_type_a.h"
17
18void matrix_init_kb(void) {
19 // put your keyboard start-up code here
20 // runs once when the firmware starts up
21
22 matrix_init_user();
23}
24
25void matrix_scan_kb(void) {
26 // put your looping keyboard code here
27 // runs every cycle (a lot)
28
29 matrix_scan_user();
30}
31
32bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
33 // put your per-action keyboard code here
34 // runs for every action, just before processing by the firmware
35
36 return process_record_user(keycode, record);
37}
38
39void led_set_kb(uint8_t usb_led) {
40 // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
41
42 led_set_user(usb_led);
43}
diff --git a/keyboards/nek_type_a/nek_type_a.h b/keyboards/nek_type_a/nek_type_a.h
new file mode 100644
index 000000000..9bf6028cb
--- /dev/null
+++ b/keyboards/nek_type_a/nek_type_a.h
@@ -0,0 +1,58 @@
1/* Copyright 2018 REPLACE_WITH_YOUR_NAME
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef NEK_TYPE_A_H
17#define NEK_TYPE_A_H
18
19#include "quantum.h"
20#include <stdint.h>
21#include <stdbool.h>
22#include <util/delay.h>
23
24#define I2C_ADDR 0b0100000
25#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
26#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
27#define IODIRA 0x00 // i/o direction register
28#define IODIRB 0x01
29#define GPPUA 0x0C // GPIO pull-up resistor register
30#define GPPUB 0x0D
31#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
32#define GPIOB 0x13
33#define OLATA 0x14 // output latch register
34#define OLATB 0x15
35
36extern uint8_t expander_status;
37extern uint8_t expander_input_pin_mask;
38extern bool i2c_initialized;
39
40void init_expander(void);
41
42#define LAYOUT( \
43 L12, L14, L15, L16, L17, R11, R12, R13, R14, R15, R16, R17, R18, R19, R1A, R1B, \
44 L21, L22, L23, L24, L25, L26, L27, R21, R22, R23, R24, R25, R26, R28, R29, R2A, R2B, \
45 L31, L32, L33, L34, L35, L36, R31, R32, R33, R34, R35, R36, R37, R38, R39, R3A, R3B, \
46 L41, L42, L43, L44, L45, L46, R41, R42, R43, R44, R45, R46, R48, \
47 L51, L52, L53, L54, L55, L56, R51, R52, R53, R54, R55, R58, R5A, \
48 L61, L62, L63, L65, R61, R63, R65, R66, R68, R69, R6A, R6B \
49) \
50{ \
51 { KC_NO, L12, KC_NO, L14, L15, L16, L17, R11, R12, R13, R14, R15, R16, R17, R18, R19, R1A, R1B }, \
52 { L21, L22, L23, L24, L25, L26, L27, R21, R22, R23, R24, R25, R26, KC_NO, R28, R29, R2A, R2B }, \
53 { L31, L32, L33, L34, L35, L36, KC_NO, R31, R32, R33, R34, R35, R36, R37, R38, R39, R3A, R3B }, \
54 { L41, L42, L43, L44, L45, L46, KC_NO, R41, R42, R43, R44, R45, R46, KC_NO, R48, KC_NO, KC_NO, KC_NO }, \
55 { L51, L52, L53, L54, L55, L56, KC_NO, R51, R52, R53, R54, R55, KC_NO, KC_NO, R58, KC_NO, R5A, KC_NO }, \
56 { L61, L62, L63, KC_NO, L65, KC_NO, KC_NO, R61, KC_NO, R63, KC_NO, R65, R66, KC_NO, R68, R69, R6A, R6B }, \
57}
58#endif
diff --git a/keyboards/nek_type_a/readme.md b/keyboards/nek_type_a/readme.md
new file mode 100644
index 000000000..49f4a4659
--- /dev/null
+++ b/keyboards/nek_type_a/readme.md
@@ -0,0 +1,30 @@
1# nek_type_a
2
3![NEK Type A Keyboard](https://i.imgur.com/XFnjlQ9.jpg)
4
5Natural Ergonomic Keyboard, Type A
6
7Keyboard Maintainer: [Mike Roberts](https://github.com/ecopoesis)
8Hardware Supported: Custom PCBs from https://github.com/ecopoesis/nek-type-a
9Hardware Availability: https://github.com/ecopoesis/nek-type-a
10
11## Design
12
13This is a column-driven split keyboard using three custom PCBs connected with ribbon cables. The left and right PCBs are
14passive: they only have the diodes and switches needed to make the matrix. The center PCB has an Adafruit Feather 32u4 and
15MCP23017 expander.
16
17The left matrix has its rows and columns directly connected to the Feather. The right matrix has its rows connect to the
18Feather (using the same pins as the left matrix) and its columns connected to the expander. The expander uses the LUFA
19hardware TWI driver.
20
21Bluetooth is enabled.
22
23## Building
24
25Make and install this keyboard (after setting up your build environment):
26```
27make nek_type_a:default:avrdude
28```
29
30See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
diff --git a/keyboards/nek_type_a/rules.mk b/keyboards/nek_type_a/rules.mk
new file mode 100644
index 000000000..6f172a9ce
--- /dev/null
+++ b/keyboards/nek_type_a/rules.mk
@@ -0,0 +1,33 @@
1SRC = matrix.c mcp23017.c
2
3MCU = atmega32u4
4F_CPU = 8000000
5
6ARCH = AVR8
7F_USB = $(F_CPU)
8
9# Interrupt driven control endpoint task(+60)
10OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
11
12BOOTLOADER = caterina
13
14BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
15MOUSEKEY_ENABLE = no # Mouse keys(+4700)
16EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
17CONSOLE_ENABLE = yes # Console for debug(+400)
18COMMAND_ENABLE = yes # Commands for debug and configuration
19# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
20SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
21# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
22NKRO_ENABLE = no # USB Nkey Rollover
23BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default
24RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
25MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config)
26UNICODE_ENABLE = no # Unicode
27BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
28AUDIO_ENABLE = no # Audio output on port C6
29FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
30HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
31CUSTOM_MATRIX = yes
32DEBUG_ENABLE = yes
33BLUETOOTH = AdafruitBLE \ No newline at end of file