Browse Source

more fonts. more instructions. added images and colors from cccamp23 style guide. text rendering now possible with colors. custom font spacing. images automatically scaled and cropped. fixed qr text and colors. allow exiting test gui with q or esc. better target check.

Thomas Buck 1 year ago
parent
commit
ba91afc6b4

+ 25
- 4
README.md View File

4
 
4
 
5
 ## Quick Start
5
 ## Quick Start
6
 
6
 
7
-Just run
7
+Just run:
8
 
8
 
9
     ./manager.py
9
     ./manager.py
10
 
10
 
12
 
12
 
13
 ## Dependencies
13
 ## Dependencies
14
 
14
 
15
-You always need
15
+You always need:
16
 
16
 
17
     pip install pil
17
     pip install pil
18
     pip install bdfparser
18
     pip install bdfparser
19
     pip install "qrcode[pil]"
19
     pip install "qrcode[pil]"
20
 
20
 
21
 The rest depends on the output device chosen.
21
 The rest depends on the output device chosen.
22
+For debugging on your host PC you can use the TestGUI interface with pygame:
23
+
24
+    pip install pygame
25
+
26
+The other currently supported option is using a Raspberry Pi with the [Adafruit RGB Matrix Bonnet](https://shop.pimoroni.com/products/adafruit-rgb-matrix-bonnet-for-raspberry-pi?variant=2257849155594) and a matching [LED Matrix](https://shop.pimoroni.com/products/rgb-led-matrix-panel?variant=35962488650).
27
+The [tutorial](https://learn.adafruit.com/adafruit-rgb-matrix-bonnet-for-raspberry-pi/driving-matrices) suggests using the [Adafruit Raspberry Pi Installer Script for the RGB matrix](https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/blob/339cccfbdd8b503b53186176ff96bead9a13a2f5/rgb-matrix.sh).
28
+This will give you the [hzeller/rpi-rgb-led-matrix](https://github.com/hzeller/rpi-rgb-led-matrix) project which includes the Python bindings used in this project.
29
+
30
+## Adding your own visualizations
31
+
32
+Take a look how others are implemented.
33
+You can chain the different screens together using `Manager` and also check for conditions, as seen in `CheckHTTP`.
34
+This should enable you to quickly create something usable.
35
+
36
+One goal is to run this project on public events.
37
+If this is the case, and you want your own message to appear, simply open up a PR or send an email with a patch.
38
+Because of different versions between host PCs and the Raspbian OS, things may look slightly different, especially regarding stuff like animated GIF viewing.
22
 
39
 
23
 ## Licensing
40
 ## Licensing
24
 
41
 
31
     think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
48
     think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
32
     ----------------------------------------------------------------------------
49
     ----------------------------------------------------------------------------
33
 
50
 
34
-The included font from [farsil/ibmfonts](https://github.com/farsil/ibmfonts) is licensed as `CC-BY-SA-4.0`.
51
+The included fonts from [farsil/ibmfonts](https://github.com/farsil/ibmfonts) are licensed as `CC-BY-SA-4.0`.
52
+
53
+The fonts from [cmvnd/fonts](https://github.com/cmvnd/fonts) are licensed as GPLv3.
54
+
55
+The tiny font is from [robey](https://robey.lag.net/2010/01/23/tiny-monospace-font.html) and licensed as CC0.
35
 
56
 
36
-The included GIFs are from [GifCities](https://gifcities.org/?q=32)
57
+The included GIFs are from [GifCities](https://gifcities.org/?q=32).

+ 18
- 4
camp_small.py View File

7
 # think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
7
 # think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
8
 # ----------------------------------------------------------------------------
8
 # ----------------------------------------------------------------------------
9
 
9
 
10
+camp_pink = (251, 72, 196)
11
+camp_green = (63, 255, 33)
12
+
10
 if __name__ == "__main__":
13
 if __name__ == "__main__":
11
     from splash import SplashScreen
14
     from splash import SplashScreen
12
     from draw import ScrollText
15
     from draw import ScrollText
30
     success = Manager(t)
33
     success = Manager(t)
31
     success.add(ImageScreen(t, "drinka.gif", 0.2, 2, 20.0))
34
     success.add(ImageScreen(t, "drinka.gif", 0.2, 2, 20.0))
32
     success.add(Solid(t, 1.0))
35
     success.add(Solid(t, 1.0))
33
-    success.add(QRScreen(t, url, 30.0, "Order:"))
36
+    success.add(QRScreen(t, url, 30.0, "Drinks:", "tom-thumb", (255, 255, 255), (0, 0, 0)))
34
     success.add(Solid(t, 1.0))
37
     success.add(Solid(t, 1.0))
35
 
38
 
36
     fail = Manager(t)
39
     fail = Manager(t)
37
     fail.add(ImageScreen(t, "attention.gif", 0.2, 2, 20.0, (0, 0, 0)))
40
     fail.add(ImageScreen(t, "attention.gif", 0.2, 2, 20.0, (0, 0, 0)))
38
     fail.add(ScrollText(t, "The UbaBot Cocktail machine is currently closed. Please come back later for more drinks!", "ib8x8u", 2))
41
     fail.add(ScrollText(t, "The UbaBot Cocktail machine is currently closed. Please come back later for more drinks!", "ib8x8u", 2))
39
-    fail.add(Solid(t, 2.0))
42
+    fail.add(Solid(t, 1.0))
40
     fail.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), None, 2.0))
43
     fail.add(GameOfLife(t, 20, (0, 255, 0), (0, 0, 0), None, 2.0))
41
-    fail.add(Solid(t, 2.0))
44
+    fail.add(Solid(t, 1.0))
42
 
45
 
43
     d = CheckHTTP(url)
46
     d = CheckHTTP(url)
44
     d.success(success)
47
     d.success(success)
45
     d.fail(fail)
48
     d.fail(fail)
46
 
49
 
47
-    t.debug_loop(d.draw)
50
+    m = Manager(t)
51
+    m.add(ScrollText(t, "#CCCAMP23", "lemon", 1, 75, camp_green))
52
+    m.add(Solid(t, 1.0))
53
+    m.add(ImageScreen(t, "Favicon.png", 0, 1, 10.0))
54
+    m.add(Solid(t, 1.0))
55
+    m.add(ScrollText(t, "#CCCAMP23", "lemon", 1, 75, camp_pink))
56
+    m.add(Solid(t, 1.0))
57
+    m.add(d)
58
+    m.add(Solid(t, 1.0))
59
+
60
+    m.restart()
61
+    t.debug_loop(m.draw)

+ 74
- 22
draw.py View File

1
 #!/usr/bin/env python3
1
 #!/usr/bin/env python3
2
 
2
 
3
+# Uses the Python BDF format bitmap font parser:
4
+# https://github.com/tomchen/bdfparser
5
+#
6
+# And the pillow Python Imaging Library:
7
+# https://github.com/python-pillow/Pillow
8
+#
3
 # ----------------------------------------------------------------------------
9
 # ----------------------------------------------------------------------------
4
 # "THE BEER-WARE LICENSE" (Revision 42):
10
 # "THE BEER-WARE LICENSE" (Revision 42):
5
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
11
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
13
 import time
19
 import time
14
 
20
 
15
 class DrawText:
21
 class DrawText:
16
-    def __init__(self, g):
22
+    def __init__(self, g, fg = (255, 255, 255), bg = (0, 0, 0), c = (0, 255, 0)):
17
         self.gui = g
23
         self.gui = g
24
+        self.fg = fg
25
+        self.bg = bg
26
+        self.color = c
18
 
27
 
19
         scriptDir = os.path.dirname(os.path.realpath(__file__))
28
         scriptDir = os.path.dirname(os.path.realpath(__file__))
20
         fontDir = os.path.join(scriptDir, "fonts")
29
         fontDir = os.path.join(scriptDir, "fonts")
25
             if not filename.lower().endswith(".bdf"):
34
             if not filename.lower().endswith(".bdf"):
26
                 continue
35
                 continue
27
 
36
 
28
-            font = Font(os.path.join(fontDir, filename))
29
-            #print(f"{filename} global size is "
30
-            #    f"{font.headers['fbbx']} x {font.headers['fbby']} (pixel), "
31
-            #    f"it contains {len(font)} glyphs.")
32
-
33
-            # TODO hard-coded per-font offsets
37
+            # TODO hard-coded per-font offsets and spacing adjustment
34
             offset = 0
38
             offset = 0
39
+            spacing = 0
35
             if filename == "iv18x16u.bdf":
40
             if filename == "iv18x16u.bdf":
36
                 offset = 6
41
                 offset = 6
37
             elif filename == "ib8x8u.bdf":
42
             elif filename == "ib8x8u.bdf":
38
                 offset = 10
43
                 offset = 10
44
+            elif filename == "lemon.bdf":
45
+                offset = 8
46
+                spacing = -3
47
+            elif filename == "antidote.bdf":
48
+                offset = 9
49
+                spacing = -1
50
+            elif filename == "uushi.bdf":
51
+                offset = 8
52
+                spacing = -2
53
+            elif filename == "tom-thumb.bdf":
54
+                offset = 12
55
+                spacing = 2
39
 
56
 
40
-            data = (font, offset, {})
57
+            font = Font(os.path.join(fontDir, filename))
58
+            data = (font, offset, {}, spacing)
41
             self.fonts[filename[:-4]] = data
59
             self.fonts[filename[:-4]] = data
42
 
60
 
43
     def getGlyph(self, c, font):
61
     def getGlyph(self, c, font):
44
-        f, o, cache = self.fonts[font]
62
+        if not isinstance(font, str):
63
+            # fall-back to first available font
64
+            f, offset, cache, spacing = next(iter(self.fonts))
65
+        else:
66
+            # users font choice
67
+            f, offset, cache, spacing = self.fonts[font]
45
 
68
 
46
         # only render glyphs once, cache resulting image data
69
         # only render glyphs once, cache resulting image data
47
         if not c in cache:
70
         if not c in cache:
51
             g = g.replace(1, 2).replace(0, 1).replace(2, 0)
74
             g = g.replace(1, 2).replace(0, 1).replace(2, 0)
52
 
75
 
53
             # render to pixel data
76
             # render to pixel data
77
+            bytesdict = {
78
+                0: int(self.fg[2] << 16 | self.fg[1] << 8 | self.fg[0]).to_bytes(4, byteorder = "little"),
79
+                1: int(self.bg[2] << 16 | self.bg[1] << 8 | self.bg[0]).to_bytes(4, byteorder = "little"),
80
+                2: int(self.color[2] << 16 | self.color[1] << 8 | self.color[0]).to_bytes(4, byteorder = "little"),
81
+            }
54
             img = Image.frombytes('RGBA',
82
             img = Image.frombytes('RGBA',
55
                                 (g.width(), g.height()),
83
                                 (g.width(), g.height()),
56
-                                g.tobytes('RGBA'))
57
-
84
+                                g.tobytes('RGBA', bytesdict))
58
             cache[c] = img
85
             cache[c] = img
59
 
86
 
60
-        return (cache[c], o)
87
+        return (cache[c], offset, spacing)
61
 
88
 
62
-    def drawGlyph(self, g, xOff, yOff):
89
+    def drawGlyph(self, g, xOff, yOff, spacing):
63
         if xOff >= self.gui.width:
90
         if xOff >= self.gui.width:
64
             return
91
             return
65
 
92
 
72
                 p = g.getpixel((x, y))
99
                 p = g.getpixel((x, y))
73
                 self.gui.set_pixel(xTarget, yOff + y, p)
100
                 self.gui.set_pixel(xTarget, yOff + y, p)
74
 
101
 
102
+        for x in range(0, spacing):
103
+            for y in range(0, g.height):
104
+                self.gui.set_pixel(xOff + x + g.width, yOff + y, self.bg)
105
+
75
     def text(self, s, f, offset = 0, earlyAbort = True, yOff = 0):
106
     def text(self, s, f, offset = 0, earlyAbort = True, yOff = 0):
76
         w = 0
107
         w = 0
77
         for c in s:
108
         for c in s:
80
                 if xOff >= self.gui.width:
111
                 if xOff >= self.gui.width:
81
                     break
112
                     break
82
 
113
 
83
-            g, y = self.getGlyph(c, f)
84
-            w += g.width
114
+            g, y, spacing = self.getGlyph(c, f)
115
+            w += g.width + spacing
85
 
116
 
86
-            if xOff >= -10: # some wiggle room so chars dont disappear
87
-                self.drawGlyph(g, xOff, y + yOff)
117
+            if xOff >= -16: # some wiggle room so chars dont disappear
118
+                self.drawGlyph(g, xOff, y + yOff, spacing)
88
         return w
119
         return w
89
 
120
 
90
 class ScrollText:
121
 class ScrollText:
91
-    def __init__(self, g, t, f, i = 1, s = 75):
122
+    def __init__(self, g, t, f, i = 1, s = 75, fg = (255, 255, 255), bg = (0, 0, 0)):
92
         self.gui = g
123
         self.gui = g
93
-        self.drawer = DrawText(self.gui)
124
+        self.drawer = DrawText(self.gui, fg, bg)
94
         self.text = t
125
         self.text = t
95
         self.font = f
126
         self.font = f
96
         self.iterations = i
127
         self.iterations = i
122
     import util
153
     import util
123
     t = util.getTarget()
154
     t = util.getTarget()
124
 
155
 
125
-    #d = ScrollText(t, "This is a long scrolling text. Is it too fast or maybe too slow?", "iv18x16u")
126
-    d = ScrollText(t, "This is a long scrolling text. Is it too fast or maybe too slow?", "ib8x8u")
127
-    t.debug_loop(d.draw)
156
+    from splash import SplashScreen
157
+    splash = SplashScreen(t)
158
+    t.loop_start()
159
+    splash.draw()
160
+    t.loop_end()
161
+
162
+    from manager import Manager
163
+    m = Manager(t)
164
+
165
+    m.add(ScrollText(t, "tom-thumb Abcdefgh tom-thumb", "tom-thumb",
166
+                     1, 75, (0, 255, 0), (0, 0, 255)))
167
+    m.add(ScrollText(t, "antidote Abcdefgh antidote", "antidote",
168
+                     1, 75, (0, 255, 0), (0, 0, 255)))
169
+    m.add(ScrollText(t, "uushi Abcdefgh uushi", "uushi",
170
+                     1, 75, (0, 255, 0), (0, 0, 255)))
171
+    m.add(ScrollText(t, "lemon Abcdefgh lemon", "lemon",
172
+                     1, 75, (0, 255, 0), (0, 0, 255)))
173
+    m.add(ScrollText(t, "ib8x8u Abcdefgh ib8x8u", "ib8x8u",
174
+                     1, 75, (0, 255, 0), (0, 0, 255)))
175
+    m.add(ScrollText(t, "iv18x16u Abcdefgh iv18x16u", "iv18x16u",
176
+                     1, 75, (0, 255, 0), (0, 0, 255)))
177
+
178
+    m.restart()
179
+    t.debug_loop(m.draw)

+ 2614
- 0
fonts/antidote.bdf
File diff suppressed because it is too large
View File


+ 37441
- 0
fonts/lemon.bdf
File diff suppressed because it is too large
View File


+ 2353
- 0
fonts/tom-thumb.bdf
File diff suppressed because it is too large
View File


+ 14695
- 0
fonts/uushi.bdf
File diff suppressed because it is too large
View File


+ 20
- 1
image.py View File

1
 #!/usr/bin/env python3
1
 #!/usr/bin/env python3
2
 
2
 
3
+# Uses the pillow Python Imaging Library:
4
+# https://github.com/python-pillow/Pillow
5
+#
3
 # ----------------------------------------------------------------------------
6
 # ----------------------------------------------------------------------------
4
 # "THE BEER-WARE LICENSE" (Revision 42):
7
 # "THE BEER-WARE LICENSE" (Revision 42):
5
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
8
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
12
 import os
15
 import os
13
 
16
 
14
 class ImageScreen:
17
 class ImageScreen:
15
-    def __init__(self, g, p, t = 0.2, i = 1, to = 20.0, bg = None):
18
+    def __init__(self, g, p, t = 0.2, i = 1, to = 10.0, bg = None):
16
         self.gui = g
19
         self.gui = g
17
         self.time = t
20
         self.time = t
18
         self.iterations = i
21
         self.iterations = i
22
         scriptDir = os.path.dirname(os.path.realpath(__file__))
25
         scriptDir = os.path.dirname(os.path.realpath(__file__))
23
         self.path = os.path.join(scriptDir, "images", p)
26
         self.path = os.path.join(scriptDir, "images", p)
24
         self.image = Image.open(self.path)
27
         self.image = Image.open(self.path)
28
+
29
+        # for some reason non-animated images don't even have this attribute
30
+        if not hasattr(self.image, "is_animated"):
31
+            self.image.is_animated = False
32
+            self.image.n_frames = 1
33
+
34
+        # automatically crop and scale large images
35
+        if not self.image.is_animated and ((self.image.width > self.gui.width) or (self.image.height > self.gui.height)):
36
+            self.image = self.image.crop(self.image.getbbox())
37
+            self.image = self.image.resize((self.gui.width, self.gui.height),
38
+                                           Image.Resampling.NEAREST)
39
+
40
+            # new image object is also missing these
41
+            self.image.is_animated = False
42
+            self.image.n_frames = 1
43
+
25
         print(p, self.image.width, self.image.height, self.image.is_animated, self.image.n_frames)
44
         print(p, self.image.width, self.image.height, self.image.is_animated, self.image.n_frames)
26
 
45
 
27
         self.xOff = int((self.gui.width - self.image.width) / 2)
46
         self.xOff = int((self.gui.width - self.image.width) / 2)

BIN
images/Favicon.png View File


BIN
images/Favicon_Accessability.png View File


BIN
images/Favicon_General.png View File


BIN
images/Favicon_Kitchens.png View File


BIN
images/Favicon_OffGrid.png View File


BIN
images/Favicon_Offtopic.png View File


BIN
images/Favicon_Trains.png View File


BIN
images/Favicon_Villages.png View File


+ 6
- 0
pi.py View File

1
 #!/usr/bin/env python3
1
 #!/usr/bin/env python3
2
 
2
 
3
+# Uses the Python bindings for the Raspberry Pi RGB LED Matrix library:
4
+# https://github.com/hzeller/rpi-rgb-led-matrix
5
+#
6
+# And the pillow Python Imaging Library:
7
+# https://github.com/python-pillow/Pillow
8
+#
3
 # ----------------------------------------------------------------------------
9
 # ----------------------------------------------------------------------------
4
 # "THE BEER-WARE LICENSE" (Revision 42):
10
 # "THE BEER-WARE LICENSE" (Revision 42):
5
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
11
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice

+ 23
- 10
qr.py View File

1
 #!/usr/bin/env python3
1
 #!/usr/bin/env python3
2
 
2
 
3
+# Uses the Python QR code image generator:
4
+# https://github.com/lincolnloop/python-qrcode
5
+#
3
 # ----------------------------------------------------------------------------
6
 # ----------------------------------------------------------------------------
4
 # "THE BEER-WARE LICENSE" (Revision 42):
7
 # "THE BEER-WARE LICENSE" (Revision 42):
5
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
8
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
13
 from draw import DrawText
16
 from draw import DrawText
14
 
17
 
15
 class QRScreen:
18
 class QRScreen:
16
-    def __init__(self, g, d, t = 10.0, h = None, c1 = (0, 0, 0), c2 = (255, 255, 255)):
19
+    def __init__(self, g, d, t = 10.0, h = None, f = None, c1 = (0, 0, 0), c2 = (255, 255, 255)):
17
         self.gui = g
20
         self.gui = g
18
         self.time = t
21
         self.time = t
19
         self.heading = h
22
         self.heading = h
23
+        self.font = f
20
         self.c1 = c1
24
         self.c1 = c1
21
         self.c2 = c2
25
         self.c2 = c2
22
 
26
 
29
 
33
 
30
         if util.isPi():
34
         if util.isPi():
31
             # work-around for weird bug in old qrcode lib?
35
             # work-around for weird bug in old qrcode lib?
32
-            self.image = qr.make_image(fill_color = "black", back_color = "white")
33
-            self.c1 = (0, 0, 0)
34
-            self.c2 = (255, 255, 255)
36
+            if (self.c1 == (0, 0, 0)) and (self.c2 == (255, 255, 255)):
37
+                self.image = qr.make_image(fill_color = "black", back_color = "white")
38
+                self.c1 = (0, 0, 0)
39
+                self.c2 = (255, 255, 255)
40
+            elif (self.c1 == (255, 255, 255)) and (self.c2 == (0, 0, 0)):
41
+                self.image = qr.make_image(fill_color = "white", back_color = "black")
42
+                self.c1 = (255, 255, 255)
43
+                self.c2 = (0, 0, 0)
44
+            else:
45
+                raise RuntimeError("QR colors other than black/white not supported on Pi")
35
         else:
46
         else:
36
             self.image = qr.make_image(fill_color = self.c1, back_color = self.c2)
47
             self.image = qr.make_image(fill_color = self.c1, back_color = self.c2)
37
 
48
 
38
         if self.heading != None:
49
         if self.heading != None:
39
-            self.text = DrawText(self.gui)
50
+            self.text = DrawText(self.gui, self.c1, self.c2)
51
+            self.yOff = self.gui.height - self.image.height
52
+        else:
53
+            self.yOff = int((self.gui.height - self.image.height) / 2)
40
 
54
 
41
         self.xOff = int((self.gui.width - self.image.width) / 2)
55
         self.xOff = int((self.gui.width - self.image.width) / 2)
42
-        self.yOff = int((self.gui.height - self.image.height) / 2)
43
 
56
 
44
         self.restart()
57
         self.restart()
45
 
58
 
63
                 for x in range(0, self.gui.width - self.image.width - self.xOff):
76
                 for x in range(0, self.gui.width - self.image.width - self.xOff):
64
                     self.gui.set_pixel(x + self.xOff + self.image.width, y + self.yOff, self.c2)
77
                     self.gui.set_pixel(x + self.xOff + self.image.width, y + self.yOff, self.c2)
65
 
78
 
79
+        if self.heading != None:
80
+            self.text.text(self.heading, self.font, 0, True, -10)
81
+
66
         for x in range(0, self.image.width):
82
         for x in range(0, self.image.width):
67
             for y in range(0, self.image.height):
83
             for y in range(0, self.image.height):
68
                 v = self.image.getpixel((x, y))
84
                 v = self.image.getpixel((x, y))
70
                     v = (v, v, v)
86
                     v = (v, v, v)
71
                 self.gui.set_pixel(x + self.xOff, y + self.yOff, v)
87
                 self.gui.set_pixel(x + self.xOff, y + self.yOff, v)
72
 
88
 
73
-        if self.heading != None:
74
-            self.text.text(self.heading, "ib8x8u", 0, True, -10)
75
-
76
 if __name__ == "__main__":
89
 if __name__ == "__main__":
77
     import util
90
     import util
78
     t = util.getTarget()
91
     t = util.getTarget()
79
 
92
 
80
-    d = QRScreen(t, "Hello World", 10.0, "Test")
93
+    d = QRScreen(t, "Hello World", 10.0, "Drinks:", "tom-thumb", (255, 255, 255), (0, 0, 0))
81
     t.debug_loop(d.draw)
94
     t.debug_loop(d.draw)

+ 6
- 0
test.py View File

1
 #!/usr/bin/env python3
1
 #!/usr/bin/env python3
2
 
2
 
3
+# Uses the pygame SDL wrapper:
4
+# https://github.com/pygame/pygame
5
+#
3
 # ----------------------------------------------------------------------------
6
 # ----------------------------------------------------------------------------
4
 # "THE BEER-WARE LICENSE" (Revision 42):
7
 # "THE BEER-WARE LICENSE" (Revision 42):
5
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
8
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
27
         for event in pygame.event.get():
30
         for event in pygame.event.get():
28
             if event.type == pygame.QUIT:
31
             if event.type == pygame.QUIT:
29
                 return True
32
                 return True
33
+            elif event.type == pygame.KEYUP:
34
+                if (event.key == pygame.K_q) or (event.key == pygame.K_ESCAPE):
35
+                    return True
30
 
36
 
31
         self.screen.fill("black")
37
         self.screen.fill("black")
32
         return False
38
         return False

+ 26
- 8
util.py View File

7
 # think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
7
 # think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
8
 # ----------------------------------------------------------------------------
8
 # ----------------------------------------------------------------------------
9
 
9
 
10
-import platform
10
+targetIsPi = None
11
 
11
 
12
 def isPi():
12
 def isPi():
13
-    return platform.machine() == "armv7l"
13
+    global targetIsPi
14
+
15
+    if targetIsPi == None:
16
+        getTarget()
17
+    return targetIsPi
14
 
18
 
15
 def getTarget():
19
 def getTarget():
16
-    t = None
17
-    if isPi():
20
+    global targetIsPi
21
+
22
+    target = None
23
+    try:
18
         from pi import PiMatrix
24
         from pi import PiMatrix
19
-        t = PiMatrix()
20
-    else:
25
+        target = PiMatrix()
26
+
27
+        if targetIsPi == None:
28
+            # only print once
29
+            print("Raspberry Pi Adafruit RGB LED Matrix detected")
30
+
31
+        targetIsPi = True
32
+    except ModuleNotFoundError:
21
         from test import TestGUI
33
         from test import TestGUI
22
-        t = TestGUI()
23
-    return t
34
+        target = TestGUI()
35
+
36
+        if targetIsPi == None:
37
+            # only print once
38
+            print("Falling back to GUI debug interface")
39
+
40
+        targetIsPi = False
41
+    return target

Loading…
Cancel
Save