Skip to content

Commit cf04472

Browse files
committed
initial
0 parents  commit cf04472

10 files changed

+22528
-0
lines changed

README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
Python Keyboard
2+
===============
3+
4+
A hand-wired keybaord powered by Python
5+
6+
![](img/python-inside-keyboard.png)
7+
8+
![](img/colorful-keycaps.jpg)
9+
10+
11+
## Steps
12+
1. [hand-wire the keyboard](hardware.md)
13+
2. Follow [the guide - How to Program Pitaya Go](https://wiki.makerdiary.com/pitaya-go/programming/) to flash [CircuitPython firmware](circuitpython-5.3.0-for-pitaya-go.hex)
14+
3. Download two CircuitPython libraries - [adafruit-ble](https://github.com/adafruit/Adafruit_CircuitPython_BLE) & [adafruit-hid](https://github.com/adafruit/Adafruit_CircuitPython_HID) and put them into the `lib` directory of the USB drive named CIRCUITPY.
15+
16+
```
17+
CIRCUITPY
18+
├───code.py
19+
└───lib
20+
├───adafruit_ble
21+
└───adafruit_hid
22+
```
23+
24+
4. Copy the Python code to `code.py`. When `code.py` is reloaded, you will get a keyboard with USB & Bluetooth
25+
26+
27+
```python
28+
import time
29+
from board import *
30+
import digitalio
31+
import usb_hid
32+
33+
import adafruit_ble
34+
from adafruit_ble.advertising import Advertisement
35+
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
36+
from adafruit_ble.services.standard.hid import HIDService
37+
from adafruit_hid.keyboard import Keyboard
38+
from adafruit_hid.keycode import Keycode as _
39+
40+
ROWS = (P27, P13, P30, P20, P3)
41+
COLS = (P26, P31, P29, P28, P5, P4, P24, P25, P23, P22, P14, P15, P16, P17)
42+
43+
KEYMAP = (_.ESCAPE, _.ONE, _.TWO, _.THREE, _.FOUR, _.FIVE, _.SIX, _.SEVEN, _.EIGHT, _.NINE, _.ZERO, _.MINUS, _.EQUALS, _.BACKSPACE,
44+
_.TAB, _.Q, _.W, _.E, _.R, _.T, _.Y, _.U, _.I, _.O, _.P, _.LEFT_BRACKET, _.RIGHT_BRACKET, _.BACKSLASH,
45+
_.CAPS_LOCK, _.A, _.S, _.D, _.F, _.G, _.H, _.J, _.K, _.L, _.SEMICOLON, _.QUOTE, None, _.ENTER,
46+
_.LEFT_SHIFT, _.Z, _.X, _.C, _.V, _.B, _.N, _.M, _.COMMA, _.PERIOD, _.FORWARD_SLASH, None, _.RIGHT_SHIFT, None,
47+
_.LEFT_CONTROL, _.LEFT_ALT, _.LEFT_GUI, None, None, _.SPACE, None, None, _.RIGHT_ALT, _.RIGHT_GUI, _.APPLICATION, _.RIGHT_CONTROL, None, None)
48+
49+
class Matrix:
50+
def __init__(self, rows=ROWS, cols=COLS):
51+
self.rows = []
52+
for pin in rows:
53+
io = digitalio.DigitalInOut(pin)
54+
io.direction = digitalio.Direction.OUTPUT
55+
io.drive_mode = digitalio.DriveMode.PUSH_PULL
56+
io.value = 0
57+
self.rows.append(io)
58+
self.cols = []
59+
for pin in cols:
60+
io = digitalio.DigitalInOut(pin)
61+
io.direction = digitalio.Direction.INPUT
62+
io.pull = digitalio.Pull.DOWN
63+
self.cols.append(io)
64+
self.pressed_keys = []
65+
66+
def scan(self):
67+
new_keys = []
68+
pressed_keys = []
69+
released_keys = self.pressed_keys
70+
for r in range(len(self.rows)):
71+
self.rows[r].value = 1
72+
for c in range(len(self.cols)):
73+
if self.cols[c].value:
74+
key = r * len(self.cols) + c
75+
pressed_keys.append(key)
76+
if key in released_keys:
77+
released_keys.remove(key)
78+
else:
79+
new_keys.append(key)
80+
self.rows[r].value = 0
81+
self.pressed_keys = pressed_keys
82+
return pressed_keys, released_keys, new_keys
83+
84+
def main():
85+
hid = HIDService()
86+
advertisement = ProvideServicesAdvertisement(hid)
87+
advertisement.appearance = 961
88+
ble = adafruit_ble.BLERadio()
89+
if ble.connected:
90+
for c in ble.connections:
91+
c.disconnect()
92+
ble.start_advertising(advertisement)
93+
advertising = True
94+
ble_keyboard = Keyboard(hid.devices)
95+
96+
matrix = Matrix()
97+
usb_keyboard = Keyboard(usb_hid.devices)
98+
99+
while True:
100+
pressed_keys, released_keys, new_keys = matrix.scan()
101+
if released_keys:
102+
released_keycodes = list(map(lambda i: KEYMAP[i], released_keys))
103+
print('released keys {}'.format(released_keycodes))
104+
105+
usb_keyboard.release(*released_keycodes)
106+
if ble.connected:
107+
advertising = False
108+
ble_keyboard.release(*released_keycodes)
109+
if new_keys:
110+
new_keycodes = list(map(lambda i: KEYMAP[i], new_keys))
111+
print('new keys {}'.format(new_keycodes))
112+
usb_keyboard.press(*new_keycodes)
113+
if ble.connected:
114+
advertising = False
115+
ble_keyboard.press(*new_keycodes)
116+
117+
if not ble.connected and not advertising:
118+
ble.start_advertising(advertisement)
119+
advertising = True
120+
121+
time.sleep(0.001)
122+
123+
if __name__ == '__main__':
124+
main()
125+
```
126+
127+
If you have a different configuration of raws and columns, you must change `ROWS` and `COLS` in the code.
128+
129+

0 commit comments

Comments
 (0)