|
| 1 | +from machine import Pin |
| 2 | +from collections import namedtuple |
| 3 | +from .asciimap import ( |
| 4 | + KEY_BACKSPACE, |
| 5 | + KEY_TAB, |
| 6 | + KEY_FN, |
| 7 | + KEY_LEFT_SHIFT, |
| 8 | + KEY_ENTER, |
| 9 | + KEY_LEFT_CTRL, |
| 10 | + KEY_OPT, |
| 11 | + KEY_LEFT_ALT, |
| 12 | + kb_asciimap, |
| 13 | +) |
| 14 | + |
| 15 | +Point2D = namedtuple('Point2D', ['x', 'y']) |
| 16 | +Chart = namedtuple('Chart', ['value', 'x_1', 'x_2']) |
| 17 | +KeyValue = namedtuple('KeyValue', ['first', 'second']) |
| 18 | + |
| 19 | +_X_map_chart = ( |
| 20 | + Chart(1, 0, 1), |
| 21 | + Chart(2, 2, 3), |
| 22 | + Chart(4, 4, 5), |
| 23 | + Chart(8, 6, 7), |
| 24 | + Chart(16, 8, 9), |
| 25 | + Chart(32, 10, 11), |
| 26 | + Chart(64, 12, 13), |
| 27 | +) |
| 28 | + |
| 29 | +_key_value_map = ( |
| 30 | + ( |
| 31 | + KeyValue(ord('`'), ord('~')), |
| 32 | + KeyValue(ord('1'), ord('!')), |
| 33 | + KeyValue(ord('2'), ord('@')), |
| 34 | + KeyValue(ord('3'), ord('#')), |
| 35 | + KeyValue(ord('4'), ord('$')), |
| 36 | + KeyValue(ord('5'), ord('%')), |
| 37 | + KeyValue(ord('6'), ord('^')), |
| 38 | + KeyValue(ord('7'), ord('&')), |
| 39 | + KeyValue(ord('8'), ord('*')), |
| 40 | + KeyValue(ord('9'), ord('(')), |
| 41 | + KeyValue(ord('0'), ord(')')), |
| 42 | + KeyValue(ord('-'), ord('_')), |
| 43 | + KeyValue(ord('='), ord('+')), |
| 44 | + KeyValue(KEY_BACKSPACE, KEY_BACKSPACE), |
| 45 | + ), |
| 46 | + ( |
| 47 | + KeyValue(KEY_TAB, KEY_TAB), |
| 48 | + KeyValue(ord('q'), ord('Q')), |
| 49 | + KeyValue(ord('w'), ord('W')), |
| 50 | + KeyValue(ord('e'), ord('E')), |
| 51 | + KeyValue(ord('r'), ord('R')), |
| 52 | + KeyValue(ord('t'), ord('T')), |
| 53 | + KeyValue(ord('y'), ord('Y')), |
| 54 | + KeyValue(ord('u'), ord('U')), |
| 55 | + KeyValue(ord('i'), ord('I')), |
| 56 | + KeyValue(ord('o'), ord('O')), |
| 57 | + KeyValue(ord('p'), ord('P')), |
| 58 | + KeyValue(ord('['), ord('{')), |
| 59 | + KeyValue(ord(']'), ord('}')), |
| 60 | + KeyValue(ord('\\'), ord('|')), |
| 61 | + ), |
| 62 | + ( |
| 63 | + KeyValue(KEY_FN, KEY_FN), |
| 64 | + KeyValue(KEY_LEFT_SHIFT, KEY_LEFT_SHIFT), |
| 65 | + KeyValue(ord('a'), ord('A')), |
| 66 | + KeyValue(ord('s'), ord('S')), |
| 67 | + KeyValue(ord('d'), ord('D')), |
| 68 | + KeyValue(ord('f'), ord('F')), |
| 69 | + KeyValue(ord('g'), ord('G')), |
| 70 | + KeyValue(ord('h'), ord('H')), |
| 71 | + KeyValue(ord('j'), ord('J')), |
| 72 | + KeyValue(ord('k'), ord('K')), |
| 73 | + KeyValue(ord('l'), ord('L')), |
| 74 | + KeyValue(ord(';'), ord(':')), |
| 75 | + KeyValue(ord('\''), ord('\"')), |
| 76 | + KeyValue(KEY_ENTER, KEY_ENTER), |
| 77 | + ), |
| 78 | + ( |
| 79 | + KeyValue(KEY_LEFT_CTRL, KEY_LEFT_CTRL), |
| 80 | + KeyValue(KEY_OPT, KEY_OPT), |
| 81 | + KeyValue(KEY_LEFT_ALT, KEY_LEFT_ALT), |
| 82 | + KeyValue(ord('z'), ord('Z')), |
| 83 | + KeyValue(ord('x'), ord('X')), |
| 84 | + KeyValue(ord('c'), ord('C')), |
| 85 | + KeyValue(ord('v'), ord('V')), |
| 86 | + KeyValue(ord('b'), ord('B')), |
| 87 | + KeyValue(ord('n'), ord('N')), |
| 88 | + KeyValue(ord('m'), ord('M')), |
| 89 | + KeyValue(ord(','), ord('<')), |
| 90 | + KeyValue(ord('.'), ord('>')), |
| 91 | + KeyValue(ord('/'), ord('?')), |
| 92 | + KeyValue(ord(' '), ord(' ')), |
| 93 | + ), |
| 94 | +) |
| 95 | + |
| 96 | + |
| 97 | +class KeysState: |
| 98 | + tab = False |
| 99 | + fn = False |
| 100 | + shift = False |
| 101 | + ctrl = False |
| 102 | + opt = False |
| 103 | + alt = False |
| 104 | + delete = False |
| 105 | + enter = False |
| 106 | + space = False |
| 107 | + modifiers = 0 |
| 108 | + |
| 109 | + def __init__(self) -> None: |
| 110 | + self.word = bytearray(0) |
| 111 | + self.hid_keys = bytearray(0) |
| 112 | + self.modifier_keys = bytearray(0) |
| 113 | + |
| 114 | + def reset(self): |
| 115 | + self.tab = False |
| 116 | + self.fn = False |
| 117 | + self.shift = False |
| 118 | + self.ctrl = False |
| 119 | + self.opt = False |
| 120 | + self.alt = False |
| 121 | + self.delete = False |
| 122 | + self.enter = False |
| 123 | + self.space = False |
| 124 | + self.modifiers = 0 |
| 125 | + self.word = bytearray(0) |
| 126 | + self.hid_keys = bytearray(0) |
| 127 | + self.modifier_keys = bytearray(0) |
| 128 | + |
| 129 | + |
| 130 | +class Keyboard: |
| 131 | + |
| 132 | + def __init__(self): |
| 133 | + self.output_list = [ Pin(id, Pin.OUT, Pin.PULL_DOWN) for id in (8, 9, 11) ] |
| 134 | + self.input_list = [ Pin(id, Pin.IN, Pin.PULL_UP) for id in (13, 15, 3, 4, 5, 6, 7) ] |
| 135 | + |
| 136 | + for pin in self.output_list: |
| 137 | + pin.value(0) |
| 138 | + |
| 139 | + self._set_output(self.output_list, 0) |
| 140 | + |
| 141 | + self._key_list_buffer = [] |
| 142 | + self._key_pos_print_keys = [] |
| 143 | + self._key_pos_hid_keys = [] |
| 144 | + self._key_pos_modifier_keys = [] |
| 145 | + self._keys_state_buffer = KeysState() |
| 146 | + self._is_caps_locked = False |
| 147 | + self._last_key_size = 0 |
| 148 | + |
| 149 | + @staticmethod |
| 150 | + def _set_output(pin_list, output): |
| 151 | + output = output & 0B00000111 |
| 152 | + pin_list[0].value(output & 0B00000001) |
| 153 | + pin_list[1].value(output & 0B00000010) |
| 154 | + pin_list[2].value(output & 0B00000100) |
| 155 | + |
| 156 | + @staticmethod |
| 157 | + def _get_input(pin_list): |
| 158 | + buffer = 0x00 |
| 159 | + pin_value = 0x00 |
| 160 | + |
| 161 | + for i in range(7): |
| 162 | + pin_value = 0x00 if pin_list[i].value() == 1 else 0x01 |
| 163 | + pin_value = pin_value << i |
| 164 | + buffer = buffer | pin_value |
| 165 | + |
| 166 | + return buffer |
| 167 | + |
| 168 | + def getKey(self, point: Point2D): |
| 169 | + ret = 0 |
| 170 | + |
| 171 | + if point.x < 0 or point.y < 0: |
| 172 | + return ret |
| 173 | + |
| 174 | + if ( |
| 175 | + self._keys_state_buffer.ctrl |
| 176 | + or self._keys_state_buffer.shift |
| 177 | + or self._is_caps_locked |
| 178 | + ): |
| 179 | + ret = _key_value_map[point.x][point.y].second |
| 180 | + else: |
| 181 | + ret = _key_value_map[point.x][point.y].first |
| 182 | + return ret |
| 183 | + |
| 184 | + def updateKeyList(self): |
| 185 | + self._key_list_buffer.clear() |
| 186 | + for i in range(8): |
| 187 | + self._set_output(self.output_list, i) |
| 188 | + input_value = self._get_input(self.input_list) |
| 189 | + |
| 190 | + if input_value != 0: |
| 191 | + # Get X |
| 192 | + for j in range(7): |
| 193 | + if input_value & (0x01 << j): |
| 194 | + x = _X_map_chart[j].x_1 if (i > 3) else _X_map_chart[j].x_2 |
| 195 | + |
| 196 | + # Get Y |
| 197 | + y = (i - 4) if (i > 3) else i |
| 198 | + |
| 199 | + # Keep the same as picture |
| 200 | + y = -y |
| 201 | + y = y + 3 |
| 202 | + |
| 203 | + self._key_list_buffer.append(Point2D(x, y)) |
| 204 | + |
| 205 | + def keyList(self) -> list: |
| 206 | + return self._key_list_buffer |
| 207 | + |
| 208 | + def getKeyValue(self, point: Point2D) -> KeyValue: |
| 209 | + return _key_value_map[point.y][point.x] |
| 210 | + |
| 211 | + def isPressed(self) -> bool: |
| 212 | + return len(self._key_list_buffer) > 0 |
| 213 | + |
| 214 | + def isChange(self) -> bool: |
| 215 | + if self._last_key_size is not len(self._key_list_buffer): |
| 216 | + self._last_key_size = len(self._key_list_buffer) |
| 217 | + return True |
| 218 | + else: |
| 219 | + return False |
| 220 | + |
| 221 | + def isKeyPressed(self, ch): |
| 222 | + if self._key_list_buffer: |
| 223 | + for i in self._key_list_buffer: |
| 224 | + if self.getKeyValue(i).first == ch: |
| 225 | + return True |
| 226 | + return False |
| 227 | + |
| 228 | + def updateKeysState(self): |
| 229 | + self._keys_state_buffer.reset() |
| 230 | + self._key_pos_print_keys.clear() |
| 231 | + self._key_pos_hid_keys.clear() |
| 232 | + self._key_pos_modifier_keys.clear() |
| 233 | + |
| 234 | + # Get special keys |
| 235 | + for i in self._key_list_buffer: |
| 236 | + # modifier |
| 237 | + if self.getKeyValue(i).first == KEY_FN: |
| 238 | + self._keys_state_buffer.fn = True |
| 239 | + continue |
| 240 | + if self.getKeyValue(i).first == KEY_OPT: |
| 241 | + self._keys_state_buffer.opt = True |
| 242 | + continue |
| 243 | + |
| 244 | + if self.getKeyValue(i).first == KEY_LEFT_CTRL: |
| 245 | + self._keys_state_buffer.ctrl = True |
| 246 | + self._key_pos_modifier_keys.append(i) |
| 247 | + continue |
| 248 | + |
| 249 | + if self.getKeyValue(i).first == KEY_LEFT_SHIFT: |
| 250 | + self._keys_state_buffer.shift = True |
| 251 | + self._key_pos_modifier_keys.append(i) |
| 252 | + continue |
| 253 | + |
| 254 | + if self.getKeyValue(i).first == KEY_LEFT_ALT: |
| 255 | + self._keys_state_buffer.alt = True |
| 256 | + self._key_pos_modifier_keys.append(i) |
| 257 | + continue |
| 258 | + |
| 259 | + # function |
| 260 | + if self.getKeyValue(i).first == KEY_TAB: |
| 261 | + self._keys_state_buffer.tab = True |
| 262 | + self._key_pos_hid_keys.append(i) |
| 263 | + continue |
| 264 | + |
| 265 | + if self.getKeyValue(i).first == KEY_BACKSPACE: |
| 266 | + self._keys_state_buffer.delete = True |
| 267 | + self._key_pos_hid_keys.append(i) |
| 268 | + continue |
| 269 | + |
| 270 | + if self.getKeyValue(i).first == KEY_ENTER: |
| 271 | + self._keys_state_buffer.enter = True |
| 272 | + self._key_pos_hid_keys.append(i) |
| 273 | + continue |
| 274 | + |
| 275 | + if self.getKeyValue(i).first == ' ': |
| 276 | + self._keys_state_buffer.space = True |
| 277 | + |
| 278 | + self._key_pos_hid_keys.append(i) |
| 279 | + self._key_pos_print_keys.append(i) |
| 280 | + |
| 281 | + for i in self._key_pos_modifier_keys: |
| 282 | + key = self.getKeyValue(i).first |
| 283 | + self._keys_state_buffer.modifier_keys.append(key) |
| 284 | + |
| 285 | + for k in self._keys_state_buffer.modifier_keys: |
| 286 | + self._keys_state_buffer.modifiers |= (1 << (k - 0x80)) |
| 287 | + |
| 288 | + for i in self._key_pos_hid_keys: |
| 289 | + k = self.getKeyValue(i).first |
| 290 | + if k in (KEY_TAB, KEY_BACKSPACE, KEY_ENTER): |
| 291 | + self._keys_state_buffer.hid_keys.append(k) |
| 292 | + continue |
| 293 | + key = kb_asciimap[k] |
| 294 | + if key: |
| 295 | + self._keys_state_buffer.hid_keys.append(key) |
| 296 | + |
| 297 | + # Deal with what's left |
| 298 | + for i in self._key_pos_print_keys: |
| 299 | + if ( |
| 300 | + self._keys_state_buffer.ctrl |
| 301 | + or self._keys_state_buffer.shift |
| 302 | + or self._is_caps_locked |
| 303 | + ): |
| 304 | + self._keys_state_buffer.word.append(self.getKeyValue(i).second) |
| 305 | + else: |
| 306 | + self._keys_state_buffer.word.append(self.getKeyValue(i).first) |
| 307 | + |
| 308 | + def keysState(self) -> KeysState: |
| 309 | + return self._keys_state_buffer |
| 310 | + |
| 311 | + def capslocked(self) -> bool: |
| 312 | + return self._is_caps_locked |
| 313 | + |
| 314 | + def setCapsLocked(self, isLocked: bool): |
| 315 | + self._is_caps_locked = isLocked |
0 commit comments