aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/_summary.md1
-rw-r--r--keyboards/dichotemy/config.h87
-rw-r--r--keyboards/dichotemy/dichotemy.c86
-rw-r--r--keyboards/dichotemy/dichotemy.h67
-rw-r--r--keyboards/dichotemy/keymaps/default/keymap.c394
-rw-r--r--keyboards/dichotemy/matrix.c178
-rw-r--r--keyboards/dichotemy/readme.md33
-rw-r--r--keyboards/dichotemy/rules.mk82
-rw-r--r--quantum/pointing_device.c2
9 files changed, 929 insertions, 1 deletions
diff --git a/docs/_summary.md b/docs/_summary.md
index ce02220fb..b085c18d7 100644
--- a/docs/_summary.md
+++ b/docs/_summary.md
@@ -21,6 +21,7 @@
21 * [Leader Key](feature_leader_key.md) 21 * [Leader Key](feature_leader_key.md)
22 * [Macros](macros.md) 22 * [Macros](macros.md)
23 * [Mouse keys](mouse_keys.md) 23 * [Mouse keys](mouse_keys.md)
24 * [Pointing Device](feature_pointing_device.md)
24 * [PS2 Mouse](feature_ps2_mouse.md) 25 * [PS2 Mouse](feature_ps2_mouse.md)
25 * [Space Cadet](space_cadet_shift.md) 26 * [Space Cadet](space_cadet_shift.md)
26 * [Tap Dance](tap_dance.md) 27 * [Tap Dance](tap_dance.md)
diff --git a/keyboards/dichotemy/config.h b/keyboards/dichotemy/config.h
new file mode 100644
index 000000000..b3bd6d942
--- /dev/null
+++ b/keyboards/dichotemy/config.h
@@ -0,0 +1,87 @@
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 0x0001
28#define MANUFACTURER unknown
29#define PRODUCT Dichotemy
30#define DESCRIPTION q.m.k. keyboard firmware for Dichotemy
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#define PREVENT_STUCK_MODIFIERS
56
57/* disable debug print */
58//#define NO_DEBUG
59
60/* disable print */
61//#define NO_PRINT
62
63/* disable action features */
64//#define NO_ACTION_LAYER
65//#define NO_ACTION_TAPPING
66//#define NO_ACTION_ONESHOT
67//#define NO_ACTION_MACRO
68//#define NO_ACTION_FUNCTION
69
70//UART settings for communication with the RF microcontroller
71#define SERIAL_UART_BAUD 1000000
72#define SERIAL_UART_DATA UDR1
73#define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
74#define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
75#define SERIAL_UART_RXD_PRESENT (UCSR1A & _BV(RXC1))
76#define SERIAL_UART_INIT() do { \
77 /* baud rate */ \
78 UBRR1L = SERIAL_UART_UBRR; \
79 /* baud rate */ \
80 UBRR1H = SERIAL_UART_UBRR >> 8; \
81 /* enable TX and RX */ \
82 UCSR1B = _BV(TXEN1) | _BV(RXEN1); \
83 /* 8-bit data */ \
84 UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
85 } while(0)
86
87#endif
diff --git a/keyboards/dichotemy/dichotemy.c b/keyboards/dichotemy/dichotemy.c
new file mode 100644
index 000000000..080c2654c
--- /dev/null
+++ b/keyboards/dichotemy/dichotemy.c
@@ -0,0 +1,86 @@
1#include "dichotemy.h"
2#include "pointing_device.h"
3#include "report.h"
4
5void uart_init(void) {
6 SERIAL_UART_INIT();
7}
8
9void pointing_device_task(void){
10 report_mouse_t currentReport = {};
11 SERIAL_UART_INIT();
12 uint32_t timeout = 0;
13
14 //the m character requests the RF slave to send the mouse report
15 SERIAL_UART_DATA = 'm';
16
17 //trust the external inputs completely, erase old data
18 uint8_t uart_data[5] = {0};
19
20 //there are 10 bytes corresponding to 10 columns, and an end byte
21 for (uint8_t i = 0; i < 5; i++) {
22 //wait for the serial data, timeout if it's been too long
23 //this only happened in testing with a loose wire, but does no
24 //harm to leave it in here
25 while(!SERIAL_UART_RXD_PRESENT){
26 timeout++;
27 if (timeout > 10000){
28 break;
29 }
30 }
31 uart_data[i] = SERIAL_UART_DATA;
32 }
33
34 //check for the end packet, bits 1-4 are movement and scroll
35 //but bit 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 currentReport = pointing_device_get_report();
41 //shifting and transferring the info to the mouse report varaible
42 //mouseReport.x = 127 max -127 min
43 currentReport.x = uart_data[0];
44 //mouseReport.y = 127 max -127 min
45 currentReport.y = uart_data[1];
46 //mouseReport.v = 127 max -127 min (scroll vertical)
47 currentReport.v = uart_data[2];
48 //mouseReport.h = 127 max -127 min (scroll horizontal)
49 currentReport.h = uart_data[3];
50 //mouseReport.buttons = 0x31 max (bitmask for mouse buttons 1-5) 0x00 min
51 //mouse buttons 1 and 2 are handled by the keymap, but not 3
52 if (uart_data[4] == 0x0F) { //then 3 is not pressed
53 currentReport.buttons &= ~MOUSE_BTN3; //MOUSE_BTN3 is def in report.h
54 } else { //3 must be pressed
55 currentReport.buttons |= MOUSE_BTN3;
56 }
57 pointing_device_set_report(currentReport);
58 }
59 pointing_device_send();
60}
61
62void led_init(void) {
63 DDRD |= (1<<1);
64 PORTD |= (1<<1);
65 DDRF |= (1<<4) | (1<<5);
66 PORTF |= (1<<4) | (1<<5);
67}
68
69
70void matrix_init_kb(void) {
71 // put your keyboard start-up code here
72 // runs once when the firmware starts up
73 matrix_init_user();
74 uart_init();
75 led_init();
76}
77
78void matrix_scan_kb(void) {
79 // put your looping keyboard code here
80 // runs every cycle (a lot)
81 matrix_scan_user();
82}
83
84void led_set_kb(uint8_t usb_led) {
85
86}
diff --git a/keyboards/dichotemy/dichotemy.h b/keyboards/dichotemy/dichotemy.h
new file mode 100644
index 000000000..09b9dfcf2
--- /dev/null
+++ b/keyboards/dichotemy/dichotemy.h
@@ -0,0 +1,67 @@
1#ifndef DICHOTEMY_H
2#define DICHOTEMY_H
3
4#include "quantum.h"
5#include "matrix.h"
6#include "backlight.h"
7#include <stddef.h>
8
9#define red_led_off PORTF |= (1<<5)
10#define red_led_on PORTF &= ~(1<<5)
11#define blu_led_off PORTF |= (1<<4)
12#define blu_led_on PORTF &= ~(1<<4)
13#define grn_led_off PORTD |= (1<<1)
14#define grn_led_on PORTD &= ~(1<<1)
15
16#define set_led_off red_led_off; grn_led_off; blu_led_off
17#define set_led_red red_led_on; grn_led_off; blu_led_off
18#define set_led_blue red_led_off; grn_led_off; blu_led_on
19#define set_led_green red_led_off; grn_led_on; blu_led_off
20#define set_led_yellow red_led_on; grn_led_on; blu_led_off
21#define set_led_magenta red_led_on; grn_led_off; blu_led_on
22#define set_led_cyan red_led_off; grn_led_on; blu_led_on
23#define set_led_white red_led_on; grn_led_on; blu_led_on
24
25/*
26#define LED_B 5
27#define LED_R 6
28#define LED_G 7
29
30#define all_leds_off PORTF &= ~(1<<LED_B) & ~(1<<LED_R) & ~(1<<LED_G)
31
32#define red_led_on PORTF |= (1<<LED_R)
33#define red_led_off PORTF &= ~(1<<LED_R)
34#define grn_led_on PORTF |= (1<<LED_G)
35#define grn_led_off PORTF &= ~(1<<LED_G)
36#define blu_led_on PORTF |= (1<<LED_B)
37#define blu_led_off PORTF &= ~(1<<LED_B)
38
39#define set_led_off PORTF &= ~(1<<LED_B) & ~(1<<LED_R) & ~(1<<LED_G)
40#define set_led_red PORTF = PORTF & ~(1<<LED_B) & ~(1<<LED_G) | (1<<LED_R)
41#define set_led_blue PORTF = PORTF & ~(1<<LED_G) & ~(1<<LED_R) | (1<<LED_B)
42#define set_led_green PORTF = PORTF & ~(1<<LED_B) & ~(1<<LED_R) | (1<<LED_G)
43#define set_led_yellow PORTF = PORTF & ~(1<<LED_B) | (1<<LED_R) | (1<<LED_G)
44#define set_led_magenta PORTF = PORTF & ~(1<<LED_G) | (1<<LED_R) | (1<<LED_B)
45#define set_led_cyan PORTF = PORTF & ~(1<<LED_R) | (1<<LED_B) | (1<<LED_G)
46#define set_led_white PORTF |= (1<<LED_B) | (1<<LED_R) | (1<<LED_G)
47*/
48
49// This a shortcut to help you visually see your layout.
50// The first section contains all of the arguements
51// The second converts the arguments into a two-dimensional array
52#define KEYMAP( \
53 k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B, \
54 k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B, \
55 k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B, \
56 k33, k34, k35, k36, k37, k38, \
57 k43, k44, k45, k46, k47, k48 \
58) \
59{ \
60 { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B }, \
61 { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B }, \
62 { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B }, \
63 { KC_NO, KC_NO, KC_NO, k33, k34, k35, k36, k37, k38, KC_NO, KC_NO, KC_NO }, \
64 { KC_NO, KC_NO, KC_NO, k43, k44, k45, k46, k47, k48, KC_NO, KC_NO, KC_NO } \
65}
66
67#endif
diff --git a/keyboards/dichotemy/keymaps/default/keymap.c b/keyboards/dichotemy/keymaps/default/keymap.c
new file mode 100644
index 000000000..2298ecb22
--- /dev/null
+++ b/keyboards/dichotemy/keymaps/default/keymap.c
@@ -0,0 +1,394 @@
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 "dichotemy.h"
5#include "report.h"
6#include "pointing_device.h"
7
8// Each layer gets a name for readability, which is then used in the keymap matrix below.
9// The underscores don't mean anything - you can have a layer called STUFF or any other name.
10// Layer names don't all need to be of the same length, obviously, and you can also skip them
11// entirely and just use numbers.
12enum dichotemy_layers
13{
14 _BS,
15 _SF,
16 _NM,
17 _NS,
18 _MS
19};
20
21#define LONGPRESS_COUNT 4
22
23enum dichotemy_keycodes
24{
25 CK_1G = SAFE_RANGE,
26 CK_BSPE,
27 CK_QE,
28 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.
29 NS_HYPH,
30 NS_EQU,
31 NUMKEY,
32 SFTKEY,
33 MOUSE,
34 MS_BTN1,
35 MS_BTN2
36 //MS_BTN3
37};
38
39// Macro definitions for readability
40enum dichotemy_macros
41{
42 VOLU,
43 VOLD,
44 ESCM
45};
46
47#define LONGPRESS_DELAY 150
48#define MAX_TOGGLE_LENGTH 300
49#define TAPPING_TOGGLE 1
50
51// Fillers to make layering more clear
52#define _______ KC_TRNS
53#define XXXXXXX KC_NO
54
55const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
56[_BS] = { /* Base layout, nearly qwerty but with modifications because it's not a full keyboard. Obviously. */
57 {CK_TE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC },
58 {NUMKEY, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, CK_QE },
59 {SFTKEY, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MOUSE },
60 {XXXXXXX, XXXXXXX, XXXXXXX, KC_LCTL, KC_LALT, KC_LGUI, KC_RGUI, KC_RALT, KC_RCTL, XXXXXXX, XXXXXXX, XXXXXXX },
61 {XXXXXXX, XXXXXXX, XXXXXXX, KC_LBRC, KC_LPRN, KC_QUOT, KC_SPC, KC_RPRN, KC_RBRC, XXXXXXX, XXXXXXX, XXXXXXX }
62},
63
64[_SF] = { /* Shifted layout, small changes (because angle brackets have been moved to thumb cluster buttons) */
65 {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
66 {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
67 {_______, _______, _______, _______, _______, _______, _______, _______, NS_HYPH, KC_UNDS, _______, _______ },
68 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX },
69 {XXXXXXX, XXXXXXX, XXXXXXX, _______, KC_LABK, _______, _______, KC_RABK, _______, XXXXXXX, XXXXXXX, XXXXXXX }
70},
71
72[_NM] = { /* Number layout, basically the main function layer */
73 {_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______ },
74 {_______, CK_1G, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, CK_BSPE },
75 {_______, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, _______ },
76 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX },
77 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX }
78},
79
80[_NS] = { /* Shifted number/function layout, for per-key control. Only active when shift is held, and number is toggled or held */
81 {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
82 {_______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PLUS, NS_EQU, _______ },
83 {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
84 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX },
85 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX }
86},
87
88[_MS] = { /* Mouse layer, including buttons for clicking. */
89 {_______, _______, _______, _______, _______, _______, KC_VOLU, KC_HOME, KC_PGUP, _______, _______, _______ },
90 {_______, _______, _______, _______, _______, _______, _______, MS_BTN1, MS_BTN2, _______, _______, _______ },
91 {_______, _______, _______, _______, _______, _______, KC_VOLD, KC_END, KC_PGDN, _______, _______, _______ },
92 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, KC_UP, _______, XXXXXXX, XXXXXXX, XXXXXXX },
93 {XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT, XXXXXXX, XXXXXXX, XXXXXXX }
94}
95
96};
97
98
99const uint16_t PROGMEM fn_actions[] = {
100
101};
102
103static uint16_t special_timers[LONGPRESS_COUNT] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
104static bool special_key_states[LONGPRESS_COUNT] = {0,0,0,0};
105
106static uint16_t shift_timer;
107static uint16_t num_timer;
108static uint16_t mouse_timer;
109
110static bool shift_singular_key = false;
111static bool number_singular_key = false;
112static bool mouse_singular_key = false;
113
114static bool shift_held = false;
115static bool shift_suspended = false;
116report_mouse_t currentReport = {};
117
118bool process_record_user(uint16_t keycode, keyrecord_t *record) {
119
120 //uint8_t layer;
121 //layer = biton32(layer_state); // get the current layer //Or don't, I didn't use it.
122
123 //custom layer handling for tri_layer,
124 switch (keycode) {
125 case NUMKEY:
126 if (record->event.pressed) {
127 num_timer = timer_read();
128 number_singular_key = true;
129 layer_invert(_NM);
130 } else {
131 if (timer_elapsed(num_timer) < MAX_TOGGLE_LENGTH && number_singular_key) {
132 //do nothing, the layer has already been inverted
133 } else {
134 layer_invert(_NM);
135 }
136 }
137 update_tri_layer(_NM, _SF, _NS);
138 return false;
139 break;
140 //SHIFT is handled as LSHIFT in the general case - 'toggle' shoudl activate caps, while the layer is only active when shift is held.
141 case SFTKEY:
142 if (record->event.pressed) {
143 shift_held = true;
144 shift_suspended = false;
145 shift_timer = timer_read();
146 shift_singular_key = true;
147 layer_on(_SF);
148 register_code(KC_LSFT);
149 } else {
150 shift_held = false;
151 if (timer_elapsed(shift_timer) < MAX_TOGGLE_LENGTH && shift_singular_key) {
152 //this was basically a toggle, so activate/deactivate caps lock.
153 SEND_STRING(SS_TAP(X_CAPSLOCK));
154 }
155 layer_off(_SF);
156 unregister_code(KC_LSFT);
157 }
158 update_tri_layer(_NM, _SF, _NS);
159 return false;
160 break;
161 //MOUSE layer needs to be handled the same way as NUMKEY, but differently from shift
162 case MOUSE:
163 if (record->event.pressed) {
164 mouse_timer = timer_read();
165 mouse_singular_key = true;
166 layer_invert(_MS);
167 } else {
168 if (timer_elapsed(mouse_timer) < MAX_TOGGLE_LENGTH && number_singular_key){
169 //do nothing, it was a toggle (and it's already been toggled)
170 } else {
171 layer_invert(_MS);
172 }
173 }
174 return false;
175 break;
176 //Custom macros for strange keys with different long-tap behavior
177 case CK_1G:
178 if (shift_held && shift_suspended){
179 register_code(KC_LSFT);
180 shift_suspended = false;
181 }
182 shift_singular_key = false;
183 number_singular_key = false;
184 mouse_singular_key = false;
185 if (record->event.pressed) {
186 special_timers[CK_1G-SAFE_RANGE] = timer_read();
187 } else {
188 if (special_key_states[CK_1G-SAFE_RANGE]){
189 //key was activated after longpress_delay, need to close those keycodes
190 special_key_states[CK_1G-SAFE_RANGE] = 0;
191 unregister_code(KC_GRAVE);
192 } else {
193 //key was not activated, return macro activating proper, pre-long-tap key
194 SEND_STRING(SS_TAP(X_1));
195 }
196 special_timers[CK_1G-SAFE_RANGE] = 0xFFFF;
197 }
198 break;
199 case CK_BSPE:
200 if (shift_held && shift_suspended){
201 register_code(KC_LSFT);
202 shift_suspended = false;
203 }
204 shift_singular_key = false;
205 number_singular_key = false;
206 mouse_singular_key = false;
207 if (record->event.pressed) {
208 special_timers[CK_BSPE-SAFE_RANGE] = timer_read();
209 } else {
210 if (special_key_states[CK_BSPE-SAFE_RANGE]){
211 //key was activated after longpress_delay, need to close those keycodes
212 special_key_states[CK_BSPE-SAFE_RANGE] = 0;
213 unregister_code(KC_ENTER);
214 } else {
215 //key was not activated, return macro activating proper, pre-long-tap key
216 SEND_STRING(SS_TAP(X_BSLASH));
217 }
218 special_timers[CK_BSPE-SAFE_RANGE] = 0xFFFF;
219 }
220 break;
221 case CK_QE:
222 if (shift_held && shift_suspended){
223 register_code(KC_LSFT);
224 shift_suspended = false;
225 }
226 shift_singular_key = false;
227 number_singular_key = false;
228 mouse_singular_key = false;
229 if (record->event.pressed) {
230 special_timers[CK_QE-SAFE_RANGE] = timer_read();
231 } else {
232 if (special_key_states[CK_QE-SAFE_RANGE]){
233 //key was activated after longpress_delay, need to close those keycodes
234 special_key_states[CK_QE-SAFE_RANGE] = 0;
235 unregister_code(KC_ENTER);
236 } else {
237 //key was not activated, return macro activating proper, pre-long-tap key
238 SEND_STRING(SS_TAP(X_QUOTE));
239 }
240 special_timers[CK_QE-SAFE_RANGE] = 0xFFFF;
241 }
242 break;
243 case CK_TE:
244 if (shift_held && shift_suspended){
245 register_code(KC_LSFT);
246 shift_suspended = false;
247 }
248 if (record->event.pressed) {
249 special_timers[CK_TE-SAFE_RANGE] = timer_read();
250 } else {
251 if (special_key_states[CK_TE-SAFE_RANGE]){
252 //key was activated after longpress_delay, need to close those keycodes
253 special_key_states[CK_TE-SAFE_RANGE] = 0;
254 unregister_code(KC_ENTER);
255 } else {
256 //key was not activated, return macro activating proper, pre-long-tap key
257 SEND_STRING(SS_TAP(X_TAB));
258 }
259 special_timers[CK_TE-SAFE_RANGE] = 0xFFFF;
260 }
261 break;
262 //No-shift keys, they unregister the KC_LSFT code so they can send
263 //unshifted values - but they don't change the bool. if any other
264 //key is pressed and the bool is set, KC_LSFT is registered again.
265 case NS_HYPH:
266 if (record->event.pressed) {
267 shift_suspended = true;
268 unregister_code(KC_LSFT);
269 register_code(KC_MINS);
270 } else {
271 unregister_code(KC_MINS);
272 if (shift_held && shift_suspended){
273 register_code(KC_LSFT);
274 shift_suspended = false;
275 }
276 }
277 break;
278 case NS_EQU:
279 if (record->event.pressed) {
280 shift_suspended = true;
281 unregister_code(KC_LSFT);
282 register_code(KC_EQUAL);
283 } else {
284 unregister_code(KC_EQUAL);
285 if (shift_held && shift_suspended){
286 register_code(KC_LSFT);
287 shift_suspended = false;
288 }
289 }
290 break;
291
292 //mouse buttons, for 1-3, to update the mouse report:
293 case MS_BTN1:
294 currentReport = pointing_device_get_report();
295 if (record->event.pressed) {
296 if (shift_held && shift_suspended){
297 register_code(KC_LSFT);
298 shift_suspended = false;
299 }
300 //update mouse report here
301 currentReport.buttons |= MOUSE_BTN1; //MOUSE_BTN1 is a const defined in report.h
302 } else {
303 //update mouse report here
304 currentReport.buttons &= ~MOUSE_BTN1;
305 }
306 pointing_device_set_report(currentReport);
307 break;
308 case MS_BTN2:
309 currentReport = pointing_device_get_report();
310 if (record->event.pressed) {
311 if (shift_held && shift_suspended){
312 register_code(KC_LSFT);
313 shift_suspended = false;
314 }
315 //update mouse report here
316 currentReport.buttons |= MOUSE_BTN2; //MOUSE_BTN2 is a const defined in report.h
317 } else {
318 //update mouse report here
319 }
320 pointing_device_set_report(currentReport);
321 break;
322 //there is a case for button 3, but that's handled in dichotemy.c, and this is being
323 //disabled to avoid any conflict.
324 /*case MS_BTN3:
325 currentReport = pointing_device_get_report();
326 if (record->event.pressed) {
327 if (shift_held && shift_suspended){
328 register_code(KC_LSFT);
329 shift_suspended = false;
330 }
331 //update mouse report here
332 currentReport.buttons |= MOUSE_BTN3; //MOUSE_BTN2 is a const defined in report.h
333 } else {
334 //update mouse report here
335 }
336 pointing_device_set_report(currentReport);
337 break;*/
338
339 //If any other key was pressed during the layer mod hold period,
340 //then the layer mod was used momentarily, and should block latching
341 //Additionally, if NS_ keys are in use, then shift may be held (but is
342 //disabled for the unshifted keycodes to be send. Check the bool and
343 //register shift as necessary.
344 default:
345 if (shift_held){
346 register_code(KC_LSFT);
347 }
348 shift_singular_key = false;
349 number_singular_key = false;
350 mouse_singular_key = false;
351 break;
352 }
353 return true;
354};
355
356void matrix_scan_user(void) {
357 uint8_t layer = biton32(layer_state);
358 for (uint8_t i = 0; i<LONGPRESS_COUNT; i++){
359 if (timer_elapsed(special_timers[i]) >= LONGPRESS_DELAY && !special_key_states[i]){
360 switch (i + SAFE_RANGE){
361 case CK_1G:
362 register_code(KC_GRAVE);
363 break;
364 case CK_BSPE:
365 register_code(KC_ENTER);
366 break;
367 case CK_QE:
368 register_code(KC_ENTER);
369 break;
370 case CK_TE:
371 register_code(KC_ESCAPE);
372 break;
373 }
374 special_key_states[i] = 1;
375 }
376 }
377 switch (layer) {
378 case _BS:
379 set_led_off;
380 break;
381 case _NM:
382 set_led_blue;
383 break;
384 case _SF:
385 set_led_red;
386 break;
387 case _NS:
388 set_led_green;
389 break;
390 default:
391 break;
392 }
393};
394
diff --git a/keyboards/dichotemy/matrix.c b/keyboards/dichotemy/matrix.c
new file mode 100644
index 000000000..02e96e38c
--- /dev/null
+++ b/keyboards/dichotemy/matrix.c
@@ -0,0 +1,178 @@
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
30#if (MATRIX_COLS <= 8)
31# define print_matrix_header() print("\nr/c 01234567\n")
32# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
33# define matrix_bitpop(i) bitpop(matrix[i])
34# define ROW_SHIFTER ((uint8_t)1)
35#elif (MATRIX_COLS <= 16)
36# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
37# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
38# define matrix_bitpop(i) bitpop16(matrix[i])
39# define ROW_SHIFTER ((uint16_t)1)
40#elif (MATRIX_COLS <= 32)
41# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
42# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
43# define matrix_bitpop(i) bitpop32(matrix[i])
44# define ROW_SHIFTER ((uint32_t)1)
45#endif
46
47#define MAIN_ROWMASK 0xFFF0;
48#define LOWER_ROWMASK 0x1F80;
49
50/* matrix state(1:on, 0:off) */
51static matrix_row_t matrix[MATRIX_ROWS];
52
53__attribute__ ((weak))
54void matrix_init_quantum(void) {
55 matrix_init_kb();
56}
57
58__attribute__ ((weak))
59void matrix_scan_quantum(void) {
60 matrix_scan_kb();
61}
62
63__attribute__ ((weak))
64void matrix_init_kb(void) {
65 matrix_init_user();
66}
67
68__attribute__ ((weak))
69void matrix_scan_kb(void) {
70 matrix_scan_user();
71}
72
73__attribute__ ((weak))
74void matrix_init_user(void) {
75}
76
77__attribute__ ((weak))
78void matrix_scan_user(void) {
79}
80
81inline
82uint8_t matrix_rows(void) {
83 return MATRIX_ROWS;
84}
85
86inline
87uint8_t matrix_cols(void) {
88 return MATRIX_COLS;
89}
90
91void matrix_init(void) {
92
93 matrix_init_quantum();
94}
95
96uint8_t matrix_scan(void)
97{
98 SERIAL_UART_INIT();
99
100 uint32_t timeout = 0;
101
102 //the s character requests the RF slave to send the matrix
103 SERIAL_UART_DATA = 's';
104
105 //trust the external keystates entirely, erase the last data
106 uint8_t uart_data[7] = {0};
107
108 //there are 10 bytes corresponding to 10 columns, and an end byte
109 for (uint8_t i = 0; i < 7; i++) {
110 //wait for the serial data, timeout if it's been too long
111 //this only happened in testing with a loose wire, but does no
112 //harm to leave it in here
113 while(!SERIAL_UART_RXD_PRESENT){
114 timeout++;
115 if (timeout > 10000){
116 break;
117 }
118 }
119 uart_data[i] = SERIAL_UART_DATA;
120 }
121
122 //check for the end packet, the key state bytes use the LSBs, so 0xE0
123 //will only show up here if the correct bytes were recieved
124 if (uart_data[6] == 0x96) { //this is an arbitrary binary checksum (10010110)
125 //shifting and transferring the keystates to the QMK matrix variable
126 //bits 1-12 are row 1, 13-24 are row 2, 25-36 are row 3,
127 //bits 37-42 are row 4 (only 6 wide, 1-3 are 0, and 10-12 are 0)
128 //bits 43-48 are row 5 (same as row 4)
129 /* ASSUMING MSB FIRST */
130 matrix[0] = (((uint16_t) uart_data[0] << 8) | ((uint16_t) uart_data[1])) & MAIN_ROWMASK;
131 matrix[1] = ((uint16_t) uart_data[1] << 12) | ((uint16_t) uart_data[2] << 4);
132 matrix[2] = (((uint16_t) uart_data[3] << 8) | ((uint16_t) uart_data[4])) & MAIN_ROWMASK;
133 matrix[3] = (((uint16_t) uart_data[4] << 9) | ((uint16_t) uart_data[5] << 1)) & LOWER_ROWMASK;
134 matrix[4] = ((uint16_t) uart_data[5] << 7) & LOWER_ROWMASK;
135 /* OK, TURNS OUT THAT WAS A BAD ASSUMPTION */
136 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
137 //I've unpacked these into the mirror image of what QMK expects them to be, so...
138 matrix[i] = ((matrix[i] * 0x0802LU & 0x22110LU) | (matrix[i] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
139 //bithack mirror! Doesn't make any sense, but works - and efficiently.
140 }
141 }
142
143
144 matrix_scan_quantum();
145 return 1;
146}
147
148inline
149bool matrix_is_on(uint8_t row, uint8_t col)
150{
151 return (matrix[row] & ((matrix_row_t)1<col));
152}
153
154inline
155matrix_row_t matrix_get_row(uint8_t row)
156{
157 return matrix[row];
158}
159
160void matrix_print(void)
161{
162 print_matrix_header();
163
164 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
165 phex(row); print(": ");
166 print_matrix_row(row);
167 print("\n");
168 }
169}
170
171uint8_t matrix_key_count(void)
172{
173 uint8_t count = 0;
174 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
175 count += matrix_bitpop(i);
176 }
177 return count;
178}
diff --git a/keyboards/dichotemy/readme.md b/keyboards/dichotemy/readme.md
new file mode 100644
index 000000000..b30cf00cb
--- /dev/null
+++ b/keyboards/dichotemy/readme.md
@@ -0,0 +1,33 @@
1Dichotemy 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/dichotemy/rules.mk b/keyboards/dichotemy/rules.mk
new file mode 100644
index 000000000..c8a316f84
--- /dev/null
+++ b/keyboards/dichotemy/rules.mk
@@ -0,0 +1,82 @@
1
2OPT_DEFS += -DDICHOTEMY_PROMICRO
3OPT_DEFS += -DCATERINA_BOOTLOADER
4DICHOTEMY_UPLOAD_COMMAND = while [ ! -r $(USB) ]; do sleep 1; done; \
5 avrdude -p $(MCU) -c avr109 -U flash:w:$(TARGET).hex -P $(USB)
6
7# # project specific files
8SRC = matrix.c
9
10
11# MCU name
12#MCU = at90usb1287
13MCU = atmega32u4
14
15# Processor frequency.
16# This will define a symbol, F_CPU, in all source code files equal to the
17# processor frequency in Hz. You can then use this symbol in your source code to
18# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
19# automatically to create a 32-bit value in your source code.
20#
21# This will be an integer division of F_USB below, as it is sourced by
22# F_USB after it has run through any CPU prescalers. Note that this value
23# does not *change* the processor frequency - it should merely be updated to
24# reflect the processor speed set externally so that the code can use accurate
25# software delays.
26F_CPU = 16000000
27
28
29#
30# LUFA specific
31#
32# Target architecture (see library "Board Types" documentation).
33ARCH = AVR8
34
35# Input clock frequency.
36# This will define a symbol, F_USB, in all source code files equal to the
37# input clock frequency (before any prescaling is performed) in Hz. This value may
38# differ from F_CPU if prescaling is used on the latter, and is required as the
39# raw input clock is fed directly to the PLL sections of the AVR for high speed
40# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
41# at the end, this will be done automatically to create a 32-bit value in your
42# source code.
43#
44# If no clock division is performed on the input clock inside the AVR (via the
45# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
46F_USB = $(F_CPU)
47
48# Interrupt driven control endpoint task(+60)
49OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
50
51
52# Boot Section Size in *bytes*
53# Teensy halfKay 512
54# Teensy++ halfKay 1024
55# Atmel DFU loader 4096
56# LUFA bootloader 4096
57# USBaspLoader 2048
58OPT_DEFS += -DBOOTLOADER_SIZE=4096
59
60
61# Build Options
62# comment out to disable the options.
63#
64#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
65#MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
66POINTING_DEVICE_ENABLE = yes # Generic Pointer, not as big as mouse keys hopefully.
67EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
68CONSOLE_ENABLE = yes # Console for debug(+400)
69COMMAND_ENABLE = yes # Commands for debug and configuration
70CUSTOM_MATRIX = yes # Remote matrix from the wireless bridge
71# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
72# SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
73NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
74# BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
75# MIDI_ENABLE = YES # MIDI controls
76UNICODE_ENABLE = YES # Unicode
77# BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
78
79USB = /dev/ttyACM0
80
81#upload: build
82# $(DICHOTEMY_UPLOAD_COMMAND)
diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c
index 0aaab84cd..e60ae8d93 100644
--- a/quantum/pointing_device.c
+++ b/quantum/pointing_device.c
@@ -33,7 +33,7 @@ void pointing_device_init(void){
33__attribute__ ((weak)) 33__attribute__ ((weak))
34void pointing_device_send(void){ 34void pointing_device_send(void){
35 //If you need to do other things, like debugging, this is the place to do it. 35 //If you need to do other things, like debugging, this is the place to do it.
36 host_mouse_send(mouseReport); 36 host_mouse_send(&mouseReport);
37 //send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device 37 //send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
38 mouseReport.x = 0; 38 mouseReport.x = 0;
39 mouseReport.y = 0; 39 mouseReport.y = 0;