source: rgbkbd/trunk/rgbkbd/geometry.py @ 71

Last change on this file since 71 was 71, checked in by retracile, 9 years ago

Initial import of source code

  • Property svn:executable set to *
File size: 8.0 KB
Line 
1#!/usr/bin/python
2"""Describes the physical layout of the keyboard"""
3
4from color import Color, Colors
5
6# Keys are described by the "pixels" they cover
7# Y is in rows, the 0 row has the space bar, the the 5 row has the function
8# keys, and the 6 row has the light, lock, and mute buttons
9# Column values; there are 2 columns per normal width key.  This isn't exact,
10# but I think it would be close enough.  There are 22 key widths, so 44 columns
11# in the grid.
12# FIXME: Should add a column for the empty space on either side of the cursor
13# keys, making it 46 columns total.
14
15def _key_row(left, row, keys):
16    """Utility function to reduce how many hardcoded numbers are required in
17    the key positions description.
18    """
19    entries = []
20    for n, key in enumerate(keys):
21        entries.append( (key, [(left+2*n, row), (left+2*n+1, row)]) )
22    return entries
23
24
25key_positions = dict(
26    # Top row
27    [
28    ("light", [(30, 6), (31, 6)]),
29    ("lock", [(32, 6), (33, 6)]),
30
31    ("mute", [(38, 6), (39, 6)]),
32    #("volup", [(41, 6), (42, 6)]), # Volume scrollwheel does not have a backlight
33    #("voldn", [(41, 6), (42, 6)]),
34
35    # Function key row
36    ("esc", [(0, 5), (1, 5)]),
37
38    ] + _key_row(4, 5, [
39    "f1",
40    "f2",
41    "f3",
42    "f4",
43    ]) + [
44
45    ] + _key_row(13, 5, [
46    "f5",
47    "f6",
48    "f7",
49    "f8",
50    ]) + [
51
52    ] + _key_row(22, 5, [
53    "f9",
54    "f10",
55    "f11",
56    "f12",
57    ]) + [
58
59    ] + _key_row(30, 5, [
60    "prtscn",
61    "scroll",
62    "pause",
63    ]) + [
64
65    ] + _key_row(36, 5, [
66    "stop",
67    "prev",
68    "play",
69    "next",
70    ]) + [
71
72    # Number row
73    ] + _key_row(0, 4, [
74    "grave",
75    "1",
76    "2",
77    "3",
78    "4",
79    "5",
80    "6",
81    "7",
82    "8",
83    "9",
84    "0",
85    "minus",
86    "equal",
87    ]) + [
88    ("bspace", [(26, 4), (27, 4), (28, 4), (29, 4)]),
89
90    ] + _key_row(30, 4, [
91    "ins",
92    "home",
93    "pgup",
94
95    "numlock",
96    "numslash",
97    "numstar",
98    "numminus",
99    ]) + [
100
101    # QWERTY row
102    ("tab", [(0, 3), (1, 3), (2, 3)]),
103    ] + _key_row(3, 3, [
104    "q",
105    "w",
106    "e",
107    "r",
108    "t",
109    "y",
110    "u",
111    "i",
112    "o",
113    "p",
114    "lbrace",
115    "rbrace",
116    ]) + [
117    ("bslash", [(27, 3), (28, 3), (29, 3)]),
118
119    ] + _key_row(30, 3, [
120    "del",
121    "end",
122    "pgdn",
123
124    "num7",
125    "num8",
126    "num9",
127    ]) + [
128    ("numplus", [(42, 3), (43, 3), (42, 4), (43, 4)]), # Note this extends into the row below
129
130    # Home row
131    ("caps", [(0, 2), (1, 2), (2, 2)]),
132    ] + _key_row(3, 2, [
133    "a",
134    "s",
135    "d",
136    "f",
137    "g",
138    "h",
139    "j",
140    "k",
141    "l",
142    "colon",
143    "quote",
144    ]) + [
145    ("enter", [(26, 2), (27, 2), (28, 2), (29, 2)]),
146
147
148    ] + _key_row(36, 2, [
149    "num4",
150    "num5",
151    "num6",
152    ]) + [
153
154    # Shift row
155    ("lshift", [(0, 1), (1, 1), (2, 1), (3, 1)]),
156    ] + _key_row(4, 1, [
157    "z",
158    "x",
159    "c",
160    "v",
161    "b",
162    "n",
163    "m",
164    "comma",
165    "dot",
166    "slash",
167    ]) + [
168    ("rshift", [(24, 1), (25, 1), (26, 1), (27, 1), (28, 1), (29, 1)]),
169
170    ("up", [(32, 1), (33, 1)]),
171
172    ] + _key_row(36, 1, [
173    "num1",
174    "num2",
175    "num3",
176    ]) + [
177    ("numenter", [(42, 1), (43, 1), (42, 0), (43, 0)]), # Extends into row below
178
179    # Bottom row
180    ("lctrl", [(0, 0), (1, 0), (2, 0)]),
181    ("lwin", [(3, 0), (4, 0)]),
182    ("lalt", [(5, 0), (6, 0), (7, 0)]),
183    ("space", [(x, 0) for x in range(8, 20)]),
184    ("ralt", [(20, 0), (21, 0), (22, 0)]),
185    ("rwin", [(23, 0), (24, 0)]),
186    ("rmenu", [(25, 0), (26, 0)]),
187    ("rctrl", [(27, 0), (28, 0), (29, 0)]),
188
189    ] + _key_row(30, 0, [
190    "left",
191    "down",
192    "right",
193    ]) + [
194
195    ("num0", [(36, 0), (37, 0), (38, 0), (39, 0)]),
196    ("numdot", [(40, 0), (41, 0)]),
197
198    # The K70 does not have the extra keys
199    #("g1", [(x, y), (x, y)]),
200    #("g2", [(x, y), (x, y)]),
201    #("g3", [(x, y), (x, y)]),
202    #("g4", [(x, y), (x, y)]),
203    #("g5", [(x, y), (x, y)]),
204    #("g6", [(x, y), (x, y)]),
205    #("g7", [(x, y), (x, y)]),
206    #("g8", [(x, y), (x, y)]),
207    #("g9", [(x, y), (x, y)]),
208    #("g10", [(x, y), (x, y)]),
209    #("g11", [(x, y), (x, y)]),
210    #("g12", [(x, y), (x, y)]),
211    #("g13", [(x, y), (x, y)]),
212    #("g14", [(x, y), (x, y)]),
213    #("g15", [(x, y), (x, y)]),
214    #("g16", [(x, y), (x, y)]),
215    #("g17", [(x, y), (x, y)]),
216    #("g18", [(x, y), (x, y)]),
217
218    #("mr", [(x, y), (x, y)]),
219    #("m1", [(x, y), (x, y)]),
220    #("m2", [(x, y), (x, y)]),
221    #("m3", [(x, y), (x, y)]),
222    ]
223)
224
225
226class KeyMatrix(object):
227    """(X,Y)<->Key mapping object to allow treating the keyboard as an image
228    grid.
229    """
230    x = 44
231    y = 7
232    def __init__(self, background=Colors.BLACK):
233        # 2-dimensional array addressible as self.data[x][y]
234        self.data = [[background for y in range(self.y)] for x in range(self.x)]
235
236    def set_pixel(self, x, y, color):
237        """Sets a pixel to a particular color."""
238        try:
239            self.data[x][y] = color
240        except IndexError, error:
241            print "Failed dereferencing (%s,%s)" % (x, y)
242
243    def set_key(self, key, color):
244        """Sets all pixels for a key to a particular color."""
245        for x, y in key_positions[key]:
246            self.set_pixel(x, y, color)
247
248    def get_key(self, key):
249        """Returns the average color of the pixels for a key."""
250        colors = [self.data[x][y] for x,y in key_positions[key]]
251        # There is also a case for taking the mode instead of the mean
252        # However, for that to make a meaningful difference, we'd probably need to
253        # allocate more pixels to each key
254        return Color.average(colors)
255
256
257class Keys(object):
258    """Shortcut names for logical groups of keys on a keyboard"""
259    ALL = ','.join(key_positions.keys())
260
261    HOME = "a,s,d,f,j,k,l,colon"
262    WASD = "w,a,s,d"
263    FUNCTION = "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12"
264    NUM_PAD = \
265        "num0," \
266        "num1," \
267        "num2," \
268        "num3," \
269        "num4," \
270        "num5," \
271        "num6," \
272        "num7," \
273        "num8," \
274        "num9," \
275        "numdot," \
276        "numenter," \
277        "numlock," \
278        "numminus," \
279        "numplus," \
280        "numslash," \
281        "numstar"
282    MEDIA = \
283        "mute," \
284        "stop," \
285        "prev," \
286        "play," \
287        "next"
288    MACRO = \
289        "g1," \
290        "g2," \
291        "g3," \
292        "g4," \
293        "g5," \
294        "g6," \
295        "g7," \
296        "g8," \
297        "g9," \
298        "g10," \
299        "g11," \
300        "g12," \
301        "g13," \
302        "g14," \
303        "g15," \
304        "g16," \
305        "g17," \
306        "g18"
307    ARROW = \
308        "up," \
309        "left," \
310        "down," \
311        "right"
312    HOME_GROUP = \
313        "ins," \
314        "home," \
315        "pgup," \
316        "del," \
317        "end," \
318        "pgdn"
319    NAV = ','.join([ARROW, HOME_GROUP])
320    MOD = \
321        "lctrl," \
322        "lwin," \
323        "lalt," \
324        "lshift," \
325        "rmenu," \
326        "rctrl," \
327        "rwin," \
328        "ralt," \
329        "rshift"
330    # Typing keys are the keys that should count for WPM calculations
331    TYPING = \
332        "grave," \
333        "1," \
334        "2," \
335        "3," \
336        "4," \
337        "5," \
338        "6," \
339        "7," \
340        "8," \
341        "9," \
342        "0," \
343        "minus," \
344        "tab," \
345        "q," \
346        "w," \
347        "e," \
348        "r," \
349        "t," \
350        "y," \
351        "u," \
352        "i," \
353        "o," \
354        "p," \
355        "lbrace," \
356        "a," \
357        "s," \
358        "d," \
359        "f," \
360        "g," \
361        "h," \
362        "j," \
363        "k," \
364        "l," \
365        "colon," \
366        "quote," \
367        "z," \
368        "x," \
369        "c," \
370        "v," \
371        "b," \
372        "n," \
373        "m," \
374        "comma," \
375        "dot," \
376        "slash," \
377        "space," \
378        "f12," \
379        "rbrace," \
380        "bslash," \
381        "enter," \
382        "equal," \
383        "numslash," \
384        "numstar," \
385        "numminus," \
386        "numplus," \
387        "numenter," \
388        "num7," \
389        "num8," \
390        "num9," \
391        "num4," \
392        "num5," \
393        "num6," \
394        "num1," \
395        "num2," \
396        "num3," \
397        "num0," \
398        "numdot"
Note: See TracBrowser for help on using the repository browser.