Skip to content

Commit 5f676e6

Browse files
committed
1st version tft spirit board project
1 parent 77ce50c commit 5f676e6

File tree

7 files changed

+491
-0
lines changed

7 files changed

+491
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# SPDX-FileCopyrightText: 2024 Tim Cocks
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
SpiritBoard code.py
6+
Feather ESP32-S3 or S2 + TFT Featherwing 3.5" 480x320 pixels
7+
8+
Receive and display messages from the spirits.
9+
"""
10+
import os
11+
import displayio
12+
import board
13+
from digitalio import DigitalInOut
14+
import adafruit_connection_manager
15+
import wifi
16+
import adafruit_requests
17+
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
18+
from adafruit_hx8357 import HX8357 # TFT Featherwing 3.5" 480x320 display driver
19+
from spirit_board import SpiritBoard
20+
import adafruit_tsc2007
21+
22+
23+
# 3.5" TFT Featherwing is 480x320
24+
displayio.release_displays()
25+
DISPLAY_WIDTH = 480
26+
DISPLAY_HEIGHT = 320
27+
28+
# Initialize TFT Display
29+
spi = board.SPI()
30+
tft_cs = board.D9
31+
tft_dc = board.D10
32+
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs)
33+
display = HX8357(display_bus, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT)
34+
display.rotation = 0
35+
_touch_flip = (False, True)
36+
37+
# Initialize 3.5" TFT Featherwing Touchscreen
38+
ts_cs_pin = DigitalInOut(board.D6)
39+
i2c = board.I2C()
40+
irq_dio = None
41+
tsc = adafruit_tsc2007.TSC2007(i2c, irq=irq_dio)
42+
43+
# Initialize a requests session
44+
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
45+
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
46+
requests = adafruit_requests.Session(pool, ssl_context)
47+
48+
# Set your Adafruit IO Username and Key in secrets.py
49+
# (visit io.adafruit.com if you need to create an account,
50+
# or if you need your Adafruit IO key.)
51+
aio_username = os.getenv("AIO_USERNAME")
52+
aio_key = os.getenv("AIO_KEY")
53+
54+
# Initialize an Adafruit IO HTTP API object
55+
io = IO_HTTP(aio_username, aio_key, requests)
56+
57+
# initialize the SpiritBoard class
58+
spirit_board = SpiritBoard(display)
59+
60+
# get messages from io or the local file
61+
messages = spirit_board.get_messages(io)
62+
63+
# The planchette is already at the home position.
64+
# Slide it to home again to make it jump, in order
65+
# indicate the message is ready to be received.
66+
spirit_board.slide_planchette(SpiritBoard.LOCATIONS["home"],
67+
delay=0.02, step_size=6)
68+
69+
# current message index
70+
message_index = 0
71+
while True:
72+
# if the display was touched
73+
if tsc.touched:
74+
# write the message at the current index
75+
spirit_board.write_message(messages[message_index], step_size=8)
76+
77+
# if there are more messages in the list inside of context
78+
if message_index < len(messages) - 1:
79+
# increment the message index
80+
message_index += 1
81+
82+
else: # there are no more messages in the list
83+
# reset the index to 0
84+
message_index = 0
85+
print("fetching next")
86+
87+
# fetch new messages
88+
messages = spirit_board.get_messages(io)
89+
90+
# make the planchette jump to indicate messages are ready to display
91+
spirit_board.slide_planchette(SpiritBoard.LOCATIONS["home"],
92+
delay=0.02, step_size=6)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../shared/lib/
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../shared/spirit_board.py
Binary file not shown.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
try:
2+
from typing import Tuple
3+
except ImportError:
4+
pass
5+
6+
from displayio import TileGrid
7+
8+
9+
class AnchoredTileGrid(TileGrid):
10+
def __init__(self, bitmap, **kwargs):
11+
super().__init__(bitmap, **kwargs)
12+
self._anchor_point = (0, 0)
13+
14+
self._anchored_position = (
15+
0 if "x" not in kwargs else kwargs["x"],
16+
0 if "y" not in kwargs else kwargs["y"]
17+
)
18+
19+
@property
20+
def anchor_point(self):
21+
return self._anchor_point
22+
23+
@anchor_point.setter
24+
def anchor_point(self, new_anchor_point: Tuple[float, float]) -> None:
25+
self._anchor_point = new_anchor_point
26+
# update the anchored_position using setter
27+
self.anchored_position = self._anchored_position
28+
29+
@property
30+
def anchored_position(self) -> Tuple[int, int]:
31+
"""Position relative to the anchor_point. Tuple containing x,y
32+
pixel coordinates."""
33+
return self._anchored_position
34+
35+
@anchored_position.setter
36+
def anchored_position(self, new_position: Tuple[int, int]) -> None:
37+
self._anchored_position = new_position
38+
# Calculate (x,y) position
39+
if (self._anchor_point is not None) and (self._anchored_position is not None):
40+
new_x = int(new_position[0]
41+
- round(self._anchor_point[0] * (self.tile_width * self.width)))
42+
43+
self.x = int(
44+
new_position[0]
45+
- round(self._anchor_point[0] * (self.tile_width * self.width))
46+
)
47+
48+
self.y = int(
49+
new_position[1]
50+
- round(self._anchor_point[1] * (self.tile_height * self.height))
51+
)

0 commit comments

Comments
 (0)