aboutsummaryrefslogtreecommitdiff
path: root/keyboards/orthodox
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/orthodox')
-rw-r--r--keyboards/orthodox/Makefile5
-rw-r--r--keyboards/orthodox/common/glcdfont.c276
-rw-r--r--keyboards/orthodox/config.h32
-rw-r--r--keyboards/orthodox/i2c.c162
-rw-r--r--keyboards/orthodox/i2c.h50
-rw-r--r--keyboards/orthodox/keymaps/i2c/config.h34
-rw-r--r--keyboards/orthodox/keymaps/i2c/keymap.c132
-rw-r--r--keyboards/orthodox/keymaps/serial/config.h34
-rw-r--r--keyboards/orthodox/keymaps/serial/keymap.c132
-rw-r--r--keyboards/orthodox/matrix.c351
-rw-r--r--keyboards/orthodox/orthodox.c1
-rw-r--r--keyboards/orthodox/orthodox.h30
-rw-r--r--keyboards/orthodox/pro_micro.h362
-rw-r--r--keyboards/orthodox/readme.md165
-rw-r--r--keyboards/orthodox/rev1/Makefile3
-rw-r--r--keyboards/orthodox/rev1/config.h99
-rw-r--r--keyboards/orthodox/rev1/rev1.c32
-rw-r--r--keyboards/orthodox/rev1/rev1.h25
-rw-r--r--keyboards/orthodox/rev1/rules.mk5
-rw-r--r--keyboards/orthodox/rules.mk87
-rw-r--r--keyboards/orthodox/serial.c230
-rw-r--r--keyboards/orthodox/serial.h27
-rw-r--r--keyboards/orthodox/split_util.c84
-rw-r--r--keyboards/orthodox/split_util.h24
-rw-r--r--keyboards/orthodox/ssd1306.c470
-rw-r--r--keyboards/orthodox/ssd1306.h17
26 files changed, 2869 insertions, 0 deletions
diff --git a/keyboards/orthodox/Makefile b/keyboards/orthodox/Makefile
new file mode 100644
index 000000000..f5c87d4d6
--- /dev/null
+++ b/keyboards/orthodox/Makefile
@@ -0,0 +1,5 @@
1SUBPROJECT_DEFAULT = rev2
2
3ifndef MAKEFILE_INCLUDED
4 include ../../Makefile
5endif
diff --git a/keyboards/orthodox/common/glcdfont.c b/keyboards/orthodox/common/glcdfont.c
new file mode 100644
index 000000000..6f88bd23a
--- /dev/null
+++ b/keyboards/orthodox/common/glcdfont.c
@@ -0,0 +1,276 @@
1// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
2// See gfxfont.h for newer custom bitmap font info.
3
4#ifndef FONT5X7_H
5#define FONT5X7_H
6
7#ifdef __AVR__
8 #include <avr/io.h>
9 #include <avr/pgmspace.h>
10#elif defined(ESP8266)
11 #include <pgmspace.h>
12#else
13 #define PROGMEM
14#endif
15
16// Standard ASCII 5x7 font
17
18static const unsigned char font[] PROGMEM = {
19 0x00, 0x00, 0x00, 0x00, 0x00,
20 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
21 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
22 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
23 0x18, 0x3C, 0x7E, 0x3C, 0x18,
24 0x1C, 0x57, 0x7D, 0x57, 0x1C,
25 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
26 0x00, 0x18, 0x3C, 0x18, 0x00,
27 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
28 0x00, 0x18, 0x24, 0x18, 0x00,
29 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
30 0x30, 0x48, 0x3A, 0x06, 0x0E,
31 0x26, 0x29, 0x79, 0x29, 0x26,
32 0x40, 0x7F, 0x05, 0x05, 0x07,
33 0x40, 0x7F, 0x05, 0x25, 0x3F,
34 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
35 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
36 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
37 0x14, 0x22, 0x7F, 0x22, 0x14,
38 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
39 0x06, 0x09, 0x7F, 0x01, 0x7F,
40 0x00, 0x66, 0x89, 0x95, 0x6A,
41 0x60, 0x60, 0x60, 0x60, 0x60,
42 0x94, 0xA2, 0xFF, 0xA2, 0x94,
43 0x08, 0x04, 0x7E, 0x04, 0x08,
44 0x10, 0x20, 0x7E, 0x20, 0x10,
45 0x08, 0x08, 0x2A, 0x1C, 0x08,
46 0x08, 0x1C, 0x2A, 0x08, 0x08,
47 0x1E, 0x10, 0x10, 0x10, 0x10,
48 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
49 0x30, 0x38, 0x3E, 0x38, 0x30,
50 0x06, 0x0E, 0x3E, 0x0E, 0x06,
51 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x5F, 0x00, 0x00,
53 0x00, 0x07, 0x00, 0x07, 0x00,
54 0x14, 0x7F, 0x14, 0x7F, 0x14,
55 0x24, 0x2A, 0x7F, 0x2A, 0x12,
56 0x23, 0x13, 0x08, 0x64, 0x62,
57 0x36, 0x49, 0x56, 0x20, 0x50,
58 0x00, 0x08, 0x07, 0x03, 0x00,
59 0x00, 0x1C, 0x22, 0x41, 0x00,
60 0x00, 0x41, 0x22, 0x1C, 0x00,
61 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
62 0x08, 0x08, 0x3E, 0x08, 0x08,
63 0x00, 0x80, 0x70, 0x30, 0x00,
64 0x08, 0x08, 0x08, 0x08, 0x08,
65 0x00, 0x00, 0x60, 0x60, 0x00,
66 0x20, 0x10, 0x08, 0x04, 0x02,
67 0x3E, 0x51, 0x49, 0x45, 0x3E,
68 0x00, 0x42, 0x7F, 0x40, 0x00,
69 0x72, 0x49, 0x49, 0x49, 0x46,
70 0x21, 0x41, 0x49, 0x4D, 0x33,
71 0x18, 0x14, 0x12, 0x7F, 0x10,
72 0x27, 0x45, 0x45, 0x45, 0x39,
73 0x3C, 0x4A, 0x49, 0x49, 0x31,
74 0x41, 0x21, 0x11, 0x09, 0x07,
75 0x36, 0x49, 0x49, 0x49, 0x36,
76 0x46, 0x49, 0x49, 0x29, 0x1E,
77 0x00, 0x00, 0x14, 0x00, 0x00,
78 0x00, 0x40, 0x34, 0x00, 0x00,
79 0x00, 0x08, 0x14, 0x22, 0x41,
80 0x14, 0x14, 0x14, 0x14, 0x14,
81 0x00, 0x41, 0x22, 0x14, 0x08,
82 0x02, 0x01, 0x59, 0x09, 0x06,
83 0x3E, 0x41, 0x5D, 0x59, 0x4E,
84 0x7C, 0x12, 0x11, 0x12, 0x7C,
85 0x7F, 0x49, 0x49, 0x49, 0x36,
86 0x3E, 0x41, 0x41, 0x41, 0x22,
87 0x7F, 0x41, 0x41, 0x41, 0x3E,
88 0x7F, 0x49, 0x49, 0x49, 0x41,
89 0x7F, 0x09, 0x09, 0x09, 0x01,
90 0x3E, 0x41, 0x41, 0x51, 0x73,
91 0x7F, 0x08, 0x08, 0x08, 0x7F,
92 0x00, 0x41, 0x7F, 0x41, 0x00,
93 0x20, 0x40, 0x41, 0x3F, 0x01,
94 0x7F, 0x08, 0x14, 0x22, 0x41,
95 0x7F, 0x40, 0x40, 0x40, 0x40,
96 0x7F, 0x02, 0x1C, 0x02, 0x7F,
97 0x7F, 0x04, 0x08, 0x10, 0x7F,
98 0x3E, 0x41, 0x41, 0x41, 0x3E,
99 0x7F, 0x09, 0x09, 0x09, 0x06,
100 0x3E, 0x41, 0x51, 0x21, 0x5E,
101 0x7F, 0x09, 0x19, 0x29, 0x46,
102 0x26, 0x49, 0x49, 0x49, 0x32,
103 0x03, 0x01, 0x7F, 0x01, 0x03,
104 0x3F, 0x40, 0x40, 0x40, 0x3F,
105 0x1F, 0x20, 0x40, 0x20, 0x1F,
106 0x3F, 0x40, 0x38, 0x40, 0x3F,
107 0x63, 0x14, 0x08, 0x14, 0x63,
108 0x03, 0x04, 0x78, 0x04, 0x03,
109 0x61, 0x59, 0x49, 0x4D, 0x43,
110 0x00, 0x7F, 0x41, 0x41, 0x41,
111 0x02, 0x04, 0x08, 0x10, 0x20,
112 0x00, 0x41, 0x41, 0x41, 0x7F,
113 0x04, 0x02, 0x01, 0x02, 0x04,
114 0x40, 0x40, 0x40, 0x40, 0x40,
115 0x00, 0x03, 0x07, 0x08, 0x00,
116 0x20, 0x54, 0x54, 0x78, 0x40,
117 0x7F, 0x28, 0x44, 0x44, 0x38,
118 0x38, 0x44, 0x44, 0x44, 0x28,
119 0x38, 0x44, 0x44, 0x28, 0x7F,
120 0x38, 0x54, 0x54, 0x54, 0x18,
121 0x00, 0x08, 0x7E, 0x09, 0x02,
122 0x18, 0xA4, 0xA4, 0x9C, 0x78,
123 0x7F, 0x08, 0x04, 0x04, 0x78,
124 0x00, 0x44, 0x7D, 0x40, 0x00,
125 0x20, 0x40, 0x40, 0x3D, 0x00,
126 0x7F, 0x10, 0x28, 0x44, 0x00,
127 0x00, 0x41, 0x7F, 0x40, 0x00,
128 0x7C, 0x04, 0x78, 0x04, 0x78,
129 0x7C, 0x08, 0x04, 0x04, 0x78,
130 0x38, 0x44, 0x44, 0x44, 0x38,
131 0xFC, 0x18, 0x24, 0x24, 0x18,
132 0x18, 0x24, 0x24, 0x18, 0xFC,
133 0x7C, 0x08, 0x04, 0x04, 0x08,
134 0x48, 0x54, 0x54, 0x54, 0x24,
135 0x04, 0x04, 0x3F, 0x44, 0x24,
136 0x3C, 0x40, 0x40, 0x20, 0x7C,
137 0x1C, 0x20, 0x40, 0x20, 0x1C,
138 0x3C, 0x40, 0x30, 0x40, 0x3C,
139 0x44, 0x28, 0x10, 0x28, 0x44,
140 0x4C, 0x90, 0x90, 0x90, 0x7C,
141 0x44, 0x64, 0x54, 0x4C, 0x44,
142 0x00, 0x08, 0x36, 0x41, 0x00,
143 0x00, 0x00, 0x77, 0x00, 0x00,
144 0x00, 0x41, 0x36, 0x08, 0x00,
145 0x02, 0x01, 0x02, 0x04, 0x02,
146 0x3C, 0x26, 0x23, 0x26, 0x3C,
147 0x1E, 0xA1, 0xA1, 0x61, 0x12,
148 0x3A, 0x40, 0x40, 0x20, 0x7A,
149 0x38, 0x54, 0x54, 0x55, 0x59,
150 0x21, 0x55, 0x55, 0x79, 0x41,
151 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
152 0x21, 0x55, 0x54, 0x78, 0x40,
153 0x20, 0x54, 0x55, 0x79, 0x40,
154 0x0C, 0x1E, 0x52, 0x72, 0x12,
155 0x39, 0x55, 0x55, 0x55, 0x59,
156 0x39, 0x54, 0x54, 0x54, 0x59,
157 0x39, 0x55, 0x54, 0x54, 0x58,
158 0x00, 0x00, 0x45, 0x7C, 0x41,
159 0x00, 0x02, 0x45, 0x7D, 0x42,
160 0x00, 0x01, 0x45, 0x7C, 0x40,
161 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
162 0xF0, 0x28, 0x25, 0x28, 0xF0,
163 0x7C, 0x54, 0x55, 0x45, 0x00,
164 0x20, 0x54, 0x54, 0x7C, 0x54,
165 0x7C, 0x0A, 0x09, 0x7F, 0x49,
166 0x32, 0x49, 0x49, 0x49, 0x32,
167 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
168 0x32, 0x4A, 0x48, 0x48, 0x30,
169 0x3A, 0x41, 0x41, 0x21, 0x7A,
170 0x3A, 0x42, 0x40, 0x20, 0x78,
171 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
172 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
173 0x3D, 0x40, 0x40, 0x40, 0x3D,
174 0x3C, 0x24, 0xFF, 0x24, 0x24,
175 0x48, 0x7E, 0x49, 0x43, 0x66,
176 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
177 0xFF, 0x09, 0x29, 0xF6, 0x20,
178 0xC0, 0x88, 0x7E, 0x09, 0x03,
179 0x20, 0x54, 0x54, 0x79, 0x41,
180 0x00, 0x00, 0x44, 0x7D, 0x41,
181 0x30, 0x48, 0x48, 0x4A, 0x32,
182 0x38, 0x40, 0x40, 0x22, 0x7A,
183 0x00, 0x7A, 0x0A, 0x0A, 0x72,
184 0x7D, 0x0D, 0x19, 0x31, 0x7D,
185 0x26, 0x29, 0x29, 0x2F, 0x28,
186 0x26, 0x29, 0x29, 0x29, 0x26,
187 0x30, 0x48, 0x4D, 0x40, 0x20,
188 0x38, 0x08, 0x08, 0x08, 0x08,
189 0x08, 0x08, 0x08, 0x08, 0x38,
190 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
191 0x2F, 0x10, 0x28, 0x34, 0xFA,
192 0x00, 0x00, 0x7B, 0x00, 0x00,
193 0x08, 0x14, 0x2A, 0x14, 0x22,
194 0x22, 0x14, 0x2A, 0x14, 0x08,
195 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
196 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
197 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
198 0x00, 0x00, 0x00, 0xFF, 0x00,
199 0x10, 0x10, 0x10, 0xFF, 0x00,
200 0x14, 0x14, 0x14, 0xFF, 0x00,
201 0x10, 0x10, 0xFF, 0x00, 0xFF,
202 0x10, 0x10, 0xF0, 0x10, 0xF0,
203 0x14, 0x14, 0x14, 0xFC, 0x00,
204 0x14, 0x14, 0xF7, 0x00, 0xFF,
205 0x00, 0x00, 0xFF, 0x00, 0xFF,
206 0x14, 0x14, 0xF4, 0x04, 0xFC,
207 0x14, 0x14, 0x17, 0x10, 0x1F,
208 0x10, 0x10, 0x1F, 0x10, 0x1F,
209 0x14, 0x14, 0x14, 0x1F, 0x00,
210 0x10, 0x10, 0x10, 0xF0, 0x00,
211 0x00, 0x00, 0x00, 0x1F, 0x10,
212 0x10, 0x10, 0x10, 0x1F, 0x10,
213 0x10, 0x10, 0x10, 0xF0, 0x10,
214 0x00, 0x00, 0x00, 0xFF, 0x10,
215 0x10, 0x10, 0x10, 0x10, 0x10,
216 0x10, 0x10, 0x10, 0xFF, 0x10,
217 0x00, 0x00, 0x00, 0xFF, 0x14,
218 0x00, 0x00, 0xFF, 0x00, 0xFF,
219 0x00, 0x00, 0x1F, 0x10, 0x17,
220 0x00, 0x00, 0xFC, 0x04, 0xF4,
221 0x14, 0x14, 0x17, 0x10, 0x17,
222 0x14, 0x14, 0xF4, 0x04, 0xF4,
223 0x00, 0x00, 0xFF, 0x00, 0xF7,
224 0x14, 0x14, 0x14, 0x14, 0x14,
225 0x14, 0x14, 0xF7, 0x00, 0xF7,
226 0x14, 0x14, 0x14, 0x17, 0x14,
227 0x10, 0x10, 0x1F, 0x10, 0x1F,
228 0x14, 0x14, 0x14, 0xF4, 0x14,
229 0x10, 0x10, 0xF0, 0x10, 0xF0,
230 0x00, 0x00, 0x1F, 0x10, 0x1F,
231 0x00, 0x00, 0x00, 0x1F, 0x14,
232 0x00, 0x00, 0x00, 0xFC, 0x14,
233 0x00, 0x00, 0xF0, 0x10, 0xF0,
234 0x10, 0x10, 0xFF, 0x10, 0xFF,
235 0x14, 0x14, 0x14, 0xFF, 0x14,
236 0x10, 0x10, 0x10, 0x1F, 0x00,
237 0x00, 0x00, 0x00, 0xF0, 0x10,
238 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
239 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
240 0xFF, 0xFF, 0xFF, 0x00, 0x00,
241 0x00, 0x00, 0x00, 0xFF, 0xFF,
242 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
243 0x38, 0x44, 0x44, 0x38, 0x44,
244 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
245 0x7E, 0x02, 0x02, 0x06, 0x06,
246 0x02, 0x7E, 0x02, 0x7E, 0x02,
247 0x63, 0x55, 0x49, 0x41, 0x63,
248 0x38, 0x44, 0x44, 0x3C, 0x04,
249 0x40, 0x7E, 0x20, 0x1E, 0x20,
250 0x06, 0x02, 0x7E, 0x02, 0x02,
251 0x99, 0xA5, 0xE7, 0xA5, 0x99,
252 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
253 0x4C, 0x72, 0x01, 0x72, 0x4C,
254 0x30, 0x4A, 0x4D, 0x4D, 0x30,
255 0x30, 0x48, 0x78, 0x48, 0x30,
256 0xBC, 0x62, 0x5A, 0x46, 0x3D,
257 0x3E, 0x49, 0x49, 0x49, 0x00,
258 0x7E, 0x01, 0x01, 0x01, 0x7E,
259 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
260 0x44, 0x44, 0x5F, 0x44, 0x44,
261 0x40, 0x51, 0x4A, 0x44, 0x40,
262 0x40, 0x44, 0x4A, 0x51, 0x40,
263 0x00, 0x00, 0xFF, 0x01, 0x03,
264 0xE0, 0x80, 0xFF, 0x00, 0x00,
265 0x08, 0x08, 0x6B, 0x6B, 0x08,
266 0x36, 0x12, 0x36, 0x24, 0x36,
267 0x06, 0x0F, 0x09, 0x0F, 0x06,
268 0x00, 0x00, 0x18, 0x18, 0x00,
269 0x00, 0x00, 0x10, 0x10, 0x00,
270 0x30, 0x40, 0xFF, 0x01, 0x01,
271 0x00, 0x1F, 0x01, 0x01, 0x1E,
272 0x00, 0x19, 0x1D, 0x17, 0x12,
273 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
274 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
275};
276#endif // FONT5X7_H
diff --git a/keyboards/orthodox/config.h b/keyboards/orthodox/config.h
new file mode 100644
index 000000000..008fb0978
--- /dev/null
+++ b/keyboards/orthodox/config.h
@@ -0,0 +1,32 @@
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#ifdef SUBPROJECT_rev1
24 #include "rev1/config.h"
25#endif
26#ifdef SUBPROJECT_rev2
27 #include "rev2/config.h"
28#endif
29#ifdef SUBPROJECT_rev2fliphalf
30 #include "../../rev2fliphalf/config.h"
31#endif
32#endif
diff --git a/keyboards/orthodox/i2c.c b/keyboards/orthodox/i2c.c
new file mode 100644
index 000000000..084c890c4
--- /dev/null
+++ b/keyboards/orthodox/i2c.c
@@ -0,0 +1,162 @@
1#include <util/twi.h>
2#include <avr/io.h>
3#include <stdlib.h>
4#include <avr/interrupt.h>
5#include <util/twi.h>
6#include <stdbool.h>
7#include "i2c.h"
8
9#ifdef USE_I2C
10
11// Limits the amount of we wait for any one i2c transaction.
12// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
13// 9 bits, a single transaction will take around 90μs to complete.
14//
15// (F_CPU/SCL_CLOCK) => # of μC cycles to transfer a bit
16// poll loop takes at least 8 clock cycles to execute
17#define I2C_LOOP_TIMEOUT (9+1)*(F_CPU/SCL_CLOCK)/8
18
19#define BUFFER_POS_INC() (slave_buffer_pos = (slave_buffer_pos+1)%SLAVE_BUFFER_SIZE)
20
21volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
22
23static volatile uint8_t slave_buffer_pos;
24static volatile bool slave_has_register_set = false;
25
26// Wait for an i2c operation to finish
27inline static
28void i2c_delay(void) {
29 uint16_t lim = 0;
30 while(!(TWCR & (1<<TWINT)) && lim < I2C_LOOP_TIMEOUT)
31 lim++;
32
33 // easier way, but will wait slightly longer
34 // _delay_us(100);
35}
36
37// Setup twi to run at 100kHz
38void i2c_master_init(void) {
39 // no prescaler
40 TWSR = 0;
41 // Set TWI clock frequency to SCL_CLOCK. Need TWBR>10.
42 // Check datasheets for more info.
43 TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
44}
45
46// Start a transaction with the given i2c slave address. The direction of the
47// transfer is set with I2C_READ and I2C_WRITE.
48// returns: 0 => success
49// 1 => error
50uint8_t i2c_master_start(uint8_t address) {
51 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
52
53 i2c_delay();
54
55 // check that we started successfully
56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
57 return 1;
58
59 TWDR = address;
60 TWCR = (1<<TWINT) | (1<<TWEN);
61
62 i2c_delay();
63
64 if ( (TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) )
65 return 1; // slave did not acknowledge
66 else
67 return 0; // success
68}
69
70
71// Finish the i2c transaction.
72void i2c_master_stop(void) {
73 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
74
75 uint16_t lim = 0;
76 while(!(TWCR & (1<<TWSTO)) && lim < I2C_LOOP_TIMEOUT)
77 lim++;
78}
79
80// Write one byte to the i2c slave.
81// returns 0 => slave ACK
82// 1 => slave NACK
83uint8_t i2c_master_write(uint8_t data) {
84 TWDR = data;
85 TWCR = (1<<TWINT) | (1<<TWEN);
86
87 i2c_delay();
88
89 // check if the slave acknowledged us
90 return (TW_STATUS == TW_MT_DATA_ACK) ? 0 : 1;
91}
92
93// Read one byte from the i2c slave. If ack=1 the slave is acknowledged,
94// if ack=0 the acknowledge bit is not set.
95// returns: byte read from i2c device
96uint8_t i2c_master_read(int ack) {
97 TWCR = (1<<TWINT) | (1<<TWEN) | (ack<<TWEA);
98
99 i2c_delay();
100 return TWDR;
101}
102
103void i2c_reset_state(void) {
104 TWCR = 0;
105}
106
107void i2c_slave_init(uint8_t address) {
108 TWAR = address << 0; // slave i2c address
109 // TWEN - twi enable
110 // TWEA - enable address acknowledgement
111 // TWINT - twi interrupt flag
112 // TWIE - enable the twi interrupt
113 TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
114}
115
116ISR(TWI_vect);
117
118ISR(TWI_vect) {
119 uint8_t ack = 1;
120 switch(TW_STATUS) {
121 case TW_SR_SLA_ACK:
122 // this device has been addressed as a slave receiver
123 slave_has_register_set = false;
124 break;
125
126 case TW_SR_DATA_ACK:
127 // this device has received data as a slave receiver
128 // The first byte that we receive in this transaction sets the location
129 // of the read/write location of the slaves memory that it exposes over
130 // i2c. After that, bytes will be written at slave_buffer_pos, incrementing
131 // slave_buffer_pos after each write.
132 if(!slave_has_register_set) {
133 slave_buffer_pos = TWDR;
134 // don't acknowledge the master if this memory loctaion is out of bounds
135 if ( slave_buffer_pos >= SLAVE_BUFFER_SIZE ) {
136 ack = 0;
137 slave_buffer_pos = 0;
138 }
139 slave_has_register_set = true;
140 } else {
141 i2c_slave_buffer[slave_buffer_pos] = TWDR;
142 BUFFER_POS_INC();
143 }
144 break;
145
146 case TW_ST_SLA_ACK:
147 case TW_ST_DATA_ACK:
148 // master has addressed this device as a slave transmitter and is
149 // requesting data.
150 TWDR = i2c_slave_buffer[slave_buffer_pos];
151 BUFFER_POS_INC();
152 break;
153
154 case TW_BUS_ERROR: // something went wrong, reset twi state
155 TWCR = 0;
156 default:
157 break;
158 }
159 // Reset everything, so we are ready for the next TWI interrupt
160 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
161}
162#endif
diff --git a/keyboards/orthodox/i2c.h b/keyboards/orthodox/i2c.h
new file mode 100644
index 000000000..2af843ff6
--- /dev/null
+++ b/keyboards/orthodox/i2c.h
@@ -0,0 +1,50 @@
1#ifndef I2C_H
2#define I2C_H
3
4#include <stdint.h>
5#include "matrix.h"
6
7#ifndef F_CPU
8#define F_CPU 16000000UL
9#endif
10
11#define I2C_READ 1
12#define I2C_WRITE 0
13
14#define I2C_ACK 1
15#define I2C_NACK 0
16
17#define SLAVE_BUFFER_SIZE 0x10
18
19// i2c SCL clock frequency
20#define SCL_CLOCK 100000UL
21
22extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
23
24void i2c_master_init(void);
25uint8_t i2c_master_start(uint8_t address);
26void i2c_master_stop(void);
27uint8_t i2c_master_write(uint8_t data);
28uint8_t i2c_master_read(int);
29void i2c_reset_state(void);
30void i2c_slave_init(uint8_t address);
31
32
33static inline unsigned char i2c_start_read(unsigned char addr) {
34 return i2c_master_start((addr << 1) | I2C_READ);
35}
36
37static inline unsigned char i2c_start_write(unsigned char addr) {
38 return i2c_master_start((addr << 1) | I2C_WRITE);
39}
40
41// from SSD1306 scrips
42extern unsigned char i2c_rep_start(unsigned char addr);
43extern void i2c_start_wait(unsigned char addr);
44extern unsigned char i2c_readAck(void);
45extern unsigned char i2c_readNak(void);
46extern unsigned char i2c_read(unsigned char ack);
47
48#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
49
50#endif
diff --git a/keyboards/orthodox/keymaps/i2c/config.h b/keyboards/orthodox/keymaps/i2c/config.h
new file mode 100644
index 000000000..542529719
--- /dev/null
+++ b/keyboards/orthodox/keymaps/i2c/config.h
@@ -0,0 +1,34 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18
19#define USE_I2C
20
21//#define MASTER_LEFT
22//#define _MASTER_RIGHT
23#define EE_HANDS
24
25
26#ifdef SUBPROJECT_rev1
27 #include "../../rev1/config.h"
28#endif
29#ifdef SUBPROJECT_rev2
30 #include "../../rev2/config.h"
31#endif
32#ifdef SUBPROJECT_rev2fliphalf
33 #include "../../rev2fliphalf/config.h"
34#endif
diff --git a/keyboards/orthodox/keymaps/i2c/keymap.c b/keyboards/orthodox/keymaps/i2c/keymap.c
new file mode 100644
index 000000000..ed24a3a1f
--- /dev/null
+++ b/keyboards/orthodox/keymaps/i2c/keymap.c
@@ -0,0 +1,132 @@
1#include "orthodox.h"
2#include "action_layer.h"
3#include "eeconfig.h"
4
5extern keymap_config_t keymap_config;
6
7// Each layer gets a name for readability, which is then used in the keymap matrix below.
8// The underscores don't mean anything - you can have a layer called STUFF or any other name.
9// Layer names don't all need to be of the same length, obviously, and you can also skip them
10// entirely and just use numbers.
11#define _QWERTY 0
12#define _COLEMAK 1
13#define _DVORAK 2
14#define _LOWER 3
15#define _RAISE 4
16#define _ADJUST 16
17
18enum custom_keycodes {
19 QWERTY = SAFE_RANGE,
20 COLEMAK,
21 DVORAK,
22 LOWER,
23 RAISE,
24 ADJUST,
25};
26
27// Fillers to make layering more clear
28#define _______ KC_TRNS
29#define XXXXXXX KC_NO
30
31#define LS__SPC MT(MOD_LSFT, KC_SPC)
32
33const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
34
35[_QWERTY] = KEYMAP( \
36 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
37 KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_LEFT, XXXXXXX, KC_DOWN, KC_UP, XXXXXXX, KC_RIGHT,KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
38 KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, LOWER, KC_BSPC, KC_ENT, KC_RALT, LS__SPC, RAISE, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_LGUI \
39),
40
41[_LOWER] = KEYMAP( \
42 KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, \
43 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_LCTL, XXXXXXX, _______, _______, XXXXXXX, KC_RCTL, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
44 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, _______, _______, _______, _______, KC_F12, KC_HOME, KC_COMM, KC_DOT, KC_END, _______ \
45),
46
47[_RAISE] = KEYMAP( \
48 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \
49 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, _______, XXXXXXX, _______, _______, XXXXXXX, _______, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
50 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, _______, _______, _______, _______, KC_F12, KC_PGUP, KC_COMM, KC_DOT, KC_PGDN, _______ \
51),
52
53[_ADJUST] = KEYMAP( \
54 _______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL, \
55 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, _______, XXXXXXX, _______, _______, XXXXXXX, _______, AG_SWAP, QWERTY , COLEMAK, DVORAK, _______, _______, \
56 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \
57)
58
59
60};
61
62#ifdef AUDIO_ENABLE
63float tone_qwerty[][2] = SONG(QWERTY_SOUND);
64float tone_dvorak[][2] = SONG(DVORAK_SOUND);
65float tone_colemak[][2] = SONG(COLEMAK_SOUND);
66#endif
67
68void persistent_default_layer_set(uint16_t default_layer) {
69 eeconfig_update_default_layer(default_layer);
70 default_layer_set(default_layer);
71}
72
73bool process_record_user(uint16_t keycode, keyrecord_t *record) {
74 switch (keycode) {
75 case QWERTY:
76 if (record->event.pressed) {
77 #ifdef AUDIO_ENABLE
78 PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
79 #endif
80 persistent_default_layer_set(1UL<<_QWERTY);
81 }
82 return false;
83 break;
84 case COLEMAK:
85 if (record->event.pressed) {
86 #ifdef AUDIO_ENABLE
87 PLAY_NOTE_ARRAY(tone_colemak, false, 0);
88 #endif
89 persistent_default_layer_set(1UL<<_COLEMAK);
90 }
91 return false;
92 break;
93 case DVORAK:
94 if (record->event.pressed) {
95 #ifdef AUDIO_ENABLE
96 PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
97 #endif
98 persistent_default_layer_set(1UL<<_DVORAK);
99 }
100 return false;
101 break;
102 case LOWER:
103 if (record->event.pressed) {
104 layer_on(_LOWER);
105 update_tri_layer(_LOWER, _RAISE, _ADJUST);
106 } else {
107 layer_off(_LOWER);
108 update_tri_layer(_LOWER, _RAISE, _ADJUST);
109 }
110 return false;
111 break;
112 case RAISE:
113 if (record->event.pressed) {
114 layer_on(_RAISE);
115 update_tri_layer(_LOWER, _RAISE, _ADJUST);
116 } else {
117 layer_off(_RAISE);
118 update_tri_layer(_LOWER, _RAISE, _ADJUST);
119 }
120 return false;
121 break;
122 case ADJUST:
123 if (record->event.pressed) {
124 layer_on(_ADJUST);
125 } else {
126 layer_off(_ADJUST);
127 }
128 return false;
129 break;
130 }
131 return true;
132}
diff --git a/keyboards/orthodox/keymaps/serial/config.h b/keyboards/orthodox/keymaps/serial/config.h
new file mode 100644
index 000000000..5169452ba
--- /dev/null
+++ b/keyboards/orthodox/keymaps/serial/config.h
@@ -0,0 +1,34 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18
19#define USE_SERIAL
20
21//#define MASTER_LEFT
22//#define _MASTER_RIGHT
23#define EE_HANDS
24
25
26#ifdef SUBPROJECT_rev1
27 #include "../../rev1/config.h"
28#endif
29#ifdef SUBPROJECT_rev2
30 #include "../../rev2/config.h"
31#endif
32#ifdef SUBPROJECT_rev2fliphalf
33 #include "../../rev2fliphalf/config.h"
34#endif
diff --git a/keyboards/orthodox/keymaps/serial/keymap.c b/keyboards/orthodox/keymaps/serial/keymap.c
new file mode 100644
index 000000000..ed24a3a1f
--- /dev/null
+++ b/keyboards/orthodox/keymaps/serial/keymap.c
@@ -0,0 +1,132 @@
1#include "orthodox.h"
2#include "action_layer.h"
3#include "eeconfig.h"
4
5extern keymap_config_t keymap_config;
6
7// Each layer gets a name for readability, which is then used in the keymap matrix below.
8// The underscores don't mean anything - you can have a layer called STUFF or any other name.
9// Layer names don't all need to be of the same length, obviously, and you can also skip them
10// entirely and just use numbers.
11#define _QWERTY 0
12#define _COLEMAK 1
13#define _DVORAK 2
14#define _LOWER 3
15#define _RAISE 4
16#define _ADJUST 16
17
18enum custom_keycodes {
19 QWERTY = SAFE_RANGE,
20 COLEMAK,
21 DVORAK,
22 LOWER,
23 RAISE,
24 ADJUST,
25};
26
27// Fillers to make layering more clear
28#define _______ KC_TRNS
29#define XXXXXXX KC_NO
30
31#define LS__SPC MT(MOD_LSFT, KC_SPC)
32
33const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
34
35[_QWERTY] = KEYMAP( \
36 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, \
37 KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_LEFT, XXXXXXX, KC_DOWN, KC_UP, XXXXXXX, KC_RIGHT,KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, \
38 KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, LOWER, KC_BSPC, KC_ENT, KC_RALT, LS__SPC, RAISE, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_LGUI \
39),
40
41[_LOWER] = KEYMAP( \
42 KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, \
43 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_LCTL, XXXXXXX, _______, _______, XXXXXXX, KC_RCTL, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, \
44 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, _______, _______, _______, _______, KC_F12, KC_HOME, KC_COMM, KC_DOT, KC_END, _______ \
45),
46
47[_RAISE] = KEYMAP( \
48 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, \
49 KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, _______, XXXXXXX, _______, _______, XXXXXXX, _______, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, \
50 _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, _______, _______, _______, _______, _______, KC_F12, KC_PGUP, KC_COMM, KC_DOT, KC_PGDN, _______ \
51),
52
53[_ADJUST] = KEYMAP( \
54 _______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL, \
55 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, _______, XXXXXXX, _______, _______, XXXXXXX, _______, AG_SWAP, QWERTY , COLEMAK, DVORAK, _______, _______, \
56 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY \
57)
58
59
60};
61
62#ifdef AUDIO_ENABLE
63float tone_qwerty[][2] = SONG(QWERTY_SOUND);
64float tone_dvorak[][2] = SONG(DVORAK_SOUND);
65float tone_colemak[][2] = SONG(COLEMAK_SOUND);
66#endif
67
68void persistent_default_layer_set(uint16_t default_layer) {
69 eeconfig_update_default_layer(default_layer);
70 default_layer_set(default_layer);
71}
72
73bool process_record_user(uint16_t keycode, keyrecord_t *record) {
74 switch (keycode) {
75 case QWERTY:
76 if (record->event.pressed) {
77 #ifdef AUDIO_ENABLE
78 PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
79 #endif
80 persistent_default_layer_set(1UL<<_QWERTY);
81 }
82 return false;
83 break;
84 case COLEMAK:
85 if (record->event.pressed) {
86 #ifdef AUDIO_ENABLE
87 PLAY_NOTE_ARRAY(tone_colemak, false, 0);
88 #endif
89 persistent_default_layer_set(1UL<<_COLEMAK);
90 }
91 return false;
92 break;
93 case DVORAK:
94 if (record->event.pressed) {
95 #ifdef AUDIO_ENABLE
96 PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
97 #endif
98 persistent_default_layer_set(1UL<<_DVORAK);
99 }
100 return false;
101 break;
102 case LOWER:
103 if (record->event.pressed) {
104 layer_on(_LOWER);
105 update_tri_layer(_LOWER, _RAISE, _ADJUST);
106 } else {
107 layer_off(_LOWER);
108 update_tri_layer(_LOWER, _RAISE, _ADJUST);
109 }
110 return false;
111 break;
112 case RAISE:
113 if (record->event.pressed) {
114 layer_on(_RAISE);
115 update_tri_layer(_LOWER, _RAISE, _ADJUST);
116 } else {
117 layer_off(_RAISE);
118 update_tri_layer(_LOWER, _RAISE, _ADJUST);
119 }
120 return false;
121 break;
122 case ADJUST:
123 if (record->event.pressed) {
124 layer_on(_ADJUST);
125 } else {
126 layer_off(_ADJUST);
127 }
128 return false;
129 break;
130 }
131 return true;
132}
diff --git a/keyboards/orthodox/matrix.c b/keyboards/orthodox/matrix.c
new file mode 100644
index 000000000..3b60cead8
--- /dev/null
+++ b/keyboards/orthodox/matrix.c
@@ -0,0 +1,351 @@
1/*
2Copyright 2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * scan matrix
20 */
21#include <stdint.h>
22#include <stdbool.h>
23#ifdef USE_I2C
24// provides memcpy for copying TWI slave buffer
25// #include <string.h>
26#endif
27#include <avr/io.h>
28#include <avr/wdt.h>
29#include <avr/interrupt.h>
30#include <util/delay.h>
31#include "print.h"
32#include "debug.h"
33#include "util.h"
34#include "matrix.h"
35#include "split_util.h"
36#include "pro_micro.h"
37#include "config.h"
38
39#ifdef USE_I2C
40# include "i2c.h"
41#else // USE_SERIAL
42# include "serial.h"
43#endif
44
45#ifndef DEBOUNCE
46# define DEBOUNCE 5
47#endif
48
49#define ERROR_DISCONNECT_COUNT 5
50
51static uint8_t debouncing = DEBOUNCE;
52static const int ROWS_PER_HAND = MATRIX_ROWS/2;
53static uint8_t error_count = 0;
54
55static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
56static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
57
58/* matrix state(1:on, 0:off) */
59static matrix_row_t matrix[MATRIX_ROWS];
60static matrix_row_t matrix_debouncing[MATRIX_ROWS];
61
62static matrix_row_t read_cols(void);
63static void init_cols(void);
64static void unselect_rows(void);
65static void select_row(uint8_t row);
66
67__attribute__ ((weak))
68void matrix_init_quantum(void) {
69 matrix_init_kb();
70}
71
72__attribute__ ((weak))
73void matrix_scan_quantum(void) {
74 matrix_scan_kb();
75}
76
77__attribute__ ((weak))
78void matrix_init_kb(void) {
79 matrix_init_user();
80}
81
82__attribute__ ((weak))
83void matrix_scan_kb(void) {
84 matrix_scan_user();
85}
86
87__attribute__ ((weak))
88void matrix_init_user(void) {
89}
90
91__attribute__ ((weak))
92void matrix_scan_user(void) {
93}
94
95inline
96uint8_t matrix_rows(void)
97{
98 return MATRIX_ROWS;
99}
100
101inline
102uint8_t matrix_cols(void)
103{
104 return MATRIX_COLS;
105}
106
107void matrix_init(void)
108{
109 debug_enable = true;
110 debug_matrix = true;
111 debug_mouse = true;
112 // initialize row and col
113 unselect_rows();
114 init_cols();
115
116 TX_RX_LED_INIT;
117
118 // initialize matrix state: all keys off
119 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
120 matrix[i] = 0;
121 matrix_debouncing[i] = 0;
122 }
123
124 matrix_init_quantum();
125}
126
127uint8_t _matrix_scan(void)
128{
129 // Right hand is stored after the left in the matrix so, we need to offset it
130 int offset = isLeftHand ? 0 : (ROWS_PER_HAND);
131
132 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
133 select_row(i);
134 _delay_us(30); // without this wait read unstable value.
135 matrix_row_t cols = read_cols();
136 if (matrix_debouncing[i+offset] != cols) {
137 matrix_debouncing[i+offset] = cols;
138 debouncing = DEBOUNCE;
139 }
140 unselect_rows();
141 }
142
143 if (debouncing) {
144 if (--debouncing) {
145 _delay_ms(1);
146 } else {
147 for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
148 matrix[i+offset] = matrix_debouncing[i+offset];
149 }
150 }
151 }
152
153 return 1;
154}
155
156#ifdef USE_I2C
157
158// Get rows from other half over i2c
159int i2c_transaction(void) {
160 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
161
162 int err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_WRITE);
163 if (err) goto i2c_error;
164
165 // start of matrix stored at 0x00
166 err = i2c_master_write(0x00);
167 if (err) goto i2c_error;
168
169 // Start read
170 err = i2c_master_start(SLAVE_I2C_ADDRESS + I2C_READ);
171 if (err) goto i2c_error;
172
173 if (!err) {
174 /*
175 // read from TWI byte-by-byte into matrix_row_t memory space
176 size_t i;
177 for (i = 0; i < SLAVE_BUFFER_SIZE-1; ++i) {
178 *((uint8_t*)&matrix[slaveOffset]+i) = i2c_master_read(I2C_ACK);
179 }
180 // last byte to be read / end of chunk
181 *((uint8_t*)&matrix[slaveOffset]+i) = i2c_master_read(I2C_NACK);
182 */
183
184 // kludge for column #9: unpack bits for keys (2,9) and (3,9) from (1,7) and (1,8)
185 // i2c_master_read(I2C_ACK);
186 matrix[slaveOffset+0] = i2c_master_read(I2C_ACK);
187 // i2c_master_read(I2C_ACK);
188 matrix[slaveOffset+1] = (matrix_row_t)i2c_master_read(I2C_ACK)\
189 | (matrix[slaveOffset+0]&0x40U)<<2;
190 // i2c_master_read(I2C_ACK);
191 matrix[slaveOffset+2] = (matrix_row_t)i2c_master_read(I2C_NACK)\
192 | (matrix[slaveOffset+0]&0x80U)<<1;
193 // clear highest two bits on row 1, where the col9 bits were transported
194 matrix[slaveOffset+0] &= 0x3F;
195
196 i2c_master_stop();
197 } else {
198i2c_error: // the cable is disconnected, or something else went wrong
199 i2c_reset_state();
200 return err;
201 }
202
203 return 0;
204}
205
206#else // USE_SERIAL
207
208int serial_transaction(void) {
209 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
210
211 if (serial_update_buffers()) {
212 return 1;
213 }
214
215 for (int i = 0; i < ROWS_PER_HAND; ++i) {
216 matrix[slaveOffset+i] = serial_slave_buffer[i];
217 }
218 return 0;
219}
220#endif
221
222uint8_t matrix_scan(void)
223{
224 int ret = _matrix_scan();
225
226
227
228#ifdef USE_I2C
229 if( i2c_transaction() ) {
230#else // USE_SERIAL
231 if( serial_transaction() ) {
232#endif
233 // turn on the indicator led when halves are disconnected
234 TXLED1;
235
236 error_count++;
237
238 if (error_count > ERROR_DISCONNECT_COUNT) {
239 // reset other half if disconnected
240 int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
241 for (int i = 0; i < ROWS_PER_HAND; ++i) {
242 matrix[slaveOffset+i] = 0;
243 }
244 }
245 } else {
246 // turn off the indicator led on no error
247 TXLED0;
248 error_count = 0;
249 }
250 matrix_scan_quantum();
251 return ret;
252}
253
254void matrix_slave_scan(void) {
255 _matrix_scan();
256
257 int offset = (isLeftHand) ? 0 : ROWS_PER_HAND;
258
259#ifdef USE_I2C
260 // SLAVE_BUFFER_SIZE is from i2c.h
261 // (MATRIX_ROWS/2*sizeof(matrix_row_t))
262 // memcpy((void*)i2c_slave_buffer, (const void*)&matrix[offset], (ROWS_PER_HAND*sizeof(matrix_row_t)));
263
264 // kludge for column #9: put bits for keys (2,9) and (3,9) into (1,7) and (1,8)
265 i2c_slave_buffer[0] = (uint8_t)(matrix[offset+0])\
266 | (matrix[offset+1]&0x100U)>>2\
267 | (matrix[offset+2]&0x100U)>>1;
268 i2c_slave_buffer[1] = (uint8_t)(matrix[offset+1]);
269 i2c_slave_buffer[2] = (uint8_t)(matrix[offset+2]);
270 // note: looks like a possible operator-precedence bug here, in last version?
271 /*
272 i2c_slave_buffer[1] = (uint8_t)matrix[offset+0];
273 i2c_slave_buffer[2] = (uint8_t)(matrix[offset+1]>>8);
274 i2c_slave_buffer[3] = (uint8_t)(matrix[offset+1]>>8);
275 i2c_slave_buffer[4] = (uint8_t)(matrix[offset+2]>>8);
276 i2c_slave_buffer[5] = (uint8_t)matrix[offset+2];
277 */
278#else // USE_SERIAL
279 for (int i = 0; i < ROWS_PER_HAND; ++i) {
280 serial_slave_buffer[i] = matrix[offset+i];
281 }
282#endif
283}
284
285bool matrix_is_modified(void)
286{
287 if (debouncing) return false;
288 return true;
289}
290
291inline
292bool matrix_is_on(uint8_t row, uint8_t col)
293{
294 return (matrix[row] & ((matrix_row_t)1<<col));
295}
296
297inline
298matrix_row_t matrix_get_row(uint8_t row)
299{
300 return matrix[row];
301}
302
303void matrix_print(void)
304{
305 print("\nr/c 0123456789ABCDEF\n");
306 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
307 phex(row); print(": ");
308 pbin_reverse16(matrix_get_row(row));
309 print("\n");
310 }
311}
312
313uint8_t matrix_key_count(void)
314{
315 uint8_t count = 0;
316 for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
317 count += bitpop16(matrix[i]);
318 }
319 return count;
320}
321
322static void init_cols(void)
323{
324 for(int x = 0; x < MATRIX_COLS; x++) {
325 _SFR_IO8((col_pins[x] >> 4) + 1) &= ~_BV(col_pins[x] & 0xF);
326 _SFR_IO8((col_pins[x] >> 4) + 2) |= _BV(col_pins[x] & 0xF);
327 }
328}
329
330static matrix_row_t read_cols(void)
331{
332 matrix_row_t result = 0;
333 for(int x = 0; x < MATRIX_COLS; x++) {
334 result |= (_SFR_IO8(col_pins[x] >> 4) & _BV(col_pins[x] & 0xF)) ? 0 : (1 << x);
335 }
336 return result;
337}
338
339static void unselect_rows(void)
340{
341 for(int x = 0; x < ROWS_PER_HAND; x++) {
342 _SFR_IO8((row_pins[x] >> 4) + 1) &= ~_BV(row_pins[x] & 0xF);
343 _SFR_IO8((row_pins[x] >> 4) + 2) |= _BV(row_pins[x] & 0xF);
344 }
345}
346
347static void select_row(uint8_t row)
348{
349 _SFR_IO8((row_pins[row] >> 4) + 1) |= _BV(row_pins[row] & 0xF);
350 _SFR_IO8((row_pins[row] >> 4) + 2) &= ~_BV(row_pins[row] & 0xF);
351}
diff --git a/keyboards/orthodox/orthodox.c b/keyboards/orthodox/orthodox.c
new file mode 100644
index 000000000..0b366e944
--- /dev/null
+++ b/keyboards/orthodox/orthodox.c
@@ -0,0 +1 @@
#include "orthodox.h" \ No newline at end of file
diff --git a/keyboards/orthodox/orthodox.h b/keyboards/orthodox/orthodox.h
new file mode 100644
index 000000000..bb7efb6ad
--- /dev/null
+++ b/keyboards/orthodox/orthodox.h
@@ -0,0 +1,30 @@
1#ifndef ORTHODOX_H
2#define ORTHODOX_H
3
4#ifdef SUBPROJECT_rev1
5 #include "rev1.h"
6#endif
7#ifdef SUBPROJECT_rev2
8 #include "rev2.h"
9#endif
10#ifdef SUBPROJECT_rev2fliphalf
11 #include "rev2fliphalf.h"
12#endif
13
14// Used to create a keymap using only KC_ prefixed keys
15#define KC_KEYMAP( \
16 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
17 L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
18 L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
19 L30, L31, L32, L33, L34, L35, R30, R31, R32, R33, R34, R35 \
20 ) \
21 KEYMAP( \
22 KC_##L00, KC_##L01, KC_##L02, KC_##L03, KC_##L04, KC_##L05, KC_##R00, KC_##R01, KC_##R02, KC_##R03, KC_##R04, KC_##R05, \
23 KC_##L10, KC_##L11, KC_##L12, KC_##L13, KC_##L14, KC_##L15, KC_##R10, KC_##R11, KC_##R12, KC_##R13, KC_##R14, KC_##R15, \
24 KC_##L20, KC_##L21, KC_##L22, KC_##L23, KC_##L24, KC_##L25, KC_##R20, KC_##R21, KC_##R22, KC_##R23, KC_##R24, KC_##R25, \
25 KC_##L30, KC_##L31, KC_##L32, KC_##L33, KC_##L34, KC_##L35, KC_##R30, KC_##R31, KC_##R32, KC_##R33, KC_##R34, KC_##R35 \
26 )
27
28#include "quantum.h"
29
30#endif \ No newline at end of file
diff --git a/keyboards/orthodox/pro_micro.h b/keyboards/orthodox/pro_micro.h
new file mode 100644
index 000000000..f9e7ed75d
--- /dev/null
+++ b/keyboards/orthodox/pro_micro.h
@@ -0,0 +1,362 @@
1/*
2 pins_arduino.h - Pin definition functions for Arduino
3 Part of Arduino - http://www.arduino.cc/
4
5 Copyright (c) 2007 David A. Mellis
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General
18 Public License along with this library; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 Boston, MA 02111-1307 USA
21
22 $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
23*/
24
25#ifndef Pins_Arduino_h
26#define Pins_Arduino_h
27
28#include <avr/pgmspace.h>
29
30// Workaround for wrong definitions in "iom32u4.h".
31// This should be fixed in the AVR toolchain.
32#undef UHCON
33#undef UHINT
34#undef UHIEN
35#undef UHADDR
36#undef UHFNUM
37#undef UHFNUML
38#undef UHFNUMH
39#undef UHFLEN
40#undef UPINRQX
41#undef UPINTX
42#undef UPNUM
43#undef UPRST
44#undef UPCONX
45#undef UPCFG0X
46#undef UPCFG1X
47#undef UPSTAX
48#undef UPCFG2X
49#undef UPIENX
50#undef UPDATX
51#undef TCCR2A
52#undef WGM20
53#undef WGM21
54#undef COM2B0
55#undef COM2B1
56#undef COM2A0
57#undef COM2A1
58#undef TCCR2B
59#undef CS20
60#undef CS21
61#undef CS22
62#undef WGM22
63#undef FOC2B
64#undef FOC2A
65#undef TCNT2
66#undef TCNT2_0
67#undef TCNT2_1
68#undef TCNT2_2
69#undef TCNT2_3
70#undef TCNT2_4
71#undef TCNT2_5
72#undef TCNT2_6
73#undef TCNT2_7
74#undef OCR2A
75#undef OCR2_0
76#undef OCR2_1
77#undef OCR2_2
78#undef OCR2_3
79#undef OCR2_4
80#undef OCR2_5
81#undef OCR2_6
82#undef OCR2_7
83#undef OCR2B
84#undef OCR2_0
85#undef OCR2_1
86#undef OCR2_2
87#undef OCR2_3
88#undef OCR2_4
89#undef OCR2_5
90#undef OCR2_6
91#undef OCR2_7
92
93#define NUM_DIGITAL_PINS 30
94#define NUM_ANALOG_INPUTS 12
95
96#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
97#define TXLED0 PORTD |= (1<<5)
98#define TXLED1 PORTD &= ~(1<<5)
99#define RXLED0 PORTB |= (1<<0)
100#define RXLED1 PORTB &= ~(1<<0)
101
102static const uint8_t SDA = 2;
103static const uint8_t SCL = 3;
104#define LED_BUILTIN 13
105
106// Map SPI port to 'new' pins D14..D17
107static const uint8_t SS = 17;
108static const uint8_t MOSI = 16;
109static const uint8_t MISO = 14;
110static const uint8_t SCK = 15;
111
112// Mapping of analog pins as digital I/O
113// A6-A11 share with digital pins
114static const uint8_t ADC0 = 18;
115static const uint8_t ADC1 = 19;
116static const uint8_t ADC2 = 20;
117static const uint8_t ADC3 = 21;
118static const uint8_t ADC4 = 22;
119static const uint8_t ADC5 = 23;
120static const uint8_t ADC6 = 24; // D4
121static const uint8_t ADC7 = 25; // D6
122static const uint8_t ADC8 = 26; // D8
123static const uint8_t ADC9 = 27; // D9
124static const uint8_t ADC10 = 28; // D10
125static const uint8_t ADC11 = 29; // D12
126
127#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
128#define digitalPinToPCICRbit(p) 0
129#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
130#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
131
132// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
133extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
134#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
135
136#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
137
138#ifdef ARDUINO_MAIN
139
140// On the Arduino board, digital pins are also used
141// for the analog output (software PWM). Analog input
142// pins are a separate set.
143
144// ATMEL ATMEGA32U4 / ARDUINO LEONARDO
145//
146// D0 PD2 RXD1/INT2
147// D1 PD3 TXD1/INT3
148// D2 PD1 SDA SDA/INT1
149// D3# PD0 PWM8/SCL OC0B/SCL/INT0
150// D4 A6 PD4 ADC8
151// D5# PC6 ??? OC3A/#OC4A
152// D6# A7 PD7 FastPWM #OC4D/ADC10
153// D7 PE6 INT6/AIN0
154//
155// D8 A8 PB4 ADC11/PCINT4
156// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5
157// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6
158// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7
159// D12 A11 PD6 T1/#OC4D/ADC9
160// D13# PC7 PWM10 CLK0/OC4A
161//
162// A0 D18 PF7 ADC7
163// A1 D19 PF6 ADC6
164// A2 D20 PF5 ADC5
165// A3 D21 PF4 ADC4
166// A4 D22 PF1 ADC1
167// A5 D23 PF0 ADC0
168//
169// New pins D14..D17 to map SPI port to digital pins
170//
171// MISO D14 PB3 MISO,PCINT3
172// SCK D15 PB1 SCK,PCINT1
173// MOSI D16 PB2 MOSI,PCINT2
174// SS D17 PB0 RXLED,SS/PCINT0
175//
176// Connected LEDs on board for TX and RX
177// TXLED D24 PD5 XCK1
178// RXLED D17 PB0
179// HWB PE2 HWB
180
181// these arrays map port names (e.g. port B) to the
182// appropriate addresses for various functions (e.g. reading
183// and writing)
184const uint16_t PROGMEM port_to_mode_PGM[] = {
185 NOT_A_PORT,
186 NOT_A_PORT,
187 (uint16_t) &DDRB,
188 (uint16_t) &DDRC,
189 (uint16_t) &DDRD,
190 (uint16_t) &DDRE,
191 (uint16_t) &DDRF,
192};
193
194const uint16_t PROGMEM port_to_output_PGM[] = {
195 NOT_A_PORT,
196 NOT_A_PORT,
197 (uint16_t) &PORTB,
198 (uint16_t) &PORTC,
199 (uint16_t) &PORTD,
200 (uint16_t) &PORTE,
201 (uint16_t) &PORTF,
202};
203
204const uint16_t PROGMEM port_to_input_PGM[] = {
205 NOT_A_PORT,
206 NOT_A_PORT,
207 (uint16_t) &PINB,
208 (uint16_t) &PINC,
209 (uint16_t) &PIND,
210 (uint16_t) &PINE,
211 (uint16_t) &PINF,
212};
213
214const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
215 PD, // D0 - PD2
216 PD, // D1 - PD3
217 PD, // D2 - PD1
218 PD, // D3 - PD0
219 PD, // D4 - PD4
220 PC, // D5 - PC6
221 PD, // D6 - PD7
222 PE, // D7 - PE6
223
224 PB, // D8 - PB4
225 PB, // D9 - PB5
226 PB, // D10 - PB6
227 PB, // D11 - PB7
228 PD, // D12 - PD6
229 PC, // D13 - PC7
230
231 PB, // D14 - MISO - PB3
232 PB, // D15 - SCK - PB1
233 PB, // D16 - MOSI - PB2
234 PB, // D17 - SS - PB0
235
236 PF, // D18 - A0 - PF7
237 PF, // D19 - A1 - PF6
238 PF, // D20 - A2 - PF5
239 PF, // D21 - A3 - PF4
240 PF, // D22 - A4 - PF1
241 PF, // D23 - A5 - PF0
242
243 PD, // D24 - PD5
244 PD, // D25 / D6 - A7 - PD7
245 PB, // D26 / D8 - A8 - PB4
246 PB, // D27 / D9 - A9 - PB5
247 PB, // D28 / D10 - A10 - PB6
248 PD, // D29 / D12 - A11 - PD6
249};
250
251const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
252 _BV(2), // D0 - PD2
253 _BV(3), // D1 - PD3
254 _BV(1), // D2 - PD1
255 _BV(0), // D3 - PD0
256 _BV(4), // D4 - PD4
257 _BV(6), // D5 - PC6
258 _BV(7), // D6 - PD7
259 _BV(6), // D7 - PE6
260
261 _BV(4), // D8 - PB4
262 _BV(5), // D9 - PB5
263 _BV(6), // D10 - PB6
264 _BV(7), // D11 - PB7
265 _BV(6), // D12 - PD6
266 _BV(7), // D13 - PC7
267
268 _BV(3), // D14 - MISO - PB3
269 _BV(1), // D15 - SCK - PB1
270 _BV(2), // D16 - MOSI - PB2
271 _BV(0), // D17 - SS - PB0
272
273 _BV(7), // D18 - A0 - PF7
274 _BV(6), // D19 - A1 - PF6
275 _BV(5), // D20 - A2 - PF5
276 _BV(4), // D21 - A3 - PF4
277 _BV(1), // D22 - A4 - PF1
278 _BV(0), // D23 - A5 - PF0
279
280 _BV(5), // D24 - PD5
281 _BV(7), // D25 / D6 - A7 - PD7
282 _BV(4), // D26 / D8 - A8 - PB4
283 _BV(5), // D27 / D9 - A9 - PB5
284 _BV(6), // D28 / D10 - A10 - PB6
285 _BV(6), // D29 / D12 - A11 - PD6
286};
287
288const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
289 NOT_ON_TIMER,
290 NOT_ON_TIMER,
291 NOT_ON_TIMER,
292 TIMER0B, /* 3 */
293 NOT_ON_TIMER,
294 TIMER3A, /* 5 */
295 TIMER4D, /* 6 */
296 NOT_ON_TIMER,
297
298 NOT_ON_TIMER,
299 TIMER1A, /* 9 */
300 TIMER1B, /* 10 */
301 TIMER0A, /* 11 */
302
303 NOT_ON_TIMER,
304 TIMER4A, /* 13 */
305
306 NOT_ON_TIMER,
307 NOT_ON_TIMER,
308 NOT_ON_TIMER,
309 NOT_ON_TIMER,
310 NOT_ON_TIMER,
311 NOT_ON_TIMER,
312
313 NOT_ON_TIMER,
314 NOT_ON_TIMER,
315 NOT_ON_TIMER,
316 NOT_ON_TIMER,
317 NOT_ON_TIMER,
318 NOT_ON_TIMER,
319 NOT_ON_TIMER,
320 NOT_ON_TIMER,
321 NOT_ON_TIMER,
322 NOT_ON_TIMER,
323};
324
325const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
326 7, // A0 PF7 ADC7
327 6, // A1 PF6 ADC6
328 5, // A2 PF5 ADC5
329 4, // A3 PF4 ADC4
330 1, // A4 PF1 ADC1
331 0, // A5 PF0 ADC0
332 8, // A6 D4 PD4 ADC8
333 10, // A7 D6 PD7 ADC10
334 11, // A8 D8 PB4 ADC11
335 12, // A9 D9 PB5 ADC12
336 13, // A10 D10 PB6 ADC13
337 9 // A11 D12 PD6 ADC9
338};
339
340#endif /* ARDUINO_MAIN */
341
342// These serial port names are intended to allow libraries and architecture-neutral
343// sketches to automatically default to the correct port name for a particular type
344// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
345// the first hardware serial port whose RX/TX pins are not dedicated to another use.
346//
347// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
348//
349// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
350//
351// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
352//
353// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
354//
355// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
356// pins are NOT connected to anything by default.
357#define SERIAL_PORT_MONITOR Serial
358#define SERIAL_PORT_USBVIRTUAL Serial
359#define SERIAL_PORT_HARDWARE Serial1
360#define SERIAL_PORT_HARDWARE_OPEN Serial1
361
362#endif /* Pins_Arduino_h */
diff --git a/keyboards/orthodox/readme.md b/keyboards/orthodox/readme.md
new file mode 100644
index 000000000..94bb8ebb9
--- /dev/null
+++ b/keyboards/orthodox/readme.md
@@ -0,0 +1,165 @@
1Orthodox
2========
3
4*Please note this guide is a work in progress and is based directly on the Let's Split guide.*
5
6Orthodox is a split ortholinear keyboard with thumb-clusters designed in 2017 by /u/Deductivemonkee, expected to be available in group buys.
7Each half has 18 keys in a 3x6 grid and a five key thumb-cluster, of which three use 1.25-unit keycaps.
8
9![Example prototype build by /u/Deductivemonkee](http://i.imgur.com/R4PPKdog.jpg)
10
11Its firmware is based on the Let's Split's.
12Each side is controlled by an Arduino Pro Micro (or compatible), and they're connected by a TRRS cable using the serial protocol.
13Support for the protocol using TWI (i2c®) is a work-in-progress.
14
15
16## Revisions
17
18- `Rev.1` Prototype GB version, supporting only Pro Micro in the corner footprint, and using PCB top- and bottom-plates.
19
20Note that the second number after the `Rev.` text is the pcb *order number.* The prototypes will say 1, and the next order of any revision will say 2 and so on.
21
22## Keymaps
23
24[The default layout can be unofficially referred to here.](http://www.keyboard-layout-editor.com/#/gists/f120e2703a22a6a69c7be9a65a9d1342)
25
26The thumb-clusters are an extension of row 2 and row 3 along columns 7, 8, and 9.
27Row 2 does not have a physical key in column 8, so when editing keymaps a placeholder constant (`XXXXXXX` or `KC_NO`) must be used in the row2-col8 position.
28
29## Build Guide
30
31[Official build guide by /u/Deductivemonkee](http://imgur.com/a/9c0NP)
32
33For further reading on build- and flashing-procedures for split ortholinear skeleton-case keyboards, please refer to [An Overly Verbose Guide to Building a Let's Split Keyboard](https://github.com/nicinabox/lets-split-guide), much of which can be applied to the Orthodox.
34
35## First Time Setup
36
37Download or clone the whole firmware and navigate to the keyboards/orthodox directory. Once your dev env is setup, you'll be able to generate the default .hex using:
38
39```
40$ make rev1
41```
42
43You will see a lot of output and if everything worked correctly you will see the built hex files in your *root qmk_firmware directory* two levels up:
44
45```
46orthodox_rev1_serial.hex
47```
48
49If you would like to use one of the alternative keymaps, or create your own, copy one of the existing [keymaps](keymaps/) and run make like so:
50
51
52```
53$ make rev1-YOUR_KEYMAP_NAME
54```
55
56If everything worked correctly you will see a file:
57
58```
59orthodox_rev1_YOUR_KEYMAP_NAME.hex
60```
61
62For more information on customizing keymaps, take a look at the primary documentation for [Customizing Your Keymap](/readme.md##customizing-your-keymap) in the main readme.md.
63
64
65Features
66--------
67
68For the full Quantum Mechanical Keyboard feature list, see [the parent readme.md](/readme.md).
69
70Some features supported by the firmware:
71
72* Either half can connect to the computer via USB, or both halves can be used
73 independently.
74* You only need 3 wires to connect the two halves. Two for VCC and GND and one
75 for serial communication.
76
77
78Required Hardware
79-----------------
80
81Apart from diodes and key switches for the keyboard matrix in each half, you
82will need:
83
84* 2 Arduino Pro Micro's. You can find theses on aliexpress for ≈3.50USD each.
85* 2 TRRS sockets and 1 TRRS cable
86
87
88Notes on Software Configuration
89-------------------------------
90
91Configuring the firmware is similar to any other QMK project. One thing
92to note is that `MATRIX_ROWS` in `config.h` is the total number of rows between
93the two halves, i.e. if your split keyboard has 3 rows in each half, then
94`MATRIX_ROWS=6`.
95
96
97Flashing
98-------
99From the keymap directory run `make SUBPROJECT-KEYMAP-avrdude` for automatic serial port resolution and flashing.
100Example: `make rev2-serial-avrdude`
101
102
103Choosing which board to plug the USB cable into (choosing Master)
104--------
105Because the two boards are identical, the firmware has logic to differentiate the left and right board.
106
107It uses two strategies to figure things out: look at the EEPROM (memory on the chip) or looks if the current board has the usb cable.
108
109The EEPROM approach requires additional setup (flashing the eeeprom) but allows you to swap the usb cable to either side.
110
111The USB cable approach is easier to setup and if you just want the usb cable on the left board, you do not need to do anything extra.
112
113### Setting the left hand as master
114If you always plug the usb cable into the left board, nothing extra is needed as this is the default. Comment out `EE_HANDS` and comment out `I2C_MASTER_RIGHT` or `MASTER_RIGHT` if for some reason it was set.
115
116### Setting the right hand as master
117If you always plug the usb cable into the right board, add an extra flag to your `config.h`
118```
119 #define MASTER_RIGHT
120```
121
122### Setting EE_hands to use either hands as master
123If you define `EE_HANDS` in your `config.h`, you will need to set the
124EEPROM for the left and right halves.
125
126The EEPROM is used to store whether the
127half is left handed or right handed. This makes it so that the same firmware
128file will run on both hands instead of having to flash left and right handed
129versions of the firmware to each half. To flash the EEPROM file for the left
130half run:
131```
132avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-lefthand.eep
133// or the equivalent in dfu-programmer
134
135```
136and similarly for right half
137```
138avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-righhand.eep
139// or the equivalent in dfu-programmer
140```
141
142NOTE: replace `$(COM_PORT)` with the port of your device (e.g. `/dev/ttyACM0`)
143
144After you have flashed the EEPROM, you then need to set `EE_HANDS` in your config.h, rebuild the hex files and reflash.
145
146Note that you need to program both halves, but you have the option of using
147different keymaps for each half. You could program the left half with a QWERTY
148layout and the right half with a Colemak layout using bootmagic's default layout option.
149Then if you connect the left half to a computer by USB the keyboard will use QWERTY and Colemak when the
150right half is connected.
151
152
153Notes on Using Pro Micro 3.3V
154-----------------------------
155
156Do update the `F_CPU` parameter in `rules.mk` to `8000000` which reflects
157the frequency on the 3.3V board.
158
159Also, if the slave board is producing weird characters in certain columns,
160update the following line in `matrix.c` to the following:
161
162```
163// _delay_us(30); // without this wait read unstable value.
164_delay_us(300); // without this wait read unstable value.
165```
diff --git a/keyboards/orthodox/rev1/Makefile b/keyboards/orthodox/rev1/Makefile
new file mode 100644
index 000000000..4e2a6f00f
--- /dev/null
+++ b/keyboards/orthodox/rev1/Makefile
@@ -0,0 +1,3 @@
1ifndef MAKEFILE_INCLUDED
2 include ../../Makefile
3endif \ No newline at end of file
diff --git a/keyboards/orthodox/rev1/config.h b/keyboards/orthodox/rev1/config.h
new file mode 100644
index 000000000..46bb99440
--- /dev/null
+++ b/keyboards/orthodox/rev1/config.h
@@ -0,0 +1,99 @@
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#define VENDOR_ID 0xFEED
25#define PRODUCT_ID 0x3060
26#define DEVICE_VER 0x0001
27#define MANUFACTURER deductivemonkee
28#define PRODUCT Monkeebs Orthodox Rev.1
29#define DESCRIPTION Oreodox
30
31/* key matrix size */
32// Rows are doubled-up
33#define MATRIX_ROWS 6
34#define MATRIX_COLS 9
35
36// wiring of each half
37
38
39//PRO MICRO
40#define MATRIX_ROW_PINS { D4, B4, B5 }
41#define MATRIX_COL_PINS { D7, F4, F5, F6, F7, B1, B3, B2, B6 }
42//#define MATRIX_COL_PINS { B2, B3, B1, F7, F6, F5, F4, D7 }
43
44/*/
45//TEENSY
46#define MATRIX_ROW_PINS { D0, C6, C7, }
47#define MATRIX_COL_PINS { D2, F5, F6, F7, B6, B5, B4, D7, D6 }
48/*/
49
50#define CATERINA_BOOTLOADER
51
52/* COL2ROW or ROW2COL */
53#define DIODE_DIRECTION COL2ROW
54
55/* define if matrix has ghost */
56//#define MATRIX_HAS_GHOST
57
58/* number of backlight levels */
59// #define BACKLIGHT_LEVELS 3
60
61/* Set 0 if debouncing isn't needed */
62#define DEBOUNCING_DELAY 5
63
64/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
65// #define LOCKING_SUPPORT_ENABLE
66/* Locking resynchronize hack */
67// #define LOCKING_RESYNC_ENABLE
68
69/* key combination for command */
70#define IS_COMMAND() ( \
71 keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
72)
73
74/* ws2812 RGB LED */
75//#define RGB_DI_PIN D3
76//#define RGBLIGHT_TIMER
77//#define RGBLED_NUM 16 // Number of LEDs
78//#define ws2812_PORTREG PORTD
79//#define ws2812_DDRREG DDRD
80
81/*
82 * Feature disable options
83 * These options are also useful to firmware size reduction.
84 */
85
86/* disable debug print */
87// #define NO_DEBUG
88
89/* disable print */
90// #define NO_PRINT
91
92/* disable action features */
93//#define NO_ACTION_LAYER
94//#define NO_ACTION_TAPPING
95//#define NO_ACTION_ONESHOT
96//#define NO_ACTION_MACRO
97//#define NO_ACTION_FUNCTION
98
99#endif
diff --git a/keyboards/orthodox/rev1/rev1.c b/keyboards/orthodox/rev1/rev1.c
new file mode 100644
index 000000000..10ece03f0
--- /dev/null
+++ b/keyboards/orthodox/rev1/rev1.c
@@ -0,0 +1,32 @@
1#include "orthodox.h"
2
3#ifdef AUDIO_ENABLE
4 float tone_startup[][2] = SONG(STARTUP_SOUND);
5 float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
6#endif
7
8void matrix_init_kb(void) {
9
10 #ifdef AUDIO_ENABLE
11 _delay_ms(20); // gets rid of tick
12 PLAY_NOTE_ARRAY(tone_startup, false, 0);
13 #endif
14
15 // // green led on
16 // DDRD |= (1<<5);
17 // PORTD &= ~(1<<5);
18
19 // // orange led on
20 // DDRB |= (1<<0);
21 // PORTB &= ~(1<<0);
22
23 matrix_init_user();
24};
25
26void shutdown_user(void) {
27 #ifdef AUDIO_ENABLE
28 PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
29 _delay_ms(150);
30 stop_all_notes();
31 #endif
32}
diff --git a/keyboards/orthodox/rev1/rev1.h b/keyboards/orthodox/rev1/rev1.h
new file mode 100644
index 000000000..4f163299d
--- /dev/null
+++ b/keyboards/orthodox/rev1/rev1.h
@@ -0,0 +1,25 @@
1#ifndef REV1_H
2#define REV1_H
3
4#include "../orthodox.h"
5
6//void promicro_bootloader_jmp(bool program);
7#include "quantum.h"
8
9//void promicro_bootloader_jmp(bool program);
10
11#define KEYMAP( \
12 L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
13 L10, L11, L12, L13, L14, L15, L16, L17, L18, R10, R11, R12, R13, R14, R15, R16, R17, R18, \
14 L20, L21, L22, L23, L24, L25, L26, L27, L28, R20, R21, R22, R23, R24, R25, R26, R27, R28 \
15 ) \
16 { \
17 { L00, L01, L02, L03, L04, L05 }, \
18 { L10, L11, L12, L13, L14, L15, L16, L17, L18}, \
19 { L20, L21, L22, L23, L24, L25, L26, L27, L28 }, \
20 { R05, R04, R03, R02, R01, R00 }, \
21 { R18, R17, R16, R15, R14, R13, R12, R11, R10 }, \
22 { R28, R27, R26, R25, R24, R23, R22, R21, R20 } \
23 }
24
25#endif \ No newline at end of file
diff --git a/keyboards/orthodox/rev1/rules.mk b/keyboards/orthodox/rev1/rules.mk
new file mode 100644
index 000000000..a0825b4ef
--- /dev/null
+++ b/keyboards/orthodox/rev1/rules.mk
@@ -0,0 +1,5 @@
1BACKLIGHT_ENABLE = no
2
3ifndef QUANTUM_DIR
4 include ../../../Makefile
5endif \ No newline at end of file
diff --git a/keyboards/orthodox/rules.mk b/keyboards/orthodox/rules.mk
new file mode 100644
index 000000000..0efa78550
--- /dev/null
+++ b/keyboards/orthodox/rules.mk
@@ -0,0 +1,87 @@
1SRC += matrix.c \
2 i2c.c \
3 split_util.c \
4 serial.c
5
6# MCU name
7#MCU = at90usb1287
8MCU = atmega32u4
9
10# Processor frequency.
11# This will define a symbol, F_CPU, in all source code files equal to the
12# processor frequency in Hz. You can then use this symbol in your source code to
13# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
14# automatically to create a 32-bit value in your source code.
15#
16# This will be an integer division of F_USB below, as it is sourced by
17# F_USB after it has run through any CPU prescalers. Note that this value
18# does not *change* the processor frequency - it should merely be updated to
19# reflect the processor speed set externally so that the code can use accurate
20# software delays.
21F_CPU = 16000000
22
23#
24# LUFA specific
25#
26# Target architecture (see library "Board Types" documentation).
27ARCH = AVR8
28
29# Input clock frequency.
30# This will define a symbol, F_USB, in all source code files equal to the
31# input clock frequency (before any prescaling is performed) in Hz. This value may
32# differ from F_CPU if prescaling is used on the latter, and is required as the
33# raw input clock is fed directly to the PLL sections of the AVR for high speed
34# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
35# at the end, this will be done automatically to create a 32-bit value in your
36# source code.
37#
38# If no clock division is performed on the input clock inside the AVR (via the
39# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
40F_USB = $(F_CPU)
41
42# Interrupt driven control endpoint task(+60)
43OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
44
45
46# Boot Section Size in *bytes*
47# Teensy halfKay 512
48# Teensy++ halfKay 1024
49# Atmel DFU loader 4096
50# LUFA bootloader 4096
51# USBaspLoader 2048
52OPT_DEFS += -DBOOTLOADER_SIZE=4096
53
54# Build Options
55# change to "no" to disable the options, or define them in the Makefile in
56# the appropriate keymap folder that will get included automatically
57#
58BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
59MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
60EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
61CONSOLE_ENABLE ?= no # Console for debug(+400)
62COMMAND_ENABLE ?= yes # Commands for debug and configuration
63NKRO_ENABLE ?= no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
64BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality
65MIDI_ENABLE ?= no # MIDI controls
66AUDIO_ENABLE ?= no # Audio output on port C6
67UNICODE_ENABLE ?= no # Unicode
68BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
69RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
70SUBPROJECT_rev1 ?= yes
71USE_I2C ?= yes
72# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
73SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
74
75CUSTOM_MATRIX = yes
76
77avrdude: build
78 ls /dev/tty* > /tmp/1; \
79 echo "Reset your Pro Micro now"; \
80 while [[ -z $$USB ]]; do \
81 sleep 1; \
82 ls /dev/tty* > /tmp/2; \
83 USB=`diff /tmp/1 /tmp/2 | grep -o '/dev/tty.*'`; \
84 done; \
85 avrdude -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex
86
87.PHONY: avrdude
diff --git a/keyboards/orthodox/serial.c b/keyboards/orthodox/serial.c
new file mode 100644
index 000000000..4936e4249
--- /dev/null
+++ b/keyboards/orthodox/serial.c
@@ -0,0 +1,230 @@
1/*
2 * WARNING: be careful changing this code, it is very timing dependent
3 */
4
5#ifndef F_CPU
6#define F_CPU 16000000
7#endif
8
9#include <avr/io.h>
10#include <avr/interrupt.h>
11#include <util/delay.h>
12#include <stdbool.h>
13#include "serial.h"
14
15#ifdef USE_SERIAL
16
17// Serial pulse period in microseconds. Its probably a bad idea to lower this
18// value.
19#define SERIAL_DELAY 24
20
21matrix_row_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
22matrix_row_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
23
24#define ROW_MASK (((matrix_row_t)0-1)>>(8*sizeof(matrix_row_t)-MATRIX_COLS))
25
26#define SLAVE_DATA_CORRUPT (1<<0)
27volatile uint8_t status = 0;
28
29inline static
30void serial_delay(void) {
31 _delay_us(SERIAL_DELAY);
32}
33
34inline static
35void serial_output(void) {
36 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
37}
38
39// make the serial pin an input with pull-up resistor
40inline static
41void serial_input(void) {
42 SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
43 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
44}
45
46inline static
47matrix_row_t serial_read_pin(void) {
48 return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
49}
50
51inline static
52void serial_low(void) {
53 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
54}
55
56inline static
57void serial_high(void) {
58 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
59}
60
61void serial_master_init(void) {
62 serial_output();
63 serial_high();
64}
65
66void serial_slave_init(void) {
67 serial_input();
68
69 // Enable INT0
70 EIMSK |= _BV(INT0);
71 // Trigger on falling edge of INT0
72 EICRA &= ~(_BV(ISC00) | _BV(ISC01));
73}
74
75// Used by the master to synchronize timing with the slave.
76static
77void sync_recv(void) {
78 serial_input();
79 // This shouldn't hang if the slave disconnects because the
80 // serial line will float to high if the slave does disconnect.
81 while (!serial_read_pin());
82 serial_delay();
83}
84
85// Used by the slave to send a synchronization signal to the master.
86static
87void sync_send(void) {
88 serial_output();
89
90 serial_low();
91 serial_delay();
92
93 serial_high();
94}
95
96// Reads a byte from the serial line
97static
98matrix_row_t serial_read_byte(void) {
99 matrix_row_t byte = 0;
100 serial_input();
101 for ( uint8_t i = 0; i < MATRIX_COLS; ++i) {
102 byte = (byte << 1) | serial_read_pin();
103 serial_delay();
104 _delay_us(1);
105 }
106
107 return byte;
108}
109
110// Sends a byte with MSB ordering
111static
112void serial_write_byte(matrix_row_t data) {
113 matrix_row_t b = MATRIX_COLS;
114 serial_output();
115 while( b-- ) {
116 if(data & (1UL << b)) {
117 serial_high();
118 } else {
119 serial_low();
120 }
121 serial_delay();
122 }
123}
124
125// interrupt handle to be used by the slave device
126ISR(SERIAL_PIN_INTERRUPT) {
127 sync_send();
128
129 matrix_row_t checksum = 0;
130 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
131 serial_write_byte(serial_slave_buffer[i]);
132 sync_send();
133 checksum += ROW_MASK & serial_slave_buffer[i];
134 }
135 serial_write_byte(checksum);
136 sync_send();
137
138 // wait for the sync to finish sending
139 serial_delay();
140
141 // read the middle of pulses
142 _delay_us(SERIAL_DELAY/2);
143
144 matrix_row_t checksum_computed = 0;
145 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
146 serial_master_buffer[i] = serial_read_byte();
147 sync_send();
148 checksum_computed += ROW_MASK & serial_master_buffer[i];
149 }
150 matrix_row_t checksum_received = serial_read_byte();
151 sync_send();
152
153 serial_input(); // end transaction
154
155 if ( checksum_computed != checksum_received ) {
156 status |= SLAVE_DATA_CORRUPT;
157 } else {
158 status &= ~SLAVE_DATA_CORRUPT;
159 }
160}
161
162inline
163bool serial_slave_DATA_CORRUPT(void) {
164 return status & SLAVE_DATA_CORRUPT;
165}
166
167// Copies the serial_slave_buffer to the master and sends the
168// serial_master_buffer to the slave.
169//
170// Returns:
171// 0 => no error
172// 1 => slave did not respond
173int serial_update_buffers(void) {
174 // this code is very time dependent, so we need to disable interrupts
175 cli();
176
177 // signal to the slave that we want to start a transaction
178 serial_output();
179 serial_low();
180 _delay_us(1);
181
182 // wait for the slaves response
183 serial_input();
184 serial_high();
185 _delay_us(SERIAL_DELAY);
186
187 // check if the slave is present
188 if (serial_read_pin()) {
189 // slave failed to pull the line low, assume not present
190 sei();
191 return 1;
192 }
193
194 // if the slave is present syncronize with it
195 sync_recv();
196
197 matrix_row_t checksum_computed = 0;
198 // receive data from the slave
199 for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
200 serial_slave_buffer[i] = serial_read_byte();
201 sync_recv();
202 checksum_computed += ROW_MASK & serial_slave_buffer[i];
203 }
204 matrix_row_t checksum_received = serial_read_byte();
205 sync_recv();
206
207 if (checksum_computed != checksum_received) {
208 sei();
209 return 1;
210 }
211
212 matrix_row_t checksum = 0;
213 // send data to the slave
214 for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
215 serial_write_byte(serial_master_buffer[i]);
216 sync_recv();
217 checksum += ROW_MASK & serial_master_buffer[i];
218 }
219 serial_write_byte(checksum);
220 sync_recv();
221
222 // always, release the line when not in use
223 serial_output();
224 serial_high();
225
226 sei();
227 return 0;
228}
229
230#endif
diff --git a/keyboards/orthodox/serial.h b/keyboards/orthodox/serial.h
new file mode 100644
index 000000000..a46a98c94
--- /dev/null
+++ b/keyboards/orthodox/serial.h
@@ -0,0 +1,27 @@
1#ifndef MY_SERIAL_H
2#define MY_SERIAL_H
3
4#include "config.h"
5#include <stdbool.h>
6#include "matrix.h"
7
8/* TODO: some defines for interrupt setup */
9#define SERIAL_PIN_DDR DDRD
10#define SERIAL_PIN_PORT PORTD
11#define SERIAL_PIN_INPUT PIND
12#define SERIAL_PIN_MASK _BV(PD0)
13#define SERIAL_PIN_INTERRUPT INT0_vect
14
15#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
16#define SERIAL_MASTER_BUFFER_LENGTH 1
17
18// Buffers for master - slave communication
19extern volatile matrix_row_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
20extern volatile matrix_row_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
21
22void serial_master_init(void);
23void serial_slave_init(void);
24int serial_update_buffers(void);
25bool serial_slave_data_corrupt(void);
26
27#endif
diff --git a/keyboards/orthodox/split_util.c b/keyboards/orthodox/split_util.c
new file mode 100644
index 000000000..39639c3b4
--- /dev/null
+++ b/keyboards/orthodox/split_util.c
@@ -0,0 +1,84 @@
1#include <avr/io.h>
2#include <avr/wdt.h>
3#include <avr/power.h>
4#include <avr/interrupt.h>
5#include <util/delay.h>
6#include <avr/eeprom.h>
7#include "split_util.h"
8#include "matrix.h"
9#include "keyboard.h"
10#include "config.h"
11
12#ifdef USE_I2C
13# include "i2c.h"
14#else
15# include "serial.h"
16#endif
17
18volatile bool isLeftHand = true;
19
20static void setup_handedness(void) {
21 #ifdef EE_HANDS
22 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
23 #else
24 // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
25 #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
26 isLeftHand = !has_usb();
27 #else
28 isLeftHand = has_usb();
29 #endif
30 #endif
31}
32
33static void keyboard_master_setup(void) {
34#ifdef USE_I2C
35 i2c_master_init();
36#ifdef SSD1306OLED
37 matrix_master_OLED_init ();
38#endif
39#else
40 serial_master_init();
41#endif
42}
43
44static void keyboard_slave_setup(void) {
45#ifdef USE_I2C
46 i2c_slave_init(SLAVE_I2C_ADDRESS);
47#else
48 serial_slave_init();
49#endif
50}
51
52bool has_usb(void) {
53 USBCON |= (1 << OTGPADE); //enables VBUS pad
54 _delay_us(5);
55 return (USBSTA & (1<<VBUS)); //checks state of VBUS
56}
57
58void split_keyboard_setup(void) {
59 setup_handedness();
60
61 if (has_usb()) {
62 keyboard_master_setup();
63 } else {
64 keyboard_slave_setup();
65 }
66 sei();
67}
68
69void keyboard_slave_loop(void) {
70 matrix_init();
71
72 while (1) {
73 matrix_slave_scan();
74 }
75}
76
77// this code runs before the usb and keyboard is initialized
78void matrix_setup(void) {
79 split_keyboard_setup();
80
81 if (!has_usb()) {
82 keyboard_slave_loop();
83 }
84}
diff --git a/keyboards/orthodox/split_util.h b/keyboards/orthodox/split_util.h
new file mode 100644
index 000000000..3ae76c209
--- /dev/null
+++ b/keyboards/orthodox/split_util.h
@@ -0,0 +1,24 @@
1#ifndef SPLIT_KEYBOARD_UTIL_H
2#define SPLIT_KEYBOARD_UTIL_H
3
4#include <stdbool.h>
5
6#ifdef EE_HANDS
7 #define EECONFIG_BOOTMAGIC_END (uint8_t *)10
8 #define EECONFIG_HANDEDNESS EECONFIG_BOOTMAGIC_END
9#endif
10
11#define SLAVE_I2C_ADDRESS 0x32
12
13extern volatile bool isLeftHand;
14
15// slave version of matix scan, defined in matrix.c
16void matrix_slave_scan(void);
17
18void split_keyboard_setup(void);
19bool has_usb(void);
20void keyboard_slave_loop(void);
21
22void matrix_master_OLED_init (void);
23
24#endif
diff --git a/keyboards/orthodox/ssd1306.c b/keyboards/orthodox/ssd1306.c
new file mode 100644
index 000000000..5c6dff27f
--- /dev/null
+++ b/keyboards/orthodox/ssd1306.c
@@ -0,0 +1,470 @@
1#ifdef SSD1306OLED
2
3#include "ssd1306.h"
4#include "config.h"
5#include "i2c.h"
6#include <string.h>
7#include "print.h"
8#include "lets_split.h"
9#include "common/glcdfont.c"
10#ifdef ADAFRUIT_BLE_ENABLE
11#include "adafruit_ble.h"
12#endif
13#ifdef PROTOCOL_LUFA
14#include "lufa.h"
15#endif
16#include "sendchar.h"
17#include "pincontrol.h"
18
19//assign the right code to your layers
20#define _BASE 0
21#define _LOWER 8
22#define _RAISE 16
23#define _FNLAYER 64
24#define _NUMLAY 128
25#define _NLOWER 136
26#define _NFNLAYER 192
27#define _MOUSECURSOR 256
28#define _ADJUST 65560
29
30// Set this to 1 to help diagnose early startup problems
31// when testing power-on with ble. Turn it off otherwise,
32// as the latency of printing most of the debug info messes
33// with the matrix scan, causing keys to drop.
34#define DEBUG_TO_SCREEN 0
35
36// Controls the SSD1306 128x32 OLED display via i2c
37
38#define i2cAddress 0x3C
39
40#define DisplayHeight 32
41#define DisplayWidth 128
42
43#define FontHeight 8
44#define FontWidth 6
45
46#define MatrixRows (DisplayHeight / FontHeight)
47#define MatrixCols (DisplayWidth / FontWidth)
48
49struct CharacterMatrix {
50 uint8_t display[MatrixRows][MatrixCols];
51 uint8_t *cursor;
52 bool dirty;
53};
54
55static struct CharacterMatrix display;
56//static uint16_t last_battery_update;
57//static uint32_t vbat;
58//#define BatteryUpdateInterval 10000 /* milliseconds */
59#define ScreenOffInterval 300000 /* milliseconds */
60#if DEBUG_TO_SCREEN
61static uint8_t displaying;
62#endif
63static uint16_t last_flush;
64
65enum ssd1306_cmds {
66 DisplayOff = 0xAE,
67 DisplayOn = 0xAF,
68
69 SetContrast = 0x81,
70 DisplayAllOnResume = 0xA4,
71
72 DisplayAllOn = 0xA5,
73 NormalDisplay = 0xA6,
74 InvertDisplay = 0xA7,
75 SetDisplayOffset = 0xD3,
76 SetComPins = 0xda,
77 SetVComDetect = 0xdb,
78 SetDisplayClockDiv = 0xD5,
79 SetPreCharge = 0xd9,
80 SetMultiPlex = 0xa8,
81 SetLowColumn = 0x00,
82 SetHighColumn = 0x10,
83 SetStartLine = 0x40,
84
85 SetMemoryMode = 0x20,
86 ColumnAddr = 0x21,
87 PageAddr = 0x22,
88
89 ComScanInc = 0xc0,
90 ComScanDec = 0xc8,
91 SegRemap = 0xa0,
92 SetChargePump = 0x8d,
93 ExternalVcc = 0x01,
94 SwitchCapVcc = 0x02,
95
96 ActivateScroll = 0x2f,
97 DeActivateScroll = 0x2e,
98 SetVerticalScrollArea = 0xa3,
99 RightHorizontalScroll = 0x26,
100 LeftHorizontalScroll = 0x27,
101 VerticalAndRightHorizontalScroll = 0x29,
102 VerticalAndLeftHorizontalScroll = 0x2a,
103};
104
105
106// Write command sequence.
107// Returns true on success.
108static inline bool _send_cmd1(uint8_t cmd) {
109 bool res = false;
110
111 if (i2c_start_write(i2cAddress)) {
112 xprintf("failed to start write to %d\n", i2cAddress);
113 goto done;
114 }
115
116 if (i2c_master_write(0x0 /* command byte follows */)) {
117 print("failed to write control byte\n");
118
119 goto done;
120 }
121
122 if (i2c_master_write(cmd)) {
123 xprintf("failed to write command %d\n", cmd);
124 goto done;
125 }
126 res = true;
127done:
128 i2c_master_stop();
129 return res;
130}
131
132// Write 2-byte command sequence.
133// Returns true on success
134static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
135 if (!_send_cmd1(cmd)) {
136 return false;
137 }
138 return _send_cmd1(opr);
139}
140
141// Write 3-byte command sequence.
142// Returns true on success
143static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
144 if (!_send_cmd1(cmd)) {
145 return false;
146 }
147 if (!_send_cmd1(opr1)) {
148 return false;
149 }
150 return _send_cmd1(opr2);
151}
152
153#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
154#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
155#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
156
157static void matrix_clear(struct CharacterMatrix *matrix);
158
159static void clear_display(void) {
160 matrix_clear(&display);
161
162 // Clear all of the display bits (there can be random noise
163 // in the RAM on startup)
164 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
165 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
166
167 if (i2c_start_write(i2cAddress)) {
168 goto done;
169 }
170 if (i2c_master_write(0x40)) {
171 // Data mode
172 goto done;
173 }
174 for (uint8_t row = 0; row < MatrixRows; ++row) {
175 for (uint8_t col = 0; col < DisplayWidth; ++col) {
176 i2c_master_write(0);
177 }
178 }
179
180 display.dirty = false;
181
182done:
183 i2c_master_stop();
184}
185
186#if DEBUG_TO_SCREEN
187#undef sendchar
188static int8_t capture_sendchar(uint8_t c) {
189 sendchar(c);
190 iota_gfx_write_char(c);
191
192 if (!displaying) {
193 iota_gfx_flush();
194 }
195 return 0;
196}
197#endif
198
199bool iota_gfx_init(void) {
200 bool success = false;
201
202 send_cmd1(DisplayOff);
203 send_cmd2(SetDisplayClockDiv, 0x80);
204 send_cmd2(SetMultiPlex, DisplayHeight - 1);
205
206 send_cmd2(SetDisplayOffset, 0);
207
208
209 send_cmd1(SetStartLine | 0x0);
210 send_cmd2(SetChargePump, 0x14 /* Enable */);
211 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
212
213/// Flips the display orientation 0 degrees
214 send_cmd1(SegRemap | 0x1);
215 send_cmd1(ComScanDec);
216/*
217// the following Flip the display orientation 180 degrees
218 send_cmd1(SegRemap);
219 send_cmd1(ComScanInc);
220// end flip */
221 send_cmd2(SetComPins, 0x2);
222 send_cmd2(SetContrast, 0x8f);
223 send_cmd2(SetPreCharge, 0xf1);
224 send_cmd2(SetVComDetect, 0x40);
225 send_cmd1(DisplayAllOnResume);
226 send_cmd1(NormalDisplay);
227 send_cmd1(DeActivateScroll);
228 send_cmd1(DisplayOn);
229
230 send_cmd2(SetContrast, 0); // Dim
231
232 clear_display();
233
234 success = true;
235
236 iota_gfx_flush();
237
238#if DEBUG_TO_SCREEN
239 print_set_sendchar(capture_sendchar);
240#endif
241
242done:
243 return success;
244}
245
246bool iota_gfx_off(void) {
247 bool success = false;
248
249 send_cmd1(DisplayOff);
250 success = true;
251
252done:
253 return success;
254}
255
256bool iota_gfx_on(void) {
257 bool success = false;
258
259 send_cmd1(DisplayOn);
260 success = true;
261
262done:
263 return success;
264}
265
266static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
267 *matrix->cursor = c;
268 ++matrix->cursor;
269
270 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
271 // We went off the end; scroll the display upwards by one line
272 memmove(&matrix->display[0], &matrix->display[1],
273 MatrixCols * (MatrixRows - 1));
274 matrix->cursor = &matrix->display[MatrixRows - 1][0];
275 memset(matrix->cursor, ' ', MatrixCols);
276 }
277}
278
279static void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
280 matrix->dirty = true;
281
282 if (c == '\n') {
283 // Clear to end of line from the cursor and then move to the
284 // start of the next line
285 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
286
287 while (cursor_col++ < MatrixCols) {
288 matrix_write_char_inner(matrix, ' ');
289 }
290 return;
291 }
292
293 matrix_write_char_inner(matrix, c);
294}
295
296void iota_gfx_write_char(uint8_t c) {
297 matrix_write_char(&display, c);
298}
299
300static void matrix_write(struct CharacterMatrix *matrix, const char *data) {
301 const char *end = data + strlen(data);
302 while (data < end) {
303 matrix_write_char(matrix, *data);
304 ++data;
305 }
306}
307
308void iota_gfx_write(const char *data) {
309 matrix_write(&display, data);
310}
311
312static void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
313 while (true) {
314 uint8_t c = pgm_read_byte(data);
315 if (c == 0) {
316 return;
317 }
318 matrix_write_char(matrix, c);
319 ++data;
320 }
321}
322
323void iota_gfx_write_P(const char *data) {
324 matrix_write_P(&display, data);
325}
326
327static void matrix_clear(struct CharacterMatrix *matrix) {
328 memset(matrix->display, ' ', sizeof(matrix->display));
329 matrix->cursor = &matrix->display[0][0];
330 matrix->dirty = true;
331}
332
333void iota_gfx_clear_screen(void) {
334 matrix_clear(&display);
335}
336
337static void matrix_render(struct CharacterMatrix *matrix) {
338 last_flush = timer_read();
339 iota_gfx_on();
340#if DEBUG_TO_SCREEN
341 ++displaying;
342#endif
343
344 // Move to the home position
345 send_cmd3(PageAddr, 0, MatrixRows - 1);
346 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
347
348 if (i2c_start_write(i2cAddress)) {
349 goto done;
350 }
351 if (i2c_master_write(0x40)) {
352 // Data mode
353 goto done;
354 }
355
356 for (uint8_t row = 0; row < MatrixRows; ++row) {
357 for (uint8_t col = 0; col < MatrixCols; ++col) {
358 const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
359
360 for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
361 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
362 i2c_master_write(colBits);
363 }
364
365 // 1 column of space between chars (it's not included in the glyph)
366 i2c_master_write(0);
367 }
368 }
369
370 matrix->dirty = false;
371
372done:
373 i2c_master_stop();
374#if DEBUG_TO_SCREEN
375 --displaying;
376#endif
377}
378
379void iota_gfx_flush(void) {
380 matrix_render(&display);
381}
382
383static void matrix_update(struct CharacterMatrix *dest,
384 const struct CharacterMatrix *source) {
385 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
386 memcpy(dest->display, source->display, sizeof(dest->display));
387 dest->dirty = true;
388 }
389}
390
391static void render_status_info(void) {
392#if DEBUG_TO_SCREEN
393 if (debug_enable) {
394 return;
395 }
396#endif
397
398 struct CharacterMatrix matrix;
399
400 matrix_clear(&matrix);
401 matrix_write_P(&matrix, PSTR("USB: "));
402#ifdef PROTOCOL_LUFA
403 switch (USB_DeviceState) {
404 case DEVICE_STATE_Unattached:
405 matrix_write_P(&matrix, PSTR("Unattached"));
406 break;
407 case DEVICE_STATE_Suspended:
408 matrix_write_P(&matrix, PSTR("Suspended"));
409 break;
410 case DEVICE_STATE_Configured:
411 matrix_write_P(&matrix, PSTR("Connected"));
412 break;
413 case DEVICE_STATE_Powered:
414 matrix_write_P(&matrix, PSTR("Powered"));
415 break;
416 case DEVICE_STATE_Default:
417 matrix_write_P(&matrix, PSTR("Default"));
418 break;
419 case DEVICE_STATE_Addressed:
420 matrix_write_P(&matrix, PSTR("Addressed"));
421 break;
422 default:
423 matrix_write_P(&matrix, PSTR("Invalid"));
424 }
425#endif
426
427// Define layers here, Have not worked out how to have text displayed for each layer. Copy down the number you see and add a case for it below
428
429 char buf[40];
430 snprintf(buf,sizeof(buf), "Undef-%ld", layer_state);
431 matrix_write_P(&matrix, PSTR("\n\nLayer: "));
432 switch (layer_state) {
433 case _BASE:
434 matrix_write_P(&matrix, PSTR("Default"));
435 break;
436 case _RAISE:
437 matrix_write_P(&matrix, PSTR("Raise"));
438 break;
439 case _LOWER:
440 matrix_write_P(&matrix, PSTR("Lower"));
441 break;
442 case _ADJUST:
443 matrix_write_P(&matrix, PSTR("ADJUST"));
444 break;
445 default:
446 matrix_write(&matrix, buf);
447 }
448
449 // Host Keyboard LED Status
450 char led[40];
451 snprintf(led, sizeof(led), "\n%s %s %s",
452 (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : " ",
453 (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : " ",
454 (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : " ");
455 matrix_write(&matrix, led);
456 matrix_update(&display, &matrix);
457}
458
459void iota_gfx_task(void) {
460 render_status_info();
461
462 if (display.dirty) {
463 iota_gfx_flush();
464 }
465
466 if (timer_elapsed(last_flush) > ScreenOffInterval) {
467 iota_gfx_off();
468 }
469}
470#endif
diff --git a/keyboards/orthodox/ssd1306.h b/keyboards/orthodox/ssd1306.h
new file mode 100644
index 000000000..b0c74f987
--- /dev/null
+++ b/keyboards/orthodox/ssd1306.h
@@ -0,0 +1,17 @@
1#ifndef SSD1306_H
2#define SSD1306_H
3
4#include <stdbool.h>
5#include <stdio.h>
6
7bool iota_gfx_init(void);
8void iota_gfx_task(void);
9bool iota_gfx_off(void);
10bool iota_gfx_on(void);
11void iota_gfx_flush(void);
12void iota_gfx_write_char(uint8_t c);
13void iota_gfx_write(const char *data);
14void iota_gfx_write_P(const char *data);
15void iota_gfx_clear_screen(void);
16
17#endif