aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/lets_split/common/glcdfont.c276
-rw-r--r--keyboards/lets_split/i2c.c94
-rw-r--r--keyboards/lets_split/i2c.h20
-rw-r--r--keyboards/lets_split/matrix.c7
-rw-r--r--keyboards/lets_split/rules.mk15
-rw-r--r--keyboards/lets_split/split_util.c7
-rw-r--r--keyboards/lets_split/split_util.h2
-rw-r--r--keyboards/lets_split/ssd1306.c508
8 files changed, 908 insertions, 21 deletions
diff --git a/keyboards/lets_split/common/glcdfont.c b/keyboards/lets_split/common/glcdfont.c
new file mode 100644
index 000000000..6f88bd23a
--- /dev/null
+++ b/keyboards/lets_split/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/lets_split/i2c.c b/keyboards/lets_split/i2c.c
index 084c890c4..038f37a4b 100644
--- a/keyboards/lets_split/i2c.c
+++ b/keyboards/lets_split/i2c.c
@@ -48,7 +48,7 @@ void i2c_master_init(void) {
48// returns: 0 => success 48// returns: 0 => success
49// 1 => error 49// 1 => error
50uint8_t i2c_master_start(uint8_t address) { 50uint8_t i2c_master_start(uint8_t address) {
51 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA); 51 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
52 52
53 i2c_delay(); 53 i2c_delay();
54 54
@@ -56,6 +56,7 @@ uint8_t i2c_master_start(uint8_t address) {
56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)) 56 if ( (TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
57 return 1; 57 return 1;
58 58
59 // send device address
59 TWDR = address; 60 TWDR = address;
60 TWCR = (1<<TWINT) | (1<<TWEN); 61 TWCR = (1<<TWINT) | (1<<TWEN);
61 62
@@ -159,4 +160,95 @@ ISR(TWI_vect) {
159 // Reset everything, so we are ready for the next TWI interrupt 160 // Reset everything, so we are ready for the next TWI interrupt
160 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN); 161 TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
161} 162}
163
164// from SSD1306
165/*
166void i2c_start_wait(unsigned char address)
167{
168 uint8_t twst;
169
170
171 while ( 1 )
172 {
173 // send START condition
174 TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
175
176 // wait until transmission completed
177 while(!(TWCR & (1<<TWINT)));
178
179 // check value of TWI Status Register. Mask prescaler bits.
180 twst = TW_STATUS & 0xF8;
181 if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
182
183 // send device address
184 TWDR = address;
185 TWCR = (1<<TWINT) | (1<<TWEN);
186
187 // wail until transmission completed
188 while(!(TWCR & (1<<TWINT)));
189
190 // check value of TWI Status Register. Mask prescaler bits.
191 twst = TW_STATUS & 0xF8;
192 if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
193 {
194 // device busy, send stop condition to terminate write operation
195 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
196
197 // wait until stop condition is executed and bus released
198 while(TWCR & (1<<TWSTO));
199
200 continue;
201 }
202 //if( twst != TW_MT_SLA_ACK) return 1;
203 break;
204 }
205
206}// i2c_start_wait
207*/
208/*************************************************************************
209 Issues a repeated start condition and sends address and transfer direction
210
211 Input: address and transfer direction of I2C device
212
213 Return: 0 device accessible
214 1 failed to access device
215*************************************************************************/
216/*
217unsigned char i2c_rep_start(unsigned char address)
218{
219 return i2c_master_start( address );
220
221}/* i2c_rep_start */
222/*************************************************************************
223 Read one byte from the I2C device, request more data from device
224
225 Return: byte read from I2C device
226*************************************************************************/
227/*
228unsigned char i2c_readAck(void)
229{
230 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
231 while(!(TWCR & (1<<TWINT)));
232
233 return TWDR;
234
235}/* i2c_readAck */
236
237
238/*************************************************************************
239 Read one byte from the I2C device, read is followed by a stop condition
240
241 Return: byte read from I2C device
242*************************************************************************
243unsigned char i2c_readNak(void)
244{
245 TWCR = (1<<TWINT) | (1<<TWEN);
246 while(!(TWCR & (1<<TWINT)));
247
248 return TWDR;
249
250}/* i2c_readNak */
251
252
253
162#endif 254#endif
diff --git a/keyboards/lets_split/i2c.h b/keyboards/lets_split/i2c.h
index 08ce4b009..c15b6bc50 100644
--- a/keyboards/lets_split/i2c.h
+++ b/keyboards/lets_split/i2c.h
@@ -16,7 +16,7 @@
16#define SLAVE_BUFFER_SIZE 0x10 16#define SLAVE_BUFFER_SIZE 0x10
17 17
18// i2c SCL clock frequency 18// i2c SCL clock frequency
19#define SCL_CLOCK 100000L 19#define SCL_CLOCK 400000L
20 20
21extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE]; 21extern volatile uint8_t i2c_slave_buffer[SLAVE_BUFFER_SIZE];
22 22
@@ -28,4 +28,22 @@ uint8_t i2c_master_read(int);
28void i2c_reset_state(void); 28void i2c_reset_state(void);
29void i2c_slave_init(uint8_t address); 29void i2c_slave_init(uint8_t address);
30 30
31
32static inline unsigned char i2c_start_read(unsigned char addr) {
33 return i2c_master_start((addr << 1) | I2C_READ);
34}
35
36static inline unsigned char i2c_start_write(unsigned char addr) {
37 return i2c_master_start((addr << 1) | I2C_WRITE);
38}
39
40// from SSD1306 scrips
41extern unsigned char i2c_rep_start(unsigned char addr);
42extern void i2c_start_wait(unsigned char addr);
43extern unsigned char i2c_readAck(void);
44extern unsigned char i2c_readNak(void);
45extern unsigned char i2c_read(unsigned char ack);
46
47#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
48
31#endif 49#endif
diff --git a/keyboards/lets_split/matrix.c b/keyboards/lets_split/matrix.c
index 138969004..b6e59cb7f 100644
--- a/keyboards/lets_split/matrix.c
+++ b/keyboards/lets_split/matrix.c
@@ -210,8 +210,9 @@ uint8_t matrix_scan(void)
210 if( serial_transaction() ) { 210 if( serial_transaction() ) {
211#endif 211#endif
212 // turn on the indicator led when halves are disconnected 212 // turn on the indicator led when halves are disconnected
213 TXLED1; 213// TXLED1;
214 214 TXLED0;
215
215 error_count++; 216 error_count++;
216 217
217 if (error_count > ERROR_DISCONNECT_COUNT) { 218 if (error_count > ERROR_DISCONNECT_COUNT) {
@@ -226,9 +227,7 @@ uint8_t matrix_scan(void)
226 TXLED0; 227 TXLED0;
227 error_count = 0; 228 error_count = 0;
228 } 229 }
229
230 matrix_scan_quantum(); 230 matrix_scan_quantum();
231
232 return ret; 231 return ret;
233} 232}
234 233
diff --git a/keyboards/lets_split/rules.mk b/keyboards/lets_split/rules.mk
index 0efa78550..ff159e0f0 100644
--- a/keyboards/lets_split/rules.mk
+++ b/keyboards/lets_split/rules.mk
@@ -1,7 +1,8 @@
1SRC += matrix.c \ 1SRC += matrix.c \
2 i2c.c \ 2 i2c.c \
3 split_util.c \ 3 split_util.c \
4 serial.c 4 serial.c\
5 ssd1306.c
5 6
6# MCU name 7# MCU name
7#MCU = at90usb1287 8#MCU = at90usb1287
@@ -73,15 +74,3 @@ USE_I2C ?= yes
73SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend 74SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
74 75
75CUSTOM_MATRIX = yes 76CUSTOM_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/lets_split/split_util.c b/keyboards/lets_split/split_util.c
index 226dc1881..b87bae38b 100644
--- a/keyboards/lets_split/split_util.c
+++ b/keyboards/lets_split/split_util.c
@@ -21,8 +21,8 @@ static void setup_handedness(void) {
21 #ifdef EE_HANDS 21 #ifdef EE_HANDS
22 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS); 22 isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
23 #else 23 #else
24 // I2C_MASTER_RIGHT is deprecated use MASTER_RIGHT instead since this works for both serial and i2c 24 // I2c_MASTER_RIGHT ish deprecate use MASTER_RIGHT instead since this works for both serial and i2c:
25 #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT) 25 #if defined (I2C_MASTER_RIGHT) || defined (MASTER_RIGHT)
26 isLeftHand = !has_usb(); 26 isLeftHand = !has_usb();
27 #else 27 #else
28 isLeftHand = has_usb(); 28 isLeftHand = has_usb();
@@ -33,6 +33,9 @@ static void setup_handedness(void) {
33static void keyboard_master_setup(void) { 33static void keyboard_master_setup(void) {
34#ifdef USE_I2C 34#ifdef USE_I2C
35 i2c_master_init(); 35 i2c_master_init();
36#ifdef SSD1306OLED
37 matrix_master_OLED_init ();
38#endif
36#else 39#else
37 serial_master_init(); 40 serial_master_init();
38#endif 41#endif
diff --git a/keyboards/lets_split/split_util.h b/keyboards/lets_split/split_util.h
index 6b896679c..3ae76c209 100644
--- a/keyboards/lets_split/split_util.h
+++ b/keyboards/lets_split/split_util.h
@@ -19,4 +19,6 @@ void split_keyboard_setup(void);
19bool has_usb(void); 19bool has_usb(void);
20void keyboard_slave_loop(void); 20void keyboard_slave_loop(void);
21 21
22void matrix_master_OLED_init (void);
23
22#endif 24#endif
diff --git a/keyboards/lets_split/ssd1306.c b/keyboards/lets_split/ssd1306.c
new file mode 100644
index 000000000..c25a355bf
--- /dev/null
+++ b/keyboards/lets_split/ssd1306.c
@@ -0,0 +1,508 @@
1#include "config.h"
2#include "i2c.h"
3#include <stdbool.h>
4#include <string.h>
5#include <stdio.h>
6#include "print.h"
7#include "lets_split.h"
8#include "common/glcdfont.c"
9#ifdef ADAFRUIT_BLE_ENABLE
10#include "adafruit_ble.h"
11#endif
12#ifdef PROTOCOL_LUFA
13#include "lufa.h"
14#endif
15#include "sendchar.h"
16#include "pincontrol.h"
17
18//assign the right code to your layers
19#define _BASE 0
20#define _LOWER 8
21#define _RAISE 16
22#define _FNLAYER 64
23#define _NUMLAY 128
24#define _NLOWER 136
25#define _NFNLAYER 192
26#define _MOUSECURSOR 256
27#define _ADJUST 65560
28
29// Set this to 1 to help diagnose early startup problems
30// when testing power-on with ble. Turn it off otherwise,
31// as the latency of printing most of the debug info messes
32// with the matrix scan, causing keys to drop.
33#define DEBUG_TO_SCREEN 0
34
35// Controls the SSD1306 128x32 OLED display via i2c
36
37#define i2cAddress 0x3C
38
39#define DisplayHeight 32
40#define DisplayWidth 128
41
42#define FontHeight 8
43#define FontWidth 6
44
45#define MatrixRows (DisplayHeight / FontHeight)
46#define MatrixCols (DisplayWidth / FontWidth)
47
48struct CharacterMatrix {
49 uint8_t display[MatrixRows][MatrixCols];
50 uint8_t *cursor;
51 bool dirty;
52};
53
54static struct CharacterMatrix display;
55//static uint16_t last_battery_update;
56//static uint32_t vbat;
57//#define BatteryUpdateInterval 10000 /* milliseconds */
58#define ScreenOffInterval 300000 /* milliseconds */
59#if DEBUG_TO_SCREEN
60static uint8_t displaying;
61#endif
62static uint16_t last_flush;
63
64enum ssd1306_cmds {
65 DisplayOff = 0xAE,
66 DisplayOn = 0xAF,
67
68 SetContrast = 0x81,
69 DisplayAllOnResume = 0xA4,
70
71 DisplayAllOn = 0xA5,
72 NormalDisplay = 0xA6,
73 InvertDisplay = 0xA7,
74 SetDisplayOffset = 0xD3,
75 SetComPins = 0xda,
76 SetVComDetect = 0xdb,
77 SetDisplayClockDiv = 0xD5,
78 SetPreCharge = 0xd9,
79 SetMultiPlex = 0xa8,
80 SetLowColumn = 0x00,
81 SetHighColumn = 0x10,
82 SetStartLine = 0x40,
83
84 SetMemoryMode = 0x20,
85 ColumnAddr = 0x21,
86 PageAddr = 0x22,
87
88 ComScanInc = 0xc0,
89 ComScanDec = 0xc8,
90 SegRemap = 0xa0,
91 SetChargePump = 0x8d,
92 ExternalVcc = 0x01,
93 SwitchCapVcc = 0x02,
94
95 ActivateScroll = 0x2f,
96 DeActivateScroll = 0x2e,
97 SetVerticalScrollArea = 0xa3,
98 RightHorizontalScroll = 0x26,
99 LeftHorizontalScroll = 0x27,
100 VerticalAndRightHorizontalScroll = 0x29,
101 VerticalAndLeftHorizontalScroll = 0x2a,
102};
103
104
105// Write command sequence.
106// Returns true on success.
107static inline bool _send_cmd1(uint8_t cmd) {
108 bool res = false;
109
110 if (i2c_start_write(i2cAddress)) {
111 xprintf("failed to start write to %d\n", i2cAddress);
112 goto done;
113 }
114
115 if (i2c_master_write(0x0 /* command byte follows */)) {
116 print("failed to write control byte\n");
117
118 goto done;
119 }
120
121 if (i2c_master_write(cmd)) {
122 xprintf("failed to write command %d\n", cmd);
123 goto done;
124 }
125 res = true;
126done:
127 i2c_master_stop();
128 return res;
129}
130
131// Write 2-byte command sequence.
132// Returns true on success
133static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) {
134 if (!_send_cmd1(cmd)) {
135 return false;
136 }
137 return _send_cmd1(opr);
138}
139
140// Write 3-byte command sequence.
141// Returns true on success
142static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) {
143 if (!_send_cmd1(cmd)) {
144 return false;
145 }
146 if (!_send_cmd1(opr1)) {
147 return false;
148 }
149 return _send_cmd1(opr2);
150}
151
152#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;}
153#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;}
154#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;}
155
156static void matrix_clear(struct CharacterMatrix *matrix);
157
158static void clear_display(void) {
159 matrix_clear(&display);
160
161 // Clear all of the display bits (there can be random noise
162 // in the RAM on startup)
163 send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
164 send_cmd3(ColumnAddr, 0, DisplayWidth - 1);
165
166 if (i2c_start_write(i2cAddress)) {
167 goto done;
168 }
169 if (i2c_master_write(0x40)) {
170 // Data mode
171 goto done;
172 }
173 for (uint8_t row = 0; row < MatrixRows; ++row) {
174 for (uint8_t col = 0; col < DisplayWidth; ++col) {
175 i2c_master_write(0);
176 }
177 }
178
179 display.dirty = false;
180
181done:
182 i2c_master_stop();
183}
184
185#if DEBUG_TO_SCREEN
186#undef sendchar
187static int8_t capture_sendchar(uint8_t c) {
188 sendchar(c);
189 iota_gfx_write_char(c);
190
191 if (!displaying) {
192 iota_gfx_flush();
193 }
194 return 0;
195}
196#endif
197
198bool iota_gfx_init(void) {
199 bool success = false;
200
201 send_cmd1(DisplayOff);
202 send_cmd2(SetDisplayClockDiv, 0x80);
203 send_cmd2(SetMultiPlex, DisplayHeight - 1);
204
205 send_cmd2(SetDisplayOffset, 0);
206
207
208 send_cmd1(SetStartLine | 0x0);
209 send_cmd2(SetChargePump, 0x14 /* Enable */);
210 send_cmd2(SetMemoryMode, 0 /* horizontal addressing */);
211
212/* Flips the display orientation 0 degrees
213 send_cmd1(SegRemap | 0x1);
214 send_cmd1(ComScanDec);
215*/
216// the following Flip the display orientation 180 degrees */
217 send_cmd1(SegRemap);
218 send_cmd1(ComScanInc);
219//end flip
220 send_cmd2(SetComPins, 0x2);
221 send_cmd2(SetContrast, 0x8f);
222 send_cmd2(SetPreCharge, 0xf1);
223 send_cmd2(SetVComDetect, 0x40);
224 send_cmd1(DisplayAllOnResume);
225 send_cmd1(NormalDisplay);
226 send_cmd1(DeActivateScroll);
227 send_cmd1(DisplayOn);
228
229 send_cmd2(SetContrast, 0); // Dim
230
231 clear_display();
232
233 success = true;
234
235 iota_gfx_flush();
236
237#if DEBUG_TO_SCREEN
238 print_set_sendchar(capture_sendchar);
239#endif
240
241done:
242 return success;
243}
244
245bool iota_gfx_off(void) {
246 bool success = false;
247
248 send_cmd1(DisplayOff);
249 success = true;
250
251done:
252 return success;
253}
254
255bool iota_gfx_on(void) {
256 bool success = false;
257
258 send_cmd1(DisplayOn);
259 success = true;
260
261done:
262 return success;
263}
264
265static void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
266 *matrix->cursor = c;
267 ++matrix->cursor;
268
269 if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
270 // We went off the end; scroll the display upwards by one line
271 memmove(&matrix->display[0], &matrix->display[1],
272 MatrixCols * (MatrixRows - 1));
273 matrix->cursor = &matrix->display[MatrixRows - 1][0];
274 memset(matrix->cursor, ' ', MatrixCols);
275 }
276}
277
278static void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
279 matrix->dirty = true;
280
281 if (c == '\n') {
282 // Clear to end of line from the cursor and then move to the
283 // start of the next line
284 uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
285
286 while (cursor_col++ < MatrixCols) {
287 matrix_write_char_inner(matrix, ' ');
288 }
289 return;
290 }
291
292 matrix_write_char_inner(matrix, c);
293}
294
295void iota_gfx_write_char(uint8_t c) {
296 matrix_write_char(&display, c);
297}
298
299static void matrix_write(struct CharacterMatrix *matrix, const char *data) {
300 const char *end = data + strlen(data);
301 while (data < end) {
302 matrix_write_char(matrix, *data);
303 ++data;
304 }
305}
306
307void iota_gfx_write(const char *data) {
308 matrix_write(&display, data);
309}
310
311static void matrix_write_P(struct CharacterMatrix *matrix, const char *data) {
312 while (true) {
313 uint8_t c = pgm_read_byte(data);
314 if (c == 0) {
315 return;
316 }
317 matrix_write_char(matrix, c);
318 ++data;
319 }
320}
321
322void iota_gfx_write_P(const char *data) {
323 matrix_write_P(&display, data);
324}
325
326static void matrix_clear(struct CharacterMatrix *matrix) {
327 memset(matrix->display, ' ', sizeof(matrix->display));
328 matrix->cursor = &matrix->display[0][0];
329 matrix->dirty = true;
330}
331
332void iota_gfx_clear_screen(void) {
333 matrix_clear(&display);
334}
335
336static void matrix_render(struct CharacterMatrix *matrix) {
337 last_flush = timer_read();
338 iota_gfx_on();
339#if DEBUG_TO_SCREEN
340 ++displaying;
341#endif
342
343 // Move to the home position
344 send_cmd3(PageAddr, 0, MatrixRows - 1);
345 send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1);
346
347 if (i2c_start_write(i2cAddress)) {
348 goto done;
349 }
350 if (i2c_master_write(0x40)) {
351 // Data mode
352 goto done;
353 }
354
355 for (uint8_t row = 0; row < MatrixRows; ++row) {
356 for (uint8_t col = 0; col < MatrixCols; ++col) {
357 const uint8_t *glyph = font + (matrix->display[row][col] * (FontWidth - 1));
358
359 for (uint8_t glyphCol = 0; glyphCol < FontWidth - 1; ++glyphCol) {
360 uint8_t colBits = pgm_read_byte(glyph + glyphCol);
361 i2c_master_write(colBits);
362 }
363
364 // 1 column of space between chars (it's not included in the glyph)
365 i2c_master_write(0);
366 }
367 }
368
369 matrix->dirty = false;
370
371done:
372 i2c_master_stop();
373#if DEBUG_TO_SCREEN
374 --displaying;
375#endif
376}
377
378void iota_gfx_flush(void) {
379 matrix_render(&display);
380}
381
382//#include "LUFA/Drivers/Peripheral/ADC.h"
383
384/* Returns the battery voltage; returns the number of millivolts
385static uint32_t read_battery_voltage(void) {
386 if (last_battery_update == 0 ||
387 timer_elapsed(last_battery_update) > BatteryUpdateInterval) {
388 ADC_Init(ADC_SINGLE_CONVERSION | ADC_PRESCALE_32);
389 ADC_SetupChannel(12);
390 vbat = 2 * 3.3 * ADC_GetChannelReading(ADC_REFERENCE_AVCC | ADC_CHANNEL12);
391
392 last_battery_update = timer_read();
393 }
394 return vbat;
395} */
396
397static void matrix_update(struct CharacterMatrix *dest,
398 const struct CharacterMatrix *source) {
399 if (memcmp(dest->display, source->display, sizeof(dest->display))) {
400 memcpy(dest->display, source->display, sizeof(dest->display));
401 dest->dirty = true;
402 }
403}
404
405static void render_status_info(void) {
406#if DEBUG_TO_SCREEN
407 if (debug_enable) {
408 return;
409 }
410#endif
411
412 struct CharacterMatrix matrix;
413
414 matrix_clear(&matrix);
415 matrix_write_P(&matrix, PSTR("USB: "));
416#ifdef PROTOCOL_LUFA
417 switch (USB_DeviceState) {
418 case DEVICE_STATE_Unattached:
419 matrix_write_P(&matrix, PSTR("Unattached"));
420 break;
421 case DEVICE_STATE_Suspended:
422 matrix_write_P(&matrix, PSTR("Suspended"));
423 break;
424 case DEVICE_STATE_Configured:
425 matrix_write_P(&matrix, PSTR("Connected"));
426 break;
427 case DEVICE_STATE_Powered:
428 matrix_write_P(&matrix, PSTR("Powered"));
429 break;
430 case DEVICE_STATE_Default:
431 matrix_write_P(&matrix, PSTR("Default"));
432 break;
433 case DEVICE_STATE_Addressed:
434 matrix_write_P(&matrix, PSTR("Addressed"));
435 break;
436 default:
437 matrix_write_P(&matrix, PSTR("Invalid"));
438 }
439#endif
440
441 // matrix_write_P(&matrix, (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? PSTR("\n NUMLOCK") : PSTR("\n"));
442// matrix_write_P(&matrix, PSTR("\nBLE: "));
443//#ifdef ADAFRUIT_BLE_ENABLE
444// matrix_write_P(&matrix, adafruit_ble_is_connected() ? PSTR("Connected")
445// : PSTR("Not Connected"));
446//#endif
447
448// char buf[40];
449// snprintf(buf, sizeof(buf), "VBat: %4lumV\nLayer: 0x%04lx %s",
450// read_battery_voltage(), layer_state,
451// (host_keyboard_leds() & USB_LED_CAPS_LOCK) ? "CAPS" : "");
452// matrix_write(&matrix, buf);
453
454 char buf[40];
455 snprintf(buf,sizeof(buf), "Undef-%ld", layer_state);
456 matrix_write_P(&matrix, PSTR("\n\nLayer: "));
457 switch (layer_state) {
458 case _BASE:
459 matrix_write_P(&matrix, PSTR("Default"));
460 break;
461 case _RAISE:
462 matrix_write_P(&matrix, PSTR("Raise"));
463 break;
464 case _LOWER:
465 matrix_write_P(&matrix, PSTR("Lower"));
466 break;
467 case _MOUSECURSOR:
468 matrix_write_P(&matrix, PSTR("Mouse/Macro"));
469 break;
470 case _FNLAYER:
471 matrix_write_P(&matrix, PSTR("Symbols/Fn"));
472 break;
473 case _NUMLAY:
474 matrix_write_P(&matrix, PSTR("Numbers"));
475 break;
476 case _NLOWER:
477 matrix_write_P(&matrix, PSTR("Num + Lower"));
478 break;
479 case _NFNLAYER:
480 matrix_write_P(&matrix, PSTR("Num + FN"));
481 break;
482 case _ADJUST:
483 matrix_write_P(&matrix, PSTR("ADJUST"));
484 break;
485 default:
486 matrix_write(&matrix, buf);
487 }
488
489 char led[40];
490 snprintf(led, sizeof(led), "\n%s %s %s",
491 (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) ? "NUMLOCK" : " ",
492 (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) ? "CAPS" : " ",
493 (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) ? "SCLK" : " ");
494 matrix_write(&matrix, led);
495 matrix_update(&display, &matrix);
496}
497
498void iota_gfx_task(void) {
499 render_status_info();
500
501 if (display.dirty) {
502 iota_gfx_flush();
503 }
504
505 if (timer_elapsed(last_flush) > ScreenOffInterval) {
506 iota_gfx_off();
507 }
508}