adding touch deck code

This commit is contained in:
foamyguy 2021-03-21 20:33:54 -05:00
parent f469cc9fd4
commit 767d1b4400
63 changed files with 490 additions and 0 deletions

View file

@ -0,0 +1,305 @@
# SPDX-FileCopyrightText: 2020 Tim C, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
"""
This version runs on Feather RP2040 with a 3.5" FeatherWing
"""
import time
import displayio
import terminalio
from adafruit_display_text import label, bitmap_label
from adafruit_displayio_layout.layouts.grid_layout import GridLayout
from touch_deck_layers import touch_deck_config, KEY, STRING, MEDIA, KEY_PRESS, KEY_RELEASE
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_displayio_layout.widgets.icon_widget import IconWidget
from adafruit_featherwing import tft_featherwing_35
# seems to help the touchscreen not get stuck with chip not found
time.sleep(3)
# display and touchscreen initialization
displayio.release_displays()
tft_featherwing = tft_featherwing_35.TFTFeatherWing35()
display = tft_featherwing.display
touchscreen = tft_featherwing.touchscreen
# HID setup
kbd = Keyboard(usb_hid.devices)
cc = ConsumerControl(usb_hid.devices)
kbd_layout = KeyboardLayoutUS(kbd)
# variables to envorce timout between icon presses
COOLDOWN_TIME = 0.5
LAST_PRESS_TIME = -1
# 'mock' icon indexes for the layer buttons
# used for debouncing
PREV_LAYER_INDEX = -1
NEXT_LAYER_INDEX = -2
HOME_LAYER_INDEX = -3
# start on first layer
current_layer = 0
# Make the main_group to hold everything
main_group = displayio.Group(max_size=10)
display.show(main_group)
# loading screen
loading_group = displayio.Group()
# black background, screen size minus side buttons
loading_background = displayio.Bitmap((display.width-40)//20, display.height//20, 1)
loading_palette = displayio.Palette(1)
loading_palette[0] = 0x0
# scaled group to match screen size minus side buttons
loading_background_scale_group = displayio.Group(scale=20)
loading_background_tilegrid = displayio.TileGrid(loading_background, pixel_shader=loading_palette)
loading_background_scale_group.append(loading_background_tilegrid)
# loading screen label
loading_label = bitmap_label.Label(terminalio.FONT, text="Loading...", scale=3)
loading_label.anchor_point = (0.5, 0.5)
loading_label.anchored_position = (display.width // 2, display.height // 2)
# append background and label to the group
loading_group.append(loading_background_scale_group)
loading_group.append(loading_label)
# GridLayout to hold the icons
# size and location can be adjusted to fit
# different sized screens.
layout = GridLayout(
x=20,
y=20,
width=420,
height=290,
grid_size=(4, 3),
cell_padding=6,
max_size=20,
)
# list that holds the IconWidget objects for each icon.
_icons = []
# list that holds indexes of currently pressed icons and layer buttons
# used for debouncing
_pressed_icons = []
# layer label at the top of the screen
layer_label = bitmap_label.Label(terminalio.FONT)
layer_label.anchor_point = (0.5, 0.0)
layer_label.anchored_position = (display.width // 2, 4)
main_group.append(layer_label)
# right side layer buttons
next_layer_btn = IconWidget(
"",
"touch_deck_icons/layer_next.bmp",
on_disk=True
)
next_layer_btn.x = display.width - 40
next_layer_btn.y = display.height - 100
next_layer_btn.resize = (40, 100)
main_group.append(next_layer_btn)
prev_layer_btn = IconWidget(
"",
"touch_deck_icons/layer_prev.bmp",
on_disk=True
)
prev_layer_btn.x = display.width - 40
prev_layer_btn.y = 110
prev_layer_btn.resize = (40, 100)
main_group.append(prev_layer_btn)
home_layer_btn = IconWidget(
"",
"touch_deck_icons/layer_home.bmp",
on_disk=True
)
home_layer_btn.x = display.width - 40
home_layer_btn.y = 0
home_layer_btn.resize = (40, 100)
main_group.append(home_layer_btn)
# helper method to laod icons for an index by its index in the
# list of layers
def load_layer(layer_index):
# show the loading screen
main_group.append(loading_group)
time.sleep(0.05)
# resets icon lists to empty
global _icons
_icons = []
layout._cell_content_list = []
# remove previous layer icons from the layout
while len(layout) > 0:
layout.pop()
# set the layer labed at the top of the screen
layer_label.text = touch_deck_config["layers"][layer_index]["name"]
# loop over each shortcut and it's index
for i, shortcut in enumerate(touch_deck_config["layers"][layer_index]["shortcuts"]):
# create an icon for the current shortcut
_new_icon = IconWidget(shortcut["label"], shortcut["icon"], on_disk=True)
# add it to the list of icons
_icons.append(_new_icon)
# add it to the grid layout
# calculate it's position from the index
layout.add_content(_new_icon, grid_position=(i % 4, i // 4), cell_size=(1, 1))
# hide the loading screen
time.sleep(0.05)
main_group.pop()
# append the grid layout to the main_group
# so it gets shown on the display
main_group.append(layout)
# load the first layer to start
load_layer(current_layer)
# main loop
while True:
if touchscreen.touched:
# loop over all data in touchscreen buffer
while not touchscreen.buffer_empty:
touches = touchscreen.touches
# loop over all points touched
for point in touches:
if point:
# current time, used for timeout between icon presses
_now = time.monotonic()
# if the timeout has passed
if _now - LAST_PRESS_TIME > COOLDOWN_TIME:
# print(point)
# map the observed minimum and maximum touch values
# to the screen size
y = point["y"] - 250
x = 4096 - point["x"] - 250
y = y * display.width // (3820 - 250)
x = x * display.height // (3820 - 250)
# touch data is 90 degrees rotated
# flip x, and y here to account for that
p = (y, x)
# print(p)
# Next layer button pressed
if next_layer_btn.contains(p) and NEXT_LAYER_INDEX not in _pressed_icons:
# increment layer
current_layer += 1
# wrap back to beginning from end
if current_layer >= len(touch_deck_config["layers"]):
current_layer = 0
# load the new layer
load_layer(current_layer)
# save current time to check for timeout
LAST_PRESS_TIME = _now
# append this index to pressed icons for debouncing
_pressed_icons.append(NEXT_LAYER_INDEX)
# home layer button pressed
if home_layer_btn.contains(p) and HOME_LAYER_INDEX not in _pressed_icons:
# 0 index is home layer
current_layer = 0
# load the home layer
load_layer(current_layer)
# save current time to check for timeout
LAST_PRESS_TIME = _now
# append this index to pressed icons for debouncing
_pressed_icons.append(HOME_LAYER_INDEX)
# Previous layer button pressed
if prev_layer_btn.contains(p) and PREV_LAYER_INDEX not in _pressed_icons:
# decrement layer
current_layer -= 1
# wrap back to end from beginning
if current_layer < 0:
current_layer = len(touch_deck_config["layers"]) - 1
# load the new layer
load_layer(current_layer)
# save current time to check for timeout
LAST_PRESS_TIME = _now
# append this index to pressed icons for debouncing
_pressed_icons.append(PREV_LAYER_INDEX)
# loop over current layer icons and their indexes
for index, icon_shortcut in enumerate(_icons):
# if this icon was pressed
if icon_shortcut.contains(p):
# debounce logic, check that it wasn't already pressed
if index not in _pressed_icons:
# print("pressed {}".format(index))
# get actions for this icon from config object
_cur_actions = touch_deck_config["layers"][current_layer]["shortcuts"][index][
"actions"]
# tuple means it's a single action
if isinstance(_cur_actions, tuple):
# put it in a list by itself
_cur_actions = [_cur_actions]
# loop over the actions
for _action in _cur_actions:
# HID keyboard keys
if _action[0] == KEY:
kbd.press(*_action[1])
kbd.release(*_action[1])
# String to write from layout
elif _action[0] == STRING:
kbd_layout.write(_action[1])
# Consumer control code
elif _action[0] == MEDIA:
cc.send(_action[1])
# Key press
elif _action[0] == KEY_PRESS:
kbd.press(*_action[1])
# Key release
elif _action[0] == KEY_RELEASE:
kbd.release(*_action[1])
# if there are multiple actions
if len(_cur_actions) > 1:
# small sleep to make sure
# OS can respond to previous action
time.sleep(0.2)
# save current time to check for timeout
LAST_PRESS_TIME = _now
# append this index to pressed icons for debouncing
_pressed_icons.append(index)
else: # screen not touched
# empty the pressed icons list
_pressed_icons.clear()

View file

@ -0,0 +1,2 @@
This is the source code for Touch Deck Guide Project:
https://learn.adafruit.com/touch-deck-lcd-control-pad/

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -0,0 +1,183 @@
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control_code import ConsumerControlCode
MEDIA = 1
KEY = 2
STRING = 3
KEY_PRESS = 4
KEY_RELEASE = 5
touch_deck_config = {
"layers":[
{
"name": "Youtube Controls",
"shortcuts": [
{
"label": "Play",
"icon": "touch_deck_icons/pr_play.bmp",
"actions": (KEY, [Keycode.K])
},
{
"label": "Pause",
"icon": "touch_deck_icons/pr_pause.bmp",
"actions": (KEY, [Keycode.K])
},
{
"label": "Rewind",
"icon": "touch_deck_icons/pr_rewind.bmp",
"actions": (KEY, [Keycode.LEFT_ARROW])
},
{
"label": "FastForward",
"icon": "touch_deck_icons/pr_ffwd.bmp",
"actions": (KEY, [Keycode.RIGHT_ARROW])
},
{
"label": "Previous",
"icon": "touch_deck_icons/pr_previous.bmp",
"actions": (KEY, [Keycode.RIGHT_SHIFT, Keycode.P])
},
{
"label": "Next",
"icon": "touch_deck_icons/pr_next.bmp",
"actions": (KEY, [Keycode.RIGHT_SHIFT, Keycode.N])
},
{
"label": "Vol -",
"icon": "touch_deck_icons/pr_voldown.bmp",
"actions": (MEDIA, ConsumerControlCode.VOLUME_DECREMENT)
},
{
"label": "Vol +",
"icon": "touch_deck_icons/pr_volup.bmp",
"actions": (MEDIA, ConsumerControlCode.VOLUME_INCREMENT)
},
{
"label": "Fullscreen",
"icon": "touch_deck_icons/pr_fullscreen.bmp",
"actions": (KEY, [Keycode.F])
},
{
"label": "Slow",
"icon": "touch_deck_icons/pr_slow.bmp",
"actions": (KEY, [Keycode.RIGHT_SHIFT, Keycode.COMMA])
},
{
"label": "Fast",
"icon": "touch_deck_icons/pr_fast.bmp",
"actions": (KEY, [Keycode.RIGHT_SHIFT, Keycode.PERIOD])
},
{
"label": "Mute",
"icon": "touch_deck_icons/pr_mute.bmp",
"actions": (KEY, [Keycode.M])
}
]
},
{
"name": "Discord",
"shortcuts": [
{
"label": "Blinka",
"icon": "touch_deck_icons/af_blinka.bmp",
"actions": (STRING, ":blinka:")
},
{
"label": "Adabot",
"icon": "touch_deck_icons/af_adabot.bmp",
"actions": (STRING, ":adabot:")
},
{
"label": "Billie",
"icon": "touch_deck_icons/af_billie.bmp",
"actions": (STRING, ":billie:")
},
{
"label": "Cappy",
"icon": "touch_deck_icons/af_cappy.bmp",
"actions": (STRING, ":cappy:")
},
{
"label": "Connie",
"icon": "touch_deck_icons/af_connie.bmp",
"actions": (STRING, ":connie:")
},
{
"label": "Gus",
"icon": "touch_deck_icons/af_gus.bmp",
"actions": (STRING, ":gus:")
},
{
"label": "Hans",
"icon": "touch_deck_icons/af_hans.bmp",
"actions": (STRING, ":hans:")
},
{
"label": "Mho",
"icon": "touch_deck_icons/af_mho.bmp",
"actions": (STRING, ":mho:")
},
{
"label": "Minerva",
"icon": "touch_deck_icons/af_minerva.bmp",
"actions": (STRING, ":minerva:")
},
{
"label": "NeoTrellis",
"icon": "touch_deck_icons/af_neotrellis.bmp",
"actions": (STRING, ":neotrellis:")
},
{
"label": "Ruby",
"icon": "touch_deck_icons/af_ruby.bmp",
"actions": (STRING, ":ruby:")
},
{
"label": "Sparky",
"icon": "touch_deck_icons/af_sparky.bmp",
"actions": (STRING, ":sparky:")
}
]
},
{
"name": "Test Third Layer",
"shortcuts": [
{
"label": "Flameshot",
"icon": "touch_deck_icons/test48_icon.bmp",
# \n can be used in the string for enter key
"actions": [(KEY, [Keycode.GUI]), (STRING, "flameshot\n")]
},
{
"label": "Calculator",
"icon": "touch_deck_icons/test48_icon.bmp",
"actions": [(KEY, [Keycode.GUI, Keycode.SPACE]), (STRING, "Calculator")]
},
{
"label": "Test (D)",
"icon": "touch_deck_icons/test48_icon.bmp",
"actions": [(KEY, [Keycode.CONTROL, Keycode.SHIFT, Keycode.U]), (STRING, "221e\n")]
},
{
"label": "Test (L)",
"icon": "touch_deck_icons/test48_icon.bmp",
"actions": [
(KEY_PRESS, [Keycode.SHIFT]),
(KEY, [Keycode.B]),
(KEY, [Keycode.L]),
(KEY, [Keycode.I]),
(KEY, [Keycode.N]),
(KEY, [Keycode.K]),
(KEY, [Keycode.A]),
(KEY_RELEASE, [Keycode.SHIFT])
]
},
{
"label": "Test [:)]",
"icon": "touch_deck_icons/test48_icon.bmp",
"actions": (KEY, [Keycode.RIGHT_SHIFT, Keycode.SEMICOLON, Keycode.ZERO])
}
]
}
]
}