aboutsummaryrefslogtreecommitdiff
path: root/keyboards/dichotomy
diff options
context:
space:
mode:
authorSnipeye <Snipeye@gmail.com>2018-12-05 19:31:21 -0700
committerDrashna Jaelre <drashna@live.com>2018-12-05 18:31:21 -0800
commit57678238a9f7023b3e0ba03bd9a61f6a7c309f9d (patch)
treec4f5aee61f4ca84a5f355d42c13b82bcd6fc35ea /keyboards/dichotomy
parent8ad561c8f091a4baf167ad4d7c90c02383905e38 (diff)
downloadqmk_firmware-57678238a9f7023b3e0ba03bd9a61f6a7c309f9d.tar.gz
qmk_firmware-57678238a9f7023b3e0ba03bd9a61f6a7c309f9d.zip
Keyboard: Fixing spelling, updating code, finalizing keymap for Dichotomy (#4539)
* Fixing spelling, updating code, finalizing keymap for Dichotomy * Fixing requested changes in PR * Further PR-requested changes for convention * Making macros functionable, removing unecessary defs * Fixing keymap to properly use previously-changed macros
Diffstat (limited to 'keyboards/dichotomy')
-rwxr-xr-xkeyboards/dichotomy/config.h85
-rwxr-xr-xkeyboards/dichotomy/dichotomy.c89
-rwxr-xr-xkeyboards/dichotomy/dichotomy.h46
-rw-r--r--keyboards/dichotomy/info.json12
-rwxr-xr-xkeyboards/dichotomy/keymaps/default/keymap.c506
-rwxr-xr-xkeyboards/dichotomy/matrix.c228
-rwxr-xr-xkeyboards/dichotomy/readme.md33
-rwxr-xr-xkeyboards/dichotomy/rules.mk77
8 files changed, 1076 insertions, 0 deletions
diff --git a/keyboards/dichotomy/config.h b/keyboards/dichotomy/config.h
new file mode 100755
index 000000000..f0847ec52
--- /dev/null
+++ b/keyboards/dichotomy/config.h
@@ -0,0 +1,85 @@
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#ifndef CONFIG_H
19#define CONFIG_H
20
21#include "config_common.h"
22
23/* USB Device descriptor parameter */
24
25#define VENDOR_ID 0xFEED
26#define PRODUCT_ID 0xACC7
27#define DEVICE_VER 0x0002
28#define MANUFACTURER Broekhuijsen
29#define PRODUCT Dichotomy
30#define DESCRIPTION q.m.k. keyboard firmware for Dichotomy
31
32/* key matrix size */
33#define MATRIX_ROWS 5
34#define MATRIX_COLS 12
35
36/* define if matrix has ghost */
37//#define MATRIX_HAS_GHOST
38
39/* number of backlight levels */
40//#define BACKLIGHT_LEVELS 3
41
42#define ONESHOT_TIMEOUT 500
43
44
45/* key combination for command */
46#define IS_COMMAND() ( \
47 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
48)
49
50/*
51 * Feature disable options
52 * These options are also useful to firmware size reduction.
53 */
54
55/* disable debug print */
56//#define NO_DEBUG
57
58/* disable print */
59//#define NO_PRINT
60
61/* disable action features */
62//#define NO_ACTION_LAYER
63//#define NO_ACTION_TAPPING
64//#define NO_ACTION_ONESHOT
65//#define NO_ACTION_MACRO
66//#define NO_ACTION_FUNCTION
67
68//UART settings for communication with the RF microcontroller
69#define SERIAL_UART_BAUD 1000000
70#define SERIAL_UART_DATA UDR1
71#define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
72#define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
73#define SERIAL_UART_RXD_PRESENT (UCSR1A & _BV(RXC1))
74#define SERIAL_UART_INIT() do { \
75 /* baud rate */ \
76 UBRR1L = SERIAL_UART_UBRR; \
77 /* baud rate */ \
78 UBRR1H = SERIAL_UART_UBRR >> 8; \
79 /* enable TX and RX */ \
80 UCSR1B = _BV(TXEN1) | _BV(RXEN1); \
81 /* 8-bit data */ \
82 UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
83 } while(0)
84
85#endif
diff --git a/keyboards/dichotomy/dichotomy.c b/keyboards/dichotomy/dichotomy.c
new file mode 100755
index 000000000..41e12090c
--- /dev/null
+++ b/keyboards/dichotomy/dichotomy.c
@@ -0,0 +1,89 @@
1#include "dichotomy.h"
2
3void uart_init(void) {
4 SERIAL_UART_INIT();
5}
6
7void pointing_device_task(void){
8 /*report_mouse_t currentReport = {};
9 SERIAL_UART_INIT();
10 uint32_t timeout = 0;
11
12 //the m character requests the RF slave to send the mouse report
13 SERIAL_UART_DATA = 'm';
14
15 //trust the external inputs completely, erase old data
16 uint8_t uart_data[5] = {0};
17
18 //there are 10 bytes corresponding to 10 columns, and an end byte
19 for (uint8_t i = 0; i < 5; i++) {
20 //wait for the serial data, timeout if it's been too long
21 //this only happened in testing with a loose wire, but does no
22 //harm to leave it in here
23 while(!SERIAL_UART_RXD_PRESENT){
24 timeout++;
25 if (timeout > 10000){
26 xprintf("\r\nTIMED OUT");
27 break;
28 }
29 }
30 xprintf("\r\nGOT DATA for %d",i);
31 uart_data[i] = SERIAL_UART_DATA;
32 }
33
34 //check for the end packet, bytes 1-4 are movement and scroll
35 //but byte 5 has bits 0-3 for the scroll button state
36 //(1000 if pressed, 0000 if not) and bits 4-7 are always 1
37 //We can use this to verify the report sent properly.
38 if (uart_data[4] == 0x0F || uart_data[4] == 0x8F)
39 {
40 xprintf("\r\nREQUESTED MOUSE, RECEIVED %i, %i, %i, %i, %i",uart_data[0],uart_data[1],uart_data[2],uart_data[3],uart_data[4]);
41 currentReport = pointing_device_get_report();
42 //shifting and transferring the info to the mouse report varaible
43 //mouseReport.x = 127 max -127 min
44 currentReport.x = (int8_t) uart_data[0];
45 //mouseReport.y = 127 max -127 min
46 currentReport.y = (int8_t) uart_data[1];
47 //mouseReport.v = 127 max -127 min (scroll vertical)
48 currentReport.v = (int8_t) uart_data[2];
49 //mouseReport.h = 127 max -127 min (scroll horizontal)
50 currentReport.h = (int8_t) uart_data[3];
51 //mouseReport.buttons = 0x31 max (bitmask for mouse buttons 1-5) 0x00 min
52 //mouse buttons 1 and 2 are handled by the keymap, but not 3
53 if (uart_data[4] == 0x0F) { //then 3 is not pressed
54 currentReport.buttons &= ~MOUSE_BTN3; //MOUSE_BTN3 is def in report.h
55 } else { //3 must be pressed
56 currentReport.buttons |= MOUSE_BTN3;
57 }
58 pointing_device_set_report(currentReport);
59 } else {
60 xprintf("\r\nRequested packet, data 4 was %d",uart_data[4]);
61 }*/
62 pointing_device_send();
63}
64
65void led_init(void) {
66 DDRD |= (1<<1);
67 PORTD |= (1<<1);
68 DDRF |= (1<<4) | (1<<5);
69 PORTF |= (1<<4) | (1<<5);
70}
71
72
73void matrix_init_kb(void) {
74 // put your keyboard start-up code here
75 // runs once when the firmware starts up
76 matrix_init_user();
77 uart_init();
78 led_init();
79}
80
81void matrix_scan_kb(void) {
82 // put your looping keyboard code here
83 // runs every cycle (a lot)
84 matrix_scan_user();
85}
86
87void led_set_kb(uint8_t usb_led) {
88
89}
diff --git a/keyboards/dichotomy/dichotomy.h b/keyboards/dichotomy/dichotomy.h
new file mode 100755
index 000000000..030209ff0
--- /dev/null
+++ b/keyboards/dichotomy/dichotomy.h
@@ -0,0 +1,46 @@
1#ifndef DICHOTOMY_H
2#define DICHOTOMY_H
3
4#include QMK_KEYBOARD_H
5#include "report.h"
6#include "pointing_device.h"
7#include "quantum.h"
8#include "matrix.h"
9#include "backlight.h"
10#include <stddef.h>
11
12#define red_led_off() PORTF |= (1<<6)
13#define red_led_on() PORTF &= ~(1<<6)
14#define blu_led_off() PORTF |= (1<<5)
15#define blu_led_on() PORTF &= ~(1<<5)
16#define grn_led_off() PORTD |= (1<<1)
17#define grn_led_on() PORTD &= ~(1<<1)
18
19#define set_led_off() red_led_off(); grn_led_off(); blu_led_off()
20#define set_led_red() red_led_on(); grn_led_off(); blu_led_off()
21#define set_led_blue() red_led_off(); grn_led_off(); blu_led_on()
22#define set_led_green() red_led_off(); grn_led_on(); blu_led_off()
23#define set_led_yellow() red_led_on(); grn_led_on(); blu_led_off()
24#define set_led_magenta() red_led_on(); grn_led_off(); blu_led_on()
25#define set_led_cyan() red_led_off(); grn_led_on(); blu_led_on()
26#define set_led_white() red_led_on(); grn_led_on(); blu_led_on()
27
28// This a shortcut to help you visually see your layout.
29// The first section contains all of the arguements
30// The second converts the arguments into a two-dimensional array
31#define LAYOUT( \
32 k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B, \
33 k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B, \
34 k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B, \
35 k33, k34, k35, k36, k37, k38, \
36 k42, k43, k44, k45, k46, k47, k48, k49 \
37) \
38{ \
39 { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B }, \
40 { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B }, \
41 { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B }, \
42 { KC_NO, KC_NO, KC_NO, k33, k34, k35, k36, k37, k38, KC_NO, KC_NO, KC_NO }, \
43 { KC_NO, KC_NO, k42, k43, k44, k45, k46, k47, k48, k49, KC_NO, KC_NO } \
44}
45
46#endif
diff --git a/keyboards/dichotomy/info.json b/keyboards/dichotomy/info.json
new file mode 100644
index 000000000..aeb00edce
--- /dev/null
+++ b/keyboards/dichotomy/info.json
@@ -0,0 +1,12 @@
1{
2 "keyboard_name": "Dichotomy",
3 "url": "",
4 "maintainer": "qmk",
5 "width": 13,
6 "height": 6,
7 "layouts": {
8 "LAYOUT": {
9 "layout": [{"label":"k00", "x":0, "y":0.5}, {"label":"k01", "x":1, "y":0.5}, {"label":"k02", "x":2, "y":0.25}, {"label":"k03", "x":3, "y":0}, {"label":"k04", "x":4, "y":0.5}, {"label":"k05", "x":5, "y":0.5}, {"label":"k06", "x":7, "y":0.5}, {"label":"k07", "x":8, "y":0.5}, {"label":"k08", "x":9, "y":0}, {"label":"k09", "x":10, "y":0.25}, {"label":"k0A", "x":11, "y":0.5}, {"label":"k0B", "x":12, "y":0.5}, {"label":"k10", "x":0, "y":1.5}, {"label":"k11", "x":1, "y":1.5}, {"label":"k12", "x":2, "y":1.25}, {"label":"k13", "x":3, "y":1}, {"label":"k14", "x":4, "y":1.5}, {"label":"k15", "x":5, "y":1.5}, {"label":"k16", "x":7, "y":1.5}, {"label":"k17", "x":8, "y":1.5}, {"label":"k18", "x":9, "y":1}, {"label":"k19", "x":10, "y":1.25}, {"label":"k1A", "x":11, "y":1.5}, {"label":"k1B", "x":12, "y":1.5}, {"label":"k20", "x":0, "y":2.5}, {"label":"k21", "x":1, "y":2.5}, {"label":"k22", "x":2, "y":2.25}, {"label":"k23", "x":3, "y":2}, {"label":"k24", "x":4, "y":2.5}, {"label":"k25", "x":5, "y":2.5}, {"label":"k26", "x":7, "y":2.5}, {"label":"k27", "x":8, "y":2.5}, {"label":"k28", "x":9, "y":2}, {"label":"k29", "x":10, "y":2.25}, {"label":"k2A", "x":11, "y":2.5}, {"label":"k2B", "x":12, "y":2.5}, {"label":"k33", "x":3, "y":4}, {"label":"k34", "x":4, "y":4}, {"label":"k35", "x":5, "y":4}, {"label":"k36", "x":7, "y":4}, {"label":"k37", "x":8, "y":4}, {"label":"k38", "x":9, "y":4}, {"label":"k43", "x":3, "y":5}, {"label":"k44", "x":4, "y":5}, {"label":"k45", "x":5, "y":5}, {"label":"k46", "x":7, "y":5}, {"label":"k47", "x":8, "y":5}, {"label":"k48", "x":9, "y":5}]
10 }
11 }
12}
diff --git a/keyboards/dichotomy/keymaps/default/keymap.c b/keyboards/dichotomy/keymaps/default/keymap.c
new file mode 100755
index 000000000..e44bd21d9
--- /dev/null
+++ b/keyboards/dichotomy/keymaps/default/keymap.c
@@ -0,0 +1,506 @@
1// this is the style you want to emulate.
2// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
3
4#include "dichotomy.h"
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.
10enum dichotomy_layers {
11 _BS,
12 _SF,
13 _NM,
14 _NS,
15 _MS
16};
17
18#define LONGPRESS_COUNT 4
19
20enum dichotomy_keycodes
21{
22 CK_1G = SAFE_RANGE,
23 CK_BSPE,
24 CK_QE,
25 CK_TE, //these 4 CK_XXXX keys are special "alternate long-press" keys controlled with unique timers. Make sure you understand them before you mess with them.
26 NS_HYPH,
27 NS_EQU,
28 NUMKEY,
29 SFTKEY,
30 MOUKEY,
31 MS_BTN1,
32 MS_BTN2,
33 MS_BTN3
34};
35
36#define CUSTOM_LONGPRESS 150
37#define CUSTOM_TOGGLE_TIME 300
38
39#define RED_BRIGHTNESS 3
40#define GREEN_BRIGHTNESS 2
41#define BLUE_BRIGHTNESS 2
42
43// Fillers to make layering more clear
44#define _______ KC_TRNS
45#define XXXXXXX KC_NO
46
47const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
48[_BS] = LAYOUT( /* Base layout, nearly qwerty but with modifications because it's not a full keyboard. Obviously. */
49 CK_TE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
50 NUMKEY, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, CK_QE,
51 SFTKEY, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MOUKEY,
52 KC_LCTL, KC_LALT, KC_LGUI, KC_RGUI, KC_RALT, KC_RCTL,
53 MS_BTN3, KC_LBRC, KC_LPRN, KC_SPC, KC_SPC, KC_RPRN, KC_RBRC, MS_BTN3
54),
55
56[_SF] = LAYOUT( /* Shifted layout, small changes (because angle brackets have been moved to thumb cluster buttons) */
57 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
58 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
59 _______, _______, _______, _______, _______, _______, _______, _______, NS_HYPH, KC_UNDS, _______, _______,
60 _______, _______, _______, _______, _______, _______,
61 _______, _______, KC_LABK, _______, _______, KC_RABK, _______, _______
62),
63
64[_NM] = LAYOUT( /* Number layout, basically the main function layer */
65 _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______,
66 _______, CK_1G, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, CK_BSPE,
67 _______, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, _______,
68 _______, _______, _______, _______, _______, _______,
69 _______, _______, _______, _______, _______, _______, _______, _______
70),
71
72[_NS] = LAYOUT( /* Shifted number/function layout, for per-key control. Only active when shift is held, and number is toggled or held */
73 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
74 _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PLUS, NS_EQU, _______,
75 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
76 _______, _______, _______, _______, _______, _______,
77 _______, _______, _______, _______, _______, _______, _______, _______
78),
79
80[_MS] = LAYOUT( /* Mouse layer, including buttons for clicking. */
81 _______, _______, _______, _______, _______, _______, KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______,
82 _______, _______, _______, _______, _______, _______, _______, MS_BTN1, MS_BTN2, _______, _______, _______,
83 _______, _______, _______, _______, _______, _______, KC_VOLD, KC_END, KC_PGDN, _______, _______, _______,
84 _______, _______, _______, _______, KC_UP, _______,
85 _______, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT, _______
86)
87
88};
89
90
91const uint16_t PROGMEM fn_actions[] = {
92
93};
94
95static uint16_t special_timers[LONGPRESS_COUNT] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
96static bool special_key_states[LONGPRESS_COUNT] = {0,0,0,0};
97static bool special_key_pressed[LONGPRESS_COUNT] = {0,0,0,0};
98
99static uint16_t shift_timer;
100static uint16_t num_timer;
101static uint16_t mouse_timer;
102
103static uint8_t red_timer;
104static uint8_t green_timer;
105static uint8_t blue_timer;
106
107static bool shift_singular_key = false;
108static bool number_singular_key = false;
109static bool mouse_singular_key = false;
110static bool capsLED = false;
111static bool shiftLED = false;
112static bool numLED = false;
113static bool mouseLED = false;
114
115static bool shift_held = false;
116static bool shift_suspended = false;
117report_mouse_t currentReport = {};
118
119bool process_record_user(uint16_t keycode, keyrecord_t *record) {
120 //uint8_t layer;
121 //layer = biton32(layer_state); // get the current layer //Or don't, I didn't use it.
122 bool returnVal = true; //this is to determine if more key processing is needed.
123
124 //custom layer handling for tri_layer,
125 switch (keycode) {
126 case NUMKEY:
127 if (record->event.pressed) {
128 num_timer = timer_read();
129 number_singular_key = true;
130 layer_invert(_NM);
131 numLED = !numLED;
132 } else {
133 if (timer_elapsed(num_timer) < CUSTOM_TOGGLE_TIME && number_singular_key) {
134 //do nothing, the layer has already been inverted
135 } else {
136 layer_invert(_NM);
137 numLED = !numLED;
138 }
139 }
140 update_tri_layer(_NM, _SF, _NS);
141 returnVal = false;
142 break;
143 //SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
144 case SFTKEY:
145 if (record->event.pressed) {
146 shift_held = true;
147 shiftLED = true;
148 shift_suspended = false;
149 shift_timer = timer_read();
150 shift_singular_key = true;
151 layer_on(_SF);
152 register_code(KC_LSFT);
153 } else {
154 shift_held = false;
155 shiftLED = false;
156 if (timer_elapsed(shift_timer) < CUSTOM_TOGGLE_TIME && shift_singular_key) {
157 //this was basically a toggle, so activate/deactivate caps lock.
158 SEND_STRING(SS_TAP(X_CAPSLOCK));
159 capsLED = !capsLED;
160 }
161 layer_off(_SF);
162 unregister_code(KC_LSFT);
163 }
164 update_tri_layer(_NM, _SF, _NS);
165 returnVal = false;
166 break;
167 //MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
168 case MOUKEY:
169 if (record->event.pressed) {
170 mouse_timer = timer_read();
171 mouse_singular_key = true;
172 layer_invert(_MS);
173 mouseLED = !mouseLED;
174 } else {
175 if (timer_elapsed(mouse_timer) < CUSTOM_TOGGLE_TIME && mouse_singular_key){
176 //do nothing, it was a toggle (and it's already been toggled)
177 } else {
178 layer_invert(_MS);
179 mouseLED = !mouseLED;
180 }
181 }
182 returnVal = false;
183 break;
184 //Custom macros for strange keys with different long-tap behavior
185 case CK_1G:
186 if (shift_held && shift_suspended){
187 register_code(KC_LSFT);
188 shift_suspended = false;
189 }
190 if (record->event.pressed) {
191 special_timers[CK_1G-SAFE_RANGE] = timer_read();
192 special_key_pressed[CK_1G-SAFE_RANGE] = 1;
193 } else {
194 if (special_key_states[CK_1G-SAFE_RANGE]){
195 //key was activated after custom_longpress, need to close those keycodes
196 special_key_states[CK_1G-SAFE_RANGE] = 0;
197 unregister_code(KC_GRAVE);
198 } else {
199 if (special_key_pressed[CK_1G-SAFE_RANGE]){
200 //key was not activated, return macro activating proper, pre-long-tap key
201 SEND_STRING(SS_TAP(X_1));
202 special_key_pressed[CK_1G-SAFE_RANGE] = 0;
203 } else {
204 //the short key was already sent, because another key was pressed.
205 //Do nothing.
206 }
207
208 }
209 }
210 returnVal = false;
211 break;
212 case CK_BSPE:
213 if (shift_held && shift_suspended){
214 register_code(KC_LSFT);
215 shift_suspended = false;
216 }
217 if (record->event.pressed) {
218 special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
219 special_key_pressed[CK_BSPE-SAFE_RANGE] = 1;
220 } else {
221 if (special_key_states[CK_BSPE-SAFE_RANGE]){
222 //key was activated after custom_longpress, need to close those keycodes
223 special_key_states[CK_BSPE-SAFE_RANGE] = 0;
224 unregister_code(KC_ENTER);
225 } else {
226 if (special_key_pressed[CK_BSPE-SAFE_RANGE]){
227 //key was not activated, return macro activating proper, pre-long-tap key
228 SEND_STRING(SS_TAP(X_BSLASH));
229 special_key_pressed[CK_BSPE-SAFE_RANGE] = 0;
230 } else {
231 //the short key was already sent, because another key was pressed.
232 //Do nothing.
233 }
234 }
235 }
236 returnVal = false;
237 break;
238 case CK_QE:
239 if (shift_held && shift_suspended){
240 register_code(KC_LSFT);
241 shift_suspended = false;
242 }
243 if (record->event.pressed) {
244 special_timers[CK_QE-SAFE_RANGE] = timer_read();
245 special_key_pressed[CK_QE-SAFE_RANGE] = 1;
246 } else {
247 if (special_key_states[CK_QE-SAFE_RANGE]){
248 //key was activated after custom_longpress, need to close those keycodes
249 special_key_states[CK_QE-SAFE_RANGE] = 0;
250 unregister_code(KC_ENTER);
251 } else {
252 if (special_key_pressed[CK_QE-SAFE_RANGE]){
253 //the long-press key was not activated, return macro activating proper, pre-long-tap key
254 SEND_STRING(SS_TAP(X_QUOTE));
255 special_key_pressed[CK_QE-SAFE_RANGE] = 0;
256 } else {
257 //the short key was already sent, because another key was pressed.
258 //Do nothing.
259 }
260 }
261 }
262 returnVal = false;
263 break;
264 case CK_TE:
265 if (shift_held && shift_suspended){
266 register_code(KC_LSFT);
267 shift_suspended = false;
268 }
269 if (record->event.pressed) {
270 special_timers[CK_TE-SAFE_RANGE] = timer_read();
271 special_key_pressed[CK_TE-SAFE_RANGE] = 1;
272 } else {
273 if (special_key_states[CK_TE-SAFE_RANGE]){
274 //key was activated after custom_longpress, need to close those keycodes
275 special_key_states[CK_TE-SAFE_RANGE] = 0;
276 unregister_code(KC_ESCAPE);
277 } else {
278 if (special_key_pressed[CK_TE-SAFE_RANGE]){
279 //the long-press key was not activated, return macro activating proper, pre-long-tap key
280 SEND_STRING(SS_TAP(X_TAB));
281 special_key_pressed[CK_TE-SAFE_RANGE] = 0;
282 } else {
283 //the short key was already sent, because another key was pressed.
284 //Do nothing.
285 }
286 }
287 }
288 returnVal = false;
289 break;
290 //No-shift keys, they unregister the KC_LSFT code so they can send
291 //unshifted values - but they don't change the bool. if any other
292 //key is pressed and the bool is set, KC_LSFT is registered again.
293 case NS_HYPH:
294 if (record->event.pressed) {
295 shift_suspended = true;
296 unregister_code(KC_LSFT);
297 register_code(KC_MINS);
298 } else {
299 unregister_code(KC_MINS);
300 if (shift_held && shift_suspended){
301 register_code(KC_LSFT);
302 shift_suspended = false;
303 }
304 }
305 returnVal = false;
306 break;
307 case NS_EQU:
308 if (record->event.pressed) {
309 shift_suspended = true;
310 unregister_code(KC_LSFT);
311 register_code(KC_EQUAL);
312 } else {
313 unregister_code(KC_EQUAL);
314 if (shift_held && shift_suspended){
315 register_code(KC_LSFT);
316 shift_suspended = false;
317 }
318 }
319 returnVal = false;
320 break;
321
322 //mouse buttons, for 1-3, to update the mouse report:
323 case MS_BTN1:
324 currentReport = pointing_device_get_report();
325 if (record->event.pressed) {
326 if (shift_held && shift_suspended){
327 register_code(KC_LSFT);
328 shift_suspended = false;
329 }
330 //update mouse report here
331 currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
332 } else {
333 //update mouse report here
334 currentReport.buttons &= ~MOUSE_BTN1;
335 }
336 pointing_device_set_report(currentReport);
337 returnVal = false;
338 break;
339 case MS_BTN2:
340 currentReport = pointing_device_get_report();
341 if (record->event.pressed) {
342 if (shift_held && shift_suspended){
343 register_code(KC_LSFT);
344 shift_suspended = false;
345 }
346 //update mouse report here
347 currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
348 } else {
349 //update mouse report here
350 currentReport.buttons &= ~MOUSE_BTN2;
351 }
352 pointing_device_set_report(currentReport);
353 returnVal = false;
354 break;
355 case MS_BTN3:
356 currentReport = pointing_device_get_report();
357 if (record->event.pressed) {
358 if (shift_held && shift_suspended){
359 register_code(KC_LSFT);
360 shift_suspended = false;
361 }
362 //update mouse report here
363 currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN3 is a const defined in report.h
364 } else {
365 //update mouse report here
366 currentReport.buttons &= ~MOUSE_BTN3;
367 }
368 pointing_device_set_report(currentReport);
369 returnVal = false;
370 break;
371 //Additionally, if NS_ keys are in use, then shift may be held (but is
372 //disabled for the unshifted keycodes to be send. Check the bool and
373 //register shift as necessary.
374 default:
375 if (shift_held){
376 register_code(KC_LSFT);
377 }
378 break;
379 }
380 switch (keycode){
381 case KC_BSPC:
382 case KC_NO:
383 case NUMKEY:
384 case SFTKEY:
385 case MOUKEY:
386 //don't want to reset single key variables
387 break;
388 default:
389 //If any other key was pressed during the layer mod hold period,
390 //then the layer mod was used momentarily, and should block latching
391 shift_singular_key = false;
392 number_singular_key = false;
393 mouse_singular_key = false;
394 break;
395 }
396 switch (keycode){
397 case KC_BSPC:
398 case KC_NO:
399 case NUMKEY:
400 case SFTKEY:
401 case MOUKEY:
402 case MOUSE_BTN1:
403 case MOUSE_BTN2:
404 case MOUSE_BTN3:
405 case KC_LCTL:
406 case KC_LALT:
407 case KC_LGUI:
408 case KC_RCTL:
409 case KC_RALT:
410 case KC_RGUI:
411 case CK_1G:
412 case CK_BSPE:
413 case CK_QE:
414 case CK_TE:
415 //Do nothing, don't want to trigger the timer key rollover
416 break;
417 default:
418 //Now we're checking to see if any of the special timer keys are pressed
419 //if so, we need to activate their short-press features
420 if (record->event.pressed) {
421 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
422 if ((!special_key_states[i]) && special_key_pressed[i]){
423 switch (i + SAFE_RANGE){
424 case CK_1G:
425 SEND_STRING(SS_TAP(X_1));
426 break;
427 case CK_BSPE:
428 SEND_STRING(SS_TAP(X_BSLASH));
429 break;
430 case CK_QE:
431 SEND_STRING(SS_TAP(X_QUOTE));
432 break;
433 case CK_TE:
434 SEND_STRING(SS_TAP(X_TAB));
435 break;
436 }
437 special_key_pressed[i] = 0;
438 }
439 }
440 } else {
441 //do nothing, we don't want to trigger short presses on key releases.
442 }
443 break;
444 }
445 return returnVal;
446};
447
448void matrix_scan_user(void) {
449 //uint8_t layer = biton32(layer_state);
450 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
451 if ((timer_elapsed(special_timers[i]) >= CUSTOM_LONGPRESS) && (!special_key_states[i]) && special_key_pressed[i]){
452 switch (i + SAFE_RANGE){
453 case CK_1G:
454 register_code(KC_GRAVE);
455 break;
456 case CK_BSPE:
457 register_code(KC_ENTER);
458 break;
459 case CK_QE:
460 register_code(KC_ENTER);
461 break;
462 case CK_TE:
463 register_code(KC_ESCAPE);
464 break;
465 }
466 special_key_pressed[i] = 0;
467 special_key_states[i] = 1;
468 }
469 }
470 if (shiftLED || capsLED){
471 red_timer++;
472 if (red_timer < RED_BRIGHTNESS){
473 red_led_on();
474 } else {
475 red_timer = 0;
476 red_led_off();
477 }
478 } else {
479 red_timer = 0;
480 red_led_off();
481 }
482 if (numLED){
483 green_timer++;
484 if (green_timer < GREEN_BRIGHTNESS){
485 grn_led_on();
486 } else {
487 green_timer = 0;
488 grn_led_off();
489 }
490 } else {
491 green_timer = 0;
492 grn_led_off();
493 }
494 if (mouseLED){
495 blue_timer++;
496 if (blue_timer < BLUE_BRIGHTNESS){
497 blu_led_on();
498 } else {
499 blue_timer = 0;
500 blu_led_off();
501 }
502 } else {
503 blue_timer = 0;
504 blu_led_off();
505 }
506};
diff --git a/keyboards/dichotomy/matrix.c b/keyboards/dichotomy/matrix.c
new file mode 100755
index 000000000..14c3f0d8e
--- /dev/null
+++ b/keyboards/dichotomy/matrix.c
@@ -0,0 +1,228 @@
1/*
2Copyright 2012 Jun Wako
3Copyright 2014 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#include <stdint.h>
19#include <stdbool.h>
20#if defined(__AVR__)
21#include <avr/io.h>
22#endif
23#include "wait.h"
24#include "print.h"
25#include "debug.h"
26#include "util.h"
27#include "matrix.h"
28#include "timer.h"
29#include "dichotomy.h"
30#include "pointing_device.h"
31#include "report.h"
32
33#if (MATRIX_COLS <= 8)
34# define print_matrix_header() print("\nr/c 01234567\n")
35# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
36# define matrix_bitpop(i) bitpop(matrix[i])
37# define ROW_SHIFTER ((uint8_t)1)
38#elif (MATRIX_COLS <= 16)
39# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
40# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
41# define matrix_bitpop(i) bitpop16(matrix[i])
42# define ROW_SHIFTER ((uint16_t)1)
43#elif (MATRIX_COLS <= 32)
44# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
45# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
46# define matrix_bitpop(i) bitpop32(matrix[i])
47# define ROW_SHIFTER ((uint32_t)1)
48#endif
49
50#define MAIN_ROWMASK 0xFFF0;
51#define LOWER_ROWMASK 0x3FC0;
52
53/* matrix state(1:on, 0:off) */
54static matrix_row_t matrix[MATRIX_ROWS];
55
56__attribute__ ((weak))
57void matrix_init_quantum(void) {
58 matrix_init_kb();
59}
60
61__attribute__ ((weak))
62void matrix_scan_quantum(void) {
63 matrix_scan_kb();
64}
65
66__attribute__ ((weak))
67void matrix_init_kb(void) {
68 matrix_init_user();
69}
70
71__attribute__ ((weak))
72void matrix_scan_kb(void) {
73 matrix_scan_user();
74}
75
76__attribute__ ((weak))
77void matrix_init_user(void) {
78}
79
80__attribute__ ((weak))
81void matrix_scan_user(void) {
82}
83
84inline
85uint8_t matrix_rows(void) {
86 return MATRIX_ROWS;
87}
88
89inline
90uint8_t matrix_cols(void) {
91 return MATRIX_COLS;
92}
93
94void matrix_init(void) {
95 DDRF |= (1<<6);
96 DDRF |= (1<<5);
97 DDRD |= (1<<1);
98 matrix_init_quantum();
99}
100
101uint8_t matrix_scan(void)
102{
103 SERIAL_UART_INIT();
104 //xprintf("\r\nTRYING TO SCAN");
105
106 uint32_t timeout = 0;
107
108 //the s character requests the RF slave to send the matrix
109 SERIAL_UART_DATA = 's';
110
111 //trust the external keystates entirely, erase the last data
112 uint8_t uart_data[11] = {0};
113
114 //there are 10 bytes corresponding to 10 columns, and an end byte
115 for (uint8_t i = 0; i < 11; i++) {
116 //wait for the serial data, timeout if it's been too long
117 //this only happened in testing with a loose wire, but does no
118 //harm to leave it in here
119 while(!SERIAL_UART_RXD_PRESENT){
120 timeout++;
121 if (timeout > 10000){
122 xprintf("\r\nTime out in keyboard.");
123 break;
124 }
125 }
126 uart_data[i] = SERIAL_UART_DATA;
127 }
128
129 //check for the end packet, the key state bytes use the LSBs, so 0xE0
130 //will only show up here if the correct bytes were recieved
131 uint8_t checksum = 0x00;
132 for (uint8_t z=0; z<10; z++){
133 checksum = checksum^uart_data[z];
134 }
135 checksum = checksum ^ (uart_data[10] & 0xF0);
136 // Smash the checksum from 1 byte into 4 bits
137 checksum = (checksum ^ ((checksum & 0xF0)>>4)) & 0x0F;
138//xprintf("\r\nGOT RAW PACKET: \r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d",uart_data[0],uart_data[1],uart_data[2],uart_data[3],uart_data[4],uart_data[5],uart_data[6],uart_data[7],uart_data[8],uart_data[9],uart_data[10],checksum);
139 if ((uart_data[10] & 0x0F) == checksum) { //this is an arbitrary binary checksum (1001) (that would be 0x9.)
140 //xprintf("\r\nGOT PACKET: \r\n%d\r\n%d\r\n%d\r\n%d\r\n%d\r\n%d",uart_data[0],uart_data[1],uart_data[2],uart_data[3],uart_data[4],uart_data[5]);
141 //shifting and transferring the keystates to the QMK matrix variable
142 //bits 1-12 are row 1, 13-24 are row 2, 25-36 are row 3,
143 //bits 37-42 are row 4 (only 6 wide, 1-3 are 0, and 10-12 are 0)
144 //bits 43-48 are row 5 (same as row 4)
145 /* ASSUMING MSB FIRST */
146 matrix[0] = (((uint16_t) uart_data[0] << 8) | ((uint16_t) uart_data[1])) & MAIN_ROWMASK;
147 matrix[1] = ((uint16_t) uart_data[1] << 12) | ((uint16_t) uart_data[2] << 4);
148 matrix[2] = (((uint16_t) uart_data[3] << 8) | ((uint16_t) uart_data[4])) & MAIN_ROWMASK;
149 matrix[3] = (((uint16_t) uart_data[4] << 9) | ((uint16_t) uart_data[5] << 1)) & LOWER_ROWMASK;
150 matrix[4] = (((uint16_t) uart_data[5] << 7) | ((uart_data[10] & 1<<7) ? 1:0) << 13 | ((uart_data[10] & 1<<6) ? 1:0) << 6) & LOWER_ROWMASK;
151 /* OK, TURNS OUT THAT WAS A BAD ASSUMPTION */
152 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
153 //I've unpacked these into the mirror image of what QMK expects them to be, so...
154 /*uint8_t halfOne = (matrix[i]>>8);
155 uint8_t halfTwo = (matrix[i] & 0xFF);
156 halfOne = ((halfOne * 0x0802LU & 0x22110LU) | (halfOne * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
157 halfTwo = ((halfTwo * 0x0802LU & 0x22110LU) | (halfTwo * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
158 matrix[i] = ((halfTwo<<8) & halfOne);*/
159 //matrix[i] = ((matrix[i] * 0x0802LU & 0x22110LU) | (matrix[i] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
160 matrix[i] = bitrev16(matrix[i]);
161 //bithack mirror! Doesn't make any sense, but works - and efficiently.
162 }
163 //if (uart_data[6]!=0 || uart_data[7]!=0){
164 //if (maxCount<101){
165 // xprintf("\r\nMouse data: x=%d, y=%d",(int8_t)uart_data[6],(int8_t)uart_data[7]);
166 //}
167 report_mouse_t currentReport = {};
168 //check for the end packet, bytes 1-4 are movement and scroll
169 //but byte 5 has bits 0-3 for the scroll button state
170 //(1000 if pressed, 0000 if not) and bits 4-7 are always 1
171 //We can use this to verify the report sent properly.
172
173 currentReport = pointing_device_get_report();
174 //shifting and transferring the info to the mouse report varaible
175 //mouseReport.x = 127 max -127 min
176 currentReport.x = (int8_t) uart_data[6];
177 //mouseReport.y = 127 max -127 min
178 currentReport.y = (int8_t) uart_data[7];
179 //mouseReport.v = 127 max -127 min (scroll vertical)
180 currentReport.v = (int8_t) uart_data[8];
181 //mouseReport.h = 127 max -127 min (scroll horizontal)
182 currentReport.h = (int8_t) uart_data[9];
183 /*
184 currentReport.x = 0;
185 currentReport.y = 0;
186 currentReport.v = 0;
187 currentReport.h = 0;*/
188 pointing_device_set_report(currentReport);
189 } else {
190 //xprintf("\r\nRequested packet, data 10 was %d but checksum was %d",(uart_data[10] & 0x0F), (checksum & 0x0F));
191 }
192 //matrix_print();
193
194 matrix_scan_quantum();
195 return 1;
196}
197
198inline
199bool matrix_is_on(uint8_t row, uint8_t col)
200{
201 return (matrix[row] & ((matrix_row_t)1<col));
202}
203
204inline
205matrix_row_t matrix_get_row(uint8_t row)
206{
207 return matrix[row];
208}
209
210void matrix_print(void)
211{
212 print_matrix_header();
213
214 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
215 phex(row); print(": ");
216 print_matrix_row(row);
217 print("\n");
218 }
219}
220
221uint8_t matrix_key_count(void)
222{
223 uint8_t count = 0;
224 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
225 count += matrix_bitpop(i);
226 }
227 return count;
228}
diff --git a/keyboards/dichotomy/readme.md b/keyboards/dichotomy/readme.md
new file mode 100755
index 000000000..9027825c3
--- /dev/null
+++ b/keyboards/dichotomy/readme.md
@@ -0,0 +1,33 @@
1Dichotomy Keyboard Firmware
2======================
3
4These configuration files were based off the Mitosis keyboard. This keyboard uses a completely different 'matrix scan' system to other keyboards, it relies on an external nRF51822 microcontroller maintaining a matrix of keystates received from the keyboard halves - it also receives mouse pointer information from the keyboard halves, which is implemented through a new feature, "Pointing Device". The matrix.c file contains the code to poll the external microcontroller for the key matrix, and the keymap.c file contains similar code to obtain the mouse report. As long as the relavant functions in these files are not changed, all other QMK features are supported.
5
6Build log of the keyboard can be found [here](http://google.com)
7
8Hardware design files can be found [here](http://google.com)
9
10Firmware for the nordic MCUs can be found [here](http://google.com)
11
12## Quantum MK Firmware
13
14For the full Quantum feature list, see [the parent readme](/).
15
16## Building
17
18Download or clone the whole firmware and navigate to the keyboards/atreus folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
19
20Depending on which keymap you would like to use, you will have to compile slightly differently.
21
22### Default
23To build with the default keymap, simply run `make default`.
24
25### Other Keymaps
26Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
27
28To build the firmware binary hex file with a keymap just do `make` with a keymap like this:
29
30```
31$ make [default|jack|<name>]
32```
33Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/dichotomy/rules.mk b/keyboards/dichotomy/rules.mk
new file mode 100755
index 000000000..4dbc999b7
--- /dev/null
+++ b/keyboards/dichotomy/rules.mk
@@ -0,0 +1,77 @@
1
2OPT_DEFS += -DDICHOTOMY_PROMICRO
3DICHOTOMY_UPLOAD_COMMAND = while [ ! -r $(USB) ]; do sleep 1; done; \
4 avrdude -p $(MCU) -c avr109 -U flash:w:$(TARGET).hex -P $(USB)
5
6# # project specific files
7SRC = matrix.c
8
9
10# MCU name
11#MCU = at90usb1287
12MCU = atmega32u4
13
14# Processor frequency.
15# This will define a symbol, F_CPU, in all source code files equal to the
16# processor frequency in Hz. You can then use this symbol in your source code to
17# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
18# automatically to create a 32-bit value in your source code.
19#
20# This will be an integer division of F_USB below, as it is sourced by
21# F_USB after it has run through any CPU prescalers. Note that this value
22# does not *change* the processor frequency - it should merely be updated to
23# reflect the processor speed set externally so that the code can use accurate
24# software delays.
25F_CPU = 16000000
26
27
28#
29# LUFA specific
30#
31# Target architecture (see library "Board Types" documentation).
32ARCH = AVR8
33
34# Input clock frequency.
35# This will define a symbol, F_USB, in all source code files equal to the
36# input clock frequency (before any prescaling is performed) in Hz. This value may
37# differ from F_CPU if prescaling is used on the latter, and is required as the
38# raw input clock is fed directly to the PLL sections of the AVR for high speed
39# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
40# at the end, this will be done automatically to create a 32-bit value in your
41# source code.
42#
43# If no clock division is performed on the input clock inside the AVR (via the
44# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
45F_USB = $(F_CPU)
46
47# Bootloader
48 # This definition is optional, and if your keyboard supports multiple bootloaders of
49 # different sizes, comment this out, and the correct address will be loaded
50 # automatically (+60). See bootloader.mk for all options.
51 BOOTLOADER = caterina
52
53# Interrupt driven control endpoint task(+60)
54OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
55
56# Build Options
57# comment out to disable the options.
58#
59#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
60#MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
61POINTING_DEVICE_ENABLE = yes # Generic Pointer, not as big as mouse keys hopefully.
62EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
63CONSOLE_ENABLE = yes # Console for debug(+400)
64COMMAND_ENABLE = yes # Commands for debug and configuration
65CUSTOM_MATRIX = yes # Remote matrix from the wireless bridge
66# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
67# SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
68NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
69# BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
70# MIDI_ENABLE = YES # MIDI controls
71UNICODE_ENABLE = YES # Unicode
72# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
73
74USB = /dev/ttyACM0
75
76#upload: build
77# $(DICHOTOMY_UPLOAD_COMMAND)