aboutsummaryrefslogtreecommitdiff
path: root/keyboards
diff options
context:
space:
mode:
authorJeremy Bernhardt <jeremythegeek@gmail.com>2019-03-29 11:39:28 -0600
committerDrashna Jaelre <drashna@live.com>2019-03-29 10:39:28 -0700
commit8fa9f67256772984110a6e21f19d6fb8594b804d (patch)
tree53c5ac04dd72031800e3aaba707ce66d5748cd3d /keyboards
parent3f4d706c98fc3a7f5fcec6ed0b62291b4159f097 (diff)
downloadqmk_firmware-8fa9f67256772984110a6e21f19d6fb8594b804d.tar.gz
qmk_firmware-8fa9f67256772984110a6e21f19d6fb8594b804d.zip
[Keyboard] ErgoTaco Support (#5504)
* ErgoTaco support * Update keyboards/ergotaco/ergotaco.h Co-Authored-By: germ <jeremythegeek@gmail.com> * Update keyboards/ergotaco/keymaps/default/keymap.c Co-Authored-By: germ <jeremythegeek@gmail.com> * Update keyboards/ergotaco/keymaps/default/keymap.c Co-Authored-By: germ <jeremythegeek@gmail.com> * Update keyboards/ergotaco/readme.md Co-Authored-By: germ <jeremythegeek@gmail.com> * Update keyboards/ergotaco/readme.md Co-Authored-By: germ <jeremythegeek@gmail.com> * Update keyboards/ergotaco/rules.mk Co-Authored-By: germ <jeremythegeek@gmail.com> * juggling rules.mk * Update keyboards/ergotaco/rules.mk Co-Authored-By: germ <jeremythegeek@gmail.com> * updating IS_COMMAND * learning2english Meme-tastic --Drashna
Diffstat (limited to 'keyboards')
-rw-r--r--keyboards/ergotaco/config.h61
-rw-r--r--keyboards/ergotaco/ergotaco.c72
-rw-r--r--keyboards/ergotaco/ergotaco.h50
-rw-r--r--keyboards/ergotaco/info.json61
-rw-r--r--keyboards/ergotaco/keymaps/default/keymap.c42
-rw-r--r--keyboards/ergotaco/keymaps/default/readme.md6
-rw-r--r--keyboards/ergotaco/keymaps/default/rules.mk10
-rw-r--r--keyboards/ergotaco/matrix.c366
-rw-r--r--keyboards/ergotaco/readme.md24
-rw-r--r--keyboards/ergotaco/rules.mk26
10 files changed, 718 insertions, 0 deletions
diff --git a/keyboards/ergotaco/config.h b/keyboards/ergotaco/config.h
new file mode 100644
index 000000000..4dbe0573b
--- /dev/null
+++ b/keyboards/ergotaco/config.h
@@ -0,0 +1,61 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
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// Copy and worked on with love from the EZ team
20
21#pragma once
22#include "config_common.h"
23
24#define VERBOSE
25
26/* USB Device descriptor parameter */
27#define VENDOR_ID 0xFEED
28#define PRODUCT_ID 0x1337
29#define DEVICE_VER 0x0001
30#define MANUFACTURER g Heavy Industries
31#define PRODUCT ErgoTaco
32#define DESCRIPTION QMK keyboard firmware for ErgoTaco
33
34/* key matrix size */
35#define MATRIX_ROWS 12
36#define MATRIX_ROWS_PER_SIDE (MATRIX_ROWS / 2)
37#define MATRIX_COLS 1
38
39#define MOUSEKEY_INTERVAL 20
40#define MOUSEKEY_DELAY 0
41#define MOUSEKEY_TIME_TO_MAX 60
42#define MOUSEKEY_MAX_SPEED 7
43#define MOUSEKEY_WHEEL_DELAY 0
44#define TAPPING_TOGGLE 1
45
46/* define if matrix has ghost */
47//#define MATRIX_HAS_GHOST
48
49#define TAPPING_TERM 200
50#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
51
52/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
53#define LOCKING_SUPPORT_ENABLE
54/* Locking resynchronize hack */
55#define LOCKING_RESYNC_ENABLE
56
57/* key combination for command */
58#define IS_COMMAND() (get_mods() == MOD_MASK_CTRL || get_mods() == MOD_MASK_SHIFT)
59
60#define DEBOUNCE 5
61#define USB_MAX_POWER_CONSUMPTION 500
diff --git a/keyboards/ergotaco/ergotaco.c b/keyboards/ergotaco/ergotaco.c
new file mode 100644
index 000000000..ecab74b3a
--- /dev/null
+++ b/keyboards/ergotaco/ergotaco.c
@@ -0,0 +1,72 @@
1#include QMK_KEYBOARD_H
2
3bool i2c_initialized = 0;
4i2c_status_t mcp23018_status = 0x20;
5
6void matrix_init_kb(void) {
7 // (tied to Vcc for hardware convenience)
8 //DDRB &= ~(1<<4); // set B(4) as input
9 //PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
10
11 // unused pins
12 // set as input with internal pull-up enabled
13 DDRB &= ~(1<<4 | 1<<5 | 1<<6 | 1<<7);
14 PORTB |= (1<<4 | 1<<5 | 1<<6 | 1<<7);
15
16 DDRC &= ~(1<<7 | 1<<6);
17 PORTC |= (1<<7 | 1<<6);
18
19 DDRD &= ~(1<<4 | 1<<5 | 1<<6 | 1<<7);
20 PORTD |= (1<<4 | 1<<5 | 1<<6 | 1<<7);
21
22 DDRE &= ~(1<<6);
23 PORTE |= (1<<6);
24
25 DDRF &= ~(1<<0 | 1<<1 | 1<<4 | 1<<6 | 1<<7);
26 PORTF |= (1<<0 | 1<<1 | 1<<4 | 1<<6 | 1<<7);
27
28 matrix_init_user();
29}
30
31
32uint8_t init_mcp23018(void) {
33 print("starting init");
34 mcp23018_status = 0x20;
35
36 // I2C subsystem
37
38 // uint8_t sreg_prev;
39 // sreg_prev=SREG;
40 // cli();
41
42 if (i2c_initialized == 0) {
43 i2c_init(); // on pins D(1,0)
44 i2c_initialized = true;
45 _delay_ms(1000);
46 }
47
48 // set pin direction
49 // - unused : input : 1
50 // - input : input : 1
51 // - driving : output : 0
52 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
53 mcp23018_status = i2c_write(IODIRA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
54 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
55 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
56 i2c_stop();
57
58 // set pull-up
59 // - unused : on : 1
60 // - input : on : 1
61 // - driving : off : 0
62 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
63 mcp23018_status = i2c_write(GPPUA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
64 mcp23018_status = i2c_write(0b00000000, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
65 mcp23018_status = i2c_write(0b11111111, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
66
67out:
68 i2c_stop();
69 // SREG=sreg_prev;
70 //uprintf("Init %x\n", mcp23018_status);
71 return mcp23018_status;
72}
diff --git a/keyboards/ergotaco/ergotaco.h b/keyboards/ergotaco/ergotaco.h
new file mode 100644
index 000000000..6bc5ce36f
--- /dev/null
+++ b/keyboards/ergotaco/ergotaco.h
@@ -0,0 +1,50 @@
1#pragma once
2#include <util/delay.h>
3#include <stdint.h>
4#include <stdbool.h>
5#include "quantum.h"
6#include "i2c_master.h"
7#include "matrix.h"
8
9
10extern i2c_status_t mcp23018_status;
11#define ERGODOX_EZ_I2C_TIMEOUT 1000
12#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
13#define CPU_16MHz 0x00
14
15// I2C aliases and register addresses (see "mcp23018.md")
16//#define I2C_ADDR 0b0100000
17#define I2C_ADDR 0x20
18#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
19#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
20#define IODIRA 0x00 // i/o direction register
21#define IODIRB 0x01
22#define GPPUA 0x0C // GPIO pull-up resistor register
23#define GPPUB 0x0D
24#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
25#define GPIOB 0x13
26#define OLATA 0x14 // output latch register
27#define OLATB 0x15
28
29void init_ergodox(void);
30uint8_t init_mcp23018(void);
31
32/* ---------- LEFT HAND ----------- ---------- RIGHT HAND ---------- */
33#define LAYOUT( \
34 L00,L01,L02,L03,L04,L05, R00,R01,R02,R03,R04,R05) \
35 \
36 /* matrix positions */ \
37 { \
38 {R00}, \
39 {R01}, \
40 {R02}, \
41 {R03}, \
42 {R04}, \
43 {R05}, \
44 {L05}, \
45 {L04}, \
46 {L03}, \
47 {L02}, \
48 {L01}, \
49 {L00}, \
50}
diff --git a/keyboards/ergotaco/info.json b/keyboards/ergotaco/info.json
new file mode 100644
index 000000000..cf6b810fe
--- /dev/null
+++ b/keyboards/ergotaco/info.json
@@ -0,0 +1,61 @@
1{
2 "keyboard_name": "ErgoTaco",
3 "url": "http://gboards.ca",
4 "maintainer": "germ",
5 "width": 13,
6 "height": 2.75,
7 "layouts": {
8 "LAYOUT": {
9 "layout": [
10 {
11 "x": 0,
12 "y": 1.25
13 },
14 {
15 "x": 1,
16 "y": 0.75
17 },
18 {
19 "x": 2,
20 "y": 0.5
21 },
22 {
23 "x": 3,
24 "y": 0.25
25 },
26 {
27 "x": 4,
28 "y": 1
29 },
30 {
31 "x": 5,
32 "y": 1.75
33 },
34 {
35 "x": 7,
36 "y": 1.75
37 },
38 {
39 "x": 8,
40 "y": 1
41 },
42 {
43 "x": 9,
44 "y": 0.25
45 },
46 {
47 "x": 10,
48 "y": 0.5
49 },
50 {
51 "x": 11,
52 "y": 0.75
53 },
54 {
55 "x": 12,
56 "y": 1.25
57 }
58 ]
59 }
60 }
61}
diff --git a/keyboards/ergotaco/keymaps/default/keymap.c b/keyboards/ergotaco/keymaps/default/keymap.c
new file mode 100644
index 000000000..be1267ef0
--- /dev/null
+++ b/keyboards/ergotaco/keymaps/default/keymap.c
@@ -0,0 +1,42 @@
1/* Good on you for modifying your layout! if you don't have
2 * time to read the QMK docs, a list of keycodes can be found at
3 *
4 * https://github.com/qmk/qmk_firmware/blob/master/docs/keycodes.md
5 *
6 * There's also a template for adding new layers at the bottom of this file!
7 */
8
9#include QMK_KEYBOARD_H
10
11#define FIESTA 0 // default layer
12#define TACOTIME 1 // symbols
13
14// Blank template at the bottom
15const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
16/* Keymap template
17 *
18 * ,-------------------------------------------------. ,--------------------------------------------.
19 * | | | | | | | | | | | | | | |
20 * `-------+------+------+------+------+-------------' `-------+------+------+------+------+--------' */
21[FIESTA] = LAYOUT(
22 KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H
23),
24};
25
26/* Keymap template
27 *
28 * ,-------------------------------------------------. ,--------------------------------------------.
29 * | | | | | | | | | | | | | | |
30 * `-------+------+------+------+------+-------------' `-------+------+------+------+------+--------'
31[FIESTA] = LAYOUT(
32 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
33),
34 */
35
36// Runs just one time when the keyboard initializes.
37void matrix_init_user(void) {
38};
39
40// Runs constantly in the background, in a loop.
41void matrix_scan_user(void) {
42};
diff --git a/keyboards/ergotaco/keymaps/default/readme.md b/keyboards/ergotaco/keymaps/default/readme.md
new file mode 100644
index 000000000..653f3774e
--- /dev/null
+++ b/keyboards/ergotaco/keymaps/default/readme.md
@@ -0,0 +1,6 @@
1This is the default keymap for the ErgoTaco, Make it your own!
2
3## Settings
4To edit various settings, enable the 1u trackball and whatnot please modify /keyboards/ergotaco/keymaps/default/rules.mk
5
6Ideally you should copy this directory and make your changes there. If you come up with a good layout submit a PR!
diff --git a/keyboards/ergotaco/keymaps/default/rules.mk b/keyboards/ergotaco/keymaps/default/rules.mk
new file mode 100644
index 000000000..e394fbf1e
--- /dev/null
+++ b/keyboards/ergotaco/keymaps/default/rules.mk
@@ -0,0 +1,10 @@
1#----------------------------------------------------------------------------
2# make ergotaco:default:dfu
3# Make sure you have dfu-programmer installed!
4#----------------------------------------------------------------------------
5# Firmware options
6
7#Debug options
8VERBOSE = yes
9DEBUG_MATRIX_SCAN_RATE = no
10DEBUG_MATRIX = yes
diff --git a/keyboards/ergotaco/matrix.c b/keyboards/ergotaco/matrix.c
new file mode 100644
index 000000000..e4fd6902f
--- /dev/null
+++ b/keyboards/ergotaco/matrix.c
@@ -0,0 +1,366 @@
1/*
2Note for ErgoDox EZ customizers: Here be dragons!
3This is not a file you want to be messing with.
4All of the interesting stuff for you is under keymaps/ :)
5Love, Erez
6
7Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
8
9This program is free software: you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation, either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "matrix.h"
24#include <stdint.h>
25#include <stdbool.h>
26#include <avr/io.h>
27#include "wait.h"
28#include "action_layer.h"
29#include "print.h"
30#include "debug.h"
31#include "util.h"
32#include QMK_KEYBOARD_H
33#ifdef DEBUG_MATRIX_SCAN_RATE
34#include "timer.h"
35#endif
36
37#ifndef DEBOUNCE
38# define DEBOUNCE 5
39#endif
40
41// ATmega pin defs
42#define ROW1 (1<<5)
43#define COL6 (1<<0)
44#define COL7 (1<<1)
45#define COL8 (1<<2)
46#define COL9 (1<<3)
47#define COL10 (1<<2)
48#define COL11 (1<<3)
49
50
51// bit masks
52#define BMASK (COL7 | COL8 | COL9 | COL6)
53#define DMASK (COL10 | COL11)
54#define FMASK (ROW1)
55
56/* matrix state(1:on, 0:off) */
57static matrix_row_t matrix[MATRIX_ROWS];
58/*
59 * matrix state(1:on, 0:off)
60 * contains the raw values without debounce filtering of the last read cycle.
61 */
62static matrix_row_t raw_matrix[MATRIX_ROWS];
63
64// Debouncing: store for each key the number of scans until it's eligible to
65// change. When scanning the matrix, ignore any changes in keys that have
66// already changed in the last DEBOUNCE scans.
67static uint8_t debounce_matrix[MATRIX_ROWS * MATRIX_COLS];
68
69static matrix_row_t read_cols(uint8_t row);
70static void init_cols(void);
71static void unselect_rows(void);
72static void select_row(uint8_t row);
73
74static uint8_t mcp23018_reset_loop;
75// static uint16_t mcp23018_reset_loop;
76
77#ifdef DEBUG_MATRIX_SCAN_RATE
78uint32_t matrix_timer;
79uint32_t matrix_scan_count;
80#endif
81
82
83__attribute__ ((weak))
84void matrix_init_user(void) {}
85
86__attribute__ ((weak))
87void matrix_scan_user(void) {}
88
89__attribute__ ((weak))
90void matrix_init_kb(void) {
91 matrix_init_user();
92}
93
94__attribute__ ((weak))
95void matrix_scan_kb(void) {
96 matrix_scan_user();
97}
98
99inline
100uint8_t matrix_rows(void)
101{
102 return MATRIX_ROWS;
103}
104
105inline
106uint8_t matrix_cols(void)
107{
108 return MATRIX_COLS;
109}
110
111
112void matrix_init(void)
113{
114 // initialize row and col
115 mcp23018_status = init_mcp23018();
116 unselect_rows();
117 init_cols();
118
119 // initialize matrix state: all keys off
120 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
121 matrix[i] = 0;
122 raw_matrix[i] = 0;
123 for (uint8_t j=0; j < MATRIX_COLS; ++j) {
124 debounce_matrix[i * MATRIX_COLS + j] = 0;
125 }
126 }
127
128#ifdef DEBUG_MATRIX_SCAN_RATE
129 matrix_timer = timer_read32();
130 matrix_scan_count = 0;
131#endif
132 matrix_init_quantum();
133}
134
135void matrix_power_up(void) {
136 mcp23018_status = init_mcp23018();
137
138 unselect_rows();
139 init_cols();
140
141 // initialize matrix state: all keys off
142 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
143 matrix[i] = 0;
144 }
145
146#ifdef DEBUG_MATRIX_SCAN_RATE
147 matrix_timer = timer_read32();
148 matrix_scan_count = 0;
149#endif
150
151}
152
153// Returns a matrix_row_t whose bits are set if the corresponding key should be
154// eligible to change in this scan.
155matrix_row_t debounce_mask(matrix_row_t rawcols, uint8_t row) {
156 matrix_row_t result = 0;
157 matrix_row_t change = rawcols ^ raw_matrix[row];
158 raw_matrix[row] = rawcols;
159 for (uint8_t i = 0; i < MATRIX_COLS; ++i) {
160 if (debounce_matrix[row * MATRIX_COLS + i]) {
161 --debounce_matrix[row * MATRIX_COLS + i];
162 } else {
163 result |= (1 << i);
164 }
165 if (change & (1 << i)) {
166 debounce_matrix[row * MATRIX_COLS + i] = DEBOUNCE;
167 }
168 }
169 return result;
170}
171
172matrix_row_t debounce_read_cols(uint8_t row) {
173 // Read the row without debouncing filtering and store it for later usage.
174 matrix_row_t cols = read_cols(row);
175 // Get the Debounce mask.
176 matrix_row_t mask = debounce_mask(cols, row);
177 // debounce the row and return the result.
178 return (cols & mask) | (matrix[row] & ~mask);;
179}
180
181uint8_t matrix_scan(void)
182{
183 // Then the keyboard
184 if (mcp23018_status) { // if there was an error
185 if (++mcp23018_reset_loop == 0) {
186 // if (++mcp23018_reset_loop >= 1300) {
187 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
188 // this will be approx bit more frequent than once per second
189 print("trying to reset mcp23018\n");
190 mcp23018_status = init_mcp23018();
191 if (mcp23018_status) {
192 print("left side not responding\n");
193 } else {
194 print("left side attached\n");
195 }
196 }
197 }
198
199#ifdef DEBUG_MATRIX_SCAN_RATE
200 matrix_scan_count++;
201 uint32_t timer_now = timer_read32();
202 if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
203 print("matrix scan frequency: ");
204 pdec(matrix_scan_count);
205 print("\n");
206
207 matrix_timer = timer_now;
208 matrix_scan_count = 0;
209 }
210#endif
211 for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
212 select_row(i);
213 // and select on left hand
214 select_row(i + MATRIX_ROWS_PER_SIDE);
215 // we don't need a 30us delay anymore, because selecting a
216 // left-hand row requires more than 30us for i2c.
217
218 // grab cols from left hand
219 matrix[i] = debounce_read_cols(i);
220 // grab cols from right hand
221 matrix[i + MATRIX_ROWS_PER_SIDE] = debounce_read_cols(i + MATRIX_ROWS_PER_SIDE);
222
223 unselect_rows();
224 }
225
226 matrix_scan_quantum();
227
228#ifdef DEBUG_MATRIX
229 for (uint8_t c = 0; c < MATRIX_COLS; c++)
230 for (uint8_t r = 0; r < MATRIX_ROWS; r++)
231 if (matrix_is_on(r, c)) xprintf("r:%d c:%d \n", r, c);
232#endif
233
234 return 1;
235}
236
237bool matrix_is_modified(void) // deprecated and evidently not called.
238{
239 return true;
240}
241
242inline
243bool matrix_is_on(uint8_t row, uint8_t col)
244{
245 return (matrix[row] & ((matrix_row_t)1<<col));
246}
247
248inline
249matrix_row_t matrix_get_row(uint8_t row)
250{
251 return matrix[row];
252}
253
254void matrix_print(void)
255{
256 print("\nr/c 0123456789ABCDEF\n");
257 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
258 phex(row); print(": ");
259 pbin_reverse16(matrix_get_row(row));
260 print("\n");
261 }
262}
263
264uint8_t matrix_key_count(void)
265{
266 uint8_t count = 0;
267 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
268 count += bitpop16(matrix[i]);
269 }
270 return count;
271}
272
273// Remember this means ROWS
274static void init_cols(void)
275{
276 // init on mcp23018
277 // not needed, already done as part of init_mcp23018()
278
279 // Input with pull-up(DDR:0, PORT:1)
280 DDRF &= ~FMASK;
281 PORTF |= FMASK;
282}
283
284static matrix_row_t read_cols(uint8_t row)
285{
286 if (row < 6) {
287 if (mcp23018_status) { // if there was an error
288 return 0;
289 } else {
290 uint8_t data = 0;
291 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
292 mcp23018_status = i2c_write(GPIOB, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
293 mcp23018_status = i2c_start(I2C_ADDR_READ, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
294 mcp23018_status = i2c_read_nack(ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status < 0) goto out;
295 data = (~((uint8_t)mcp23018_status) >> 2) & 0x01 ;
296 mcp23018_status = I2C_STATUS_SUCCESS;
297 out:
298 i2c_stop();
299
300#ifdef DEBUG_MATRIX
301 if (data != 0x00) xprintf("I2C: %d\n", data);
302#endif
303 return data;
304 }
305 } else {
306 // Read using bitmask
307 return ~((((PINF & ROW1) >> 5)) & 0x1);
308 }
309}
310
311// Row pin configuration
312static void unselect_rows(void)
313{
314 // no need to unselect on mcp23018, because the select step sets all
315 // the other row bits high, and it's not changing to a different
316 // direction
317 // Hi-Z(DDR:0, PORT:0) to unselect
318 DDRB &= ~BMASK;
319 PORTB &= ~BMASK;
320 DDRD &= ~DMASK;
321 PORTD &= ~DMASK;
322}
323
324static void select_row(uint8_t row)
325{
326 if (row < 6) {
327 // select on mcp23018
328 if (mcp23018_status) { // do nothing on error
329 // Read using bitmask
330 } else { // set active row low : 0 // set other rows hi-Z : 1
331 mcp23018_status = i2c_start(I2C_ADDR_WRITE, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
332 mcp23018_status = i2c_write(GPIOA, ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
333 mcp23018_status = i2c_write(~(1<<row), ERGODOX_EZ_I2C_TIMEOUT); if (mcp23018_status) goto out;
334 out:
335 i2c_stop();
336 }
337 } else {
338 // Output low(DDR:1, PORT:0) to select
339 switch (row) {
340 case 6:
341 DDRB |= COL6;
342 PORTB &= ~COL6;
343 break;
344 case 7:
345 DDRB |= COL7;
346 PORTB &= ~COL7;
347 break;
348 case 8:
349 DDRB |= COL8;
350 PORTB &= ~COL8;
351 break;
352 case 9:
353 DDRB |= COL9;
354 PORTB &= ~COL9;
355 break;
356 case 10:
357 DDRD |= COL10;
358 PORTD &= ~COL10;
359 break;
360 case 11:
361 DDRD |= COL11;
362 PORTD &= ~COL11;
363 break;
364 }
365 }
366}
diff --git a/keyboards/ergotaco/readme.md b/keyboards/ergotaco/readme.md
new file mode 100644
index 000000000..3021168db
--- /dev/null
+++ b/keyboards/ergotaco/readme.md
@@ -0,0 +1,24 @@
1# Gergo
2
3![ErgoTaco](https://i.redd.it/dbcu5i21m3i21.jpg)
4
5It's a Taco with a side of HASL. A 12 key fiesta of a board.
6
7Keyboard Maintainer: [Jeremy Bernhardt](https://github.com/germ)
8Hardware Supported: ErgoTaco
9Hardware Availability: [gboards.ca](http://gboards.ca)
10
11## Firmware building
12Clone the QMK Repo and install dfu-programmer, flash with:
13
14 make ergotaco:default:dfu
15
16And reset your keyboard!
17
18To just test if your build system is sane, try compiling the default keymap using:
19
20 make ergotaco:default
21
22See 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).
23
24## Have an idea? [Reach out to me!](mailto:bernhardtjeremy@gmail.com)
diff --git a/keyboards/ergotaco/rules.mk b/keyboards/ergotaco/rules.mk
new file mode 100644
index 000000000..0af3e3474
--- /dev/null
+++ b/keyboards/ergotaco/rules.mk
@@ -0,0 +1,26 @@
1#----------------------------------------------------------------------------
2# make ergotaco:default:dfu
3# Make sure you have dfu-programmer installed!
4# Do not edit this file! Make a copy of keymaps/default and modify that!
5#----------------------------------------------------------------------------
6
7# Hardware info
8MCU = atmega32u4
9F_CPU = 16000000
10ARCH = AVR8
11BOOTLOADER = atmel-dfu
12F_USB = $(F_CPU)
13
14CUSTOM_MATRIX = yes
15EXTRAKEY_ENABLE = yes
16CONSOLE_ENABLE = yes
17COMMAND_ENABLE = yes
18
19# A bunch of stuff that you shouldn't touch unless you
20# know what you're doing.
21#
22# No touchy, capiche?
23SRC += matrix.c i2c_master.c
24ifeq ($(strip $(DEBUG_MATRIX)), yes)
25 OPT_DEFS += -DDEBUG_MATRIX
26endif