Skip to content

Commit bb759dd

Browse files
committed
adding code for ESP32-S3 macropad
1 parent 237cb1a commit bb759dd

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

ESP32-S3_BLE_MacroPad/code.py

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import board
6+
import keypad
7+
import rotaryio
8+
import neopixel
9+
import usb_hid
10+
from adafruit_hid.keyboard import Keyboard
11+
from adafruit_hid.keycode import Keycode
12+
import adafruit_ble
13+
from adafruit_ble.advertising import Advertisement
14+
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
15+
from adafruit_ble.services.standard.hid import HIDService
16+
from adafruit_ble.services.standard.device_info import DeviceInfoService
17+
18+
# BLE advertisement names
19+
ble_maker = "Adafruit Industries"
20+
ble_name = "BLE ESP32-S3 MacroPad"
21+
# neopixel colors
22+
RED = (255, 0, 0)
23+
ORANGE = (255, 127, 0)
24+
YELLOW = (255, 255, 0)
25+
GREEN = (0, 255, 0)
26+
AQUA = (0, 255, 255)
27+
BLUE = (0, 0, 255)
28+
PURPLE = (127, 0, 255)
29+
PINK = (255, 0, 255)
30+
OFF = (0, 0, 0)
31+
# axis states selected with keys 9-11
32+
axis_states = [0, "x", "y", "z"]
33+
state = axis_states[0]
34+
# keymap for key matrix
35+
keymap = {
36+
(0): (axis_states[0], [Keycode.HOME], RED), # HOME X/Y
37+
(1): (axis_states[0], [Keycode.END], ORANGE), # HOME Z
38+
(2): (axis_states[0], (Keycode.HOME, Keycode.END), YELLOW), # HOME ALL
39+
40+
(3): (axis_states[0], (Keycode.SHIFT, Keycode.A), GREEN), # SHORTCUT A
41+
(4): (axis_states[0], (Keycode.SHIFT, Keycode.B), AQUA), # SHORTCUT B
42+
(5): (axis_states[0], (Keycode.SHIFT, Keycode.C), BLUE), # SHORTCUT C
43+
44+
(6): (axis_states[0], [Keycode.TWO], AQUA), # SET STEPS 1MM
45+
(7): (axis_states[0], [Keycode.THREE], PURPLE), # SET STEPS 10MM
46+
(8): (axis_states[0], [Keycode.FOUR], PINK), # SET STEPS 100MM
47+
48+
(9): (axis_states[1], None, RED), # SET X-AXIS STATE
49+
(10): (axis_states[2], None, GREEN), # SET Y-AXIS STATE
50+
(11): (axis_states[3], None, BLUE), # SET Z-AXIS STATE
51+
}
52+
# keymap for encoder based on state; pos = [0], neg = [1]
53+
encoder_map = {
54+
("x"): ([Keycode.RIGHT_ARROW], [Keycode.LEFT_ARROW]),
55+
("y"): ([Keycode.UP_ARROW], [Keycode.DOWN_ARROW]),
56+
("z"): ([Keycode.W], [Keycode.S]),
57+
}
58+
# make a keyboard
59+
kbd = Keyboard(usb_hid.devices)
60+
# key matrix
61+
COLUMNS = 3
62+
ROWS = 4
63+
keys = keypad.KeyMatrix(
64+
row_pins=(board.D12, board.D11, board.D10, board.D9),
65+
column_pins=(board.A0, board.A1, board.A2),
66+
columns_to_anodes=False,
67+
)
68+
# neopixels and key num to pixel function
69+
pixels = neopixel.NeoPixel(board.D5, 12, brightness=0.3)
70+
def key_to_pixel_map(key_number):
71+
row = key_number // COLUMNS
72+
column = key_number % COLUMNS
73+
if row % 2 == 1:
74+
column = COLUMNS - column - 1
75+
return row * COLUMNS + column
76+
pixels.fill(OFF) # Begin with pixels off.
77+
78+
# make an encoder
79+
encoder = rotaryio.IncrementalEncoder(board.A3, board.A4)
80+
last_position = 0
81+
82+
# connect to BLE
83+
hid = HIDService()
84+
device_info = DeviceInfoService(software_revision=adafruit_ble.__version__,
85+
manufacturer=ble_maker)
86+
advertisement = ProvideServicesAdvertisement(hid)
87+
# Advertise as "Keyboard" (0x03C1) icon when pairing
88+
# https://www.bluetooth.com/specifications/assigned-numbers/
89+
advertisement.appearance = 961
90+
scan_response = Advertisement()
91+
scan_response.complete_name = ble_name
92+
93+
ble = adafruit_ble.BLERadio()
94+
if not ble.connected:
95+
print("advertising")
96+
ble.start_advertising(advertisement, scan_response)
97+
else:
98+
print("already connected")
99+
print(ble.connections)
100+
101+
while True:
102+
while not ble.connected:
103+
pass
104+
while ble.connected:
105+
# poll for key event
106+
key_event = keys.events.get()
107+
# get position of encoder
108+
position = encoder.position
109+
# if position changes..
110+
if position != last_position:
111+
# ..and it increases..
112+
if position > last_position:
113+
# ..and state is x:
114+
if state is axis_states[1]:
115+
kbd.press(*encoder_map[state][0])
116+
# ..and state is y:
117+
if state is axis_states[2]:
118+
kbd.press(*encoder_map[state][0])
119+
# ..and state is z:
120+
if state is axis_states[3]:
121+
kbd.press(*encoder_map[state][0])
122+
# ..and it decreases..
123+
if position < last_position:
124+
# ..and state is x:
125+
if state is axis_states[1]:
126+
kbd.press(*encoder_map[state][1])
127+
# ..and state is y:
128+
if state is axis_states[2]:
129+
kbd.press(*encoder_map[state][1])
130+
# ..and state is z:
131+
if state is axis_states[3]:
132+
kbd.press(*encoder_map[state][1])
133+
# print(position)
134+
# release all keys
135+
kbd.release_all()
136+
# update last_position
137+
last_position = position
138+
# if a key event..
139+
if key_event:
140+
# print(key_event)
141+
# ..and it's pressed..
142+
if key_event.pressed:
143+
# ..and it's keys 0-8, send key presses from keymap:
144+
if keymap[key_event.key_number][0] is axis_states[0]:
145+
state = axis_states[0]
146+
kbd.press(*keymap[key_event.key_number][1])
147+
# ..and it's key 9, set state to x
148+
if keymap[key_event.key_number][0] is axis_states[1]:
149+
state = axis_states[1]
150+
pixels[key_to_pixel_map(10)] = OFF
151+
pixels[key_to_pixel_map(11)] = OFF
152+
# ..and it's key 10, set state to y
153+
if keymap[key_event.key_number][0] is axis_states[2]:
154+
state = axis_states[2]
155+
pixels[key_to_pixel_map(9)] = OFF
156+
pixels[key_to_pixel_map(11)] = OFF
157+
# ..and it's key 11, set state to z
158+
if keymap[key_event.key_number][0] is axis_states[3]:
159+
state = axis_states[3]
160+
pixels[key_to_pixel_map(9)] = OFF
161+
pixels[key_to_pixel_map(10)] = OFF
162+
# turn on neopixel for key with color from keymap
163+
pixels[key_to_pixel_map(key_event.key_number)] = keymap[key_event.key_number][2]
164+
# ..and it's released..
165+
if key_event.released:
166+
# if it's key 0-8, release the key press and turn off neopixel
167+
if keymap[key_event.key_number][0] is axis_states[0]:
168+
kbd.release(*keymap[key_event.key_number][1])
169+
pixels.fill(OFF)
170+
ble.start_advertising(advertisement)

0 commit comments

Comments
 (0)