Skip to content

Commit b3501ce

Browse files
committed
WIP - cleaned up for PR.
1 parent 7c1b65a commit b3501ce

File tree

6 files changed

+146
-47
lines changed

6 files changed

+146
-47
lines changed

README.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ Installing from PyPI
3131
.. note:: This library is not available on PyPI yet. Install documentation is included
3232
as a standard element. Stay tuned for PyPI availability!
3333

34-
.. todo:: Remove the above note if PyPI version is/will be available at time of release.
35-
If the library is not planned for PyPI, remove the entire 'Installing from PyPI' section.
36-
3734
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
3835
PyPI <https://pypi.org/project/adafruit-circuitpython-pybadger/>`_. To install for current user:
3936

@@ -59,7 +56,22 @@ To install in a virtual environment in your current project:
5956
Usage Example
6057
=============
6158

62-
.. todo:: Add a quick, simple example. It and other examples should live in the examples folder and be included in docs/examples.rst.
59+
from adafruit_pybadger import PyBadger
60+
61+
pybadger = PyBadger()
62+
63+
while True:
64+
pybadger.badge(hello_scale=2, my_name_is_scale=2, name_scale=3)
65+
pybadger.auto_dim_display()
66+
67+
if pybadger.button.a:
68+
pybadger.business_card(image_name="Blinka.bmp")
69+
elif pybadger.button.b:
70+
print("b B")
71+
elif pybadger.button.start:
72+
print("b start")
73+
elif pybadger.button.select:
74+
pybadger.qr_code()
6375

6476
Contributing
6577
============

adafruit_pybadger.py

Lines changed: 111 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,36 +33,33 @@
3333
3434
**Hardware:**
3535
36-
.. todo:: Add links to any specific hardware product page(s), or category page(s). Use unordered list & hyperlink rST
37-
inline format: "* `Link Text <url>`_"
36+
* `Adafruit PyBadge <https://www.adafruit.com/product/4200>`_
37+
* `Adafruit PyBadge LC <https://www.adafruit.com/product/3939>`_
38+
* `Adafruit PyGamer <https://www.adafruit.com/product/4277>`_
3839
3940
**Software and Dependencies:**
4041
4142
* Adafruit CircuitPython firmware for the supported boards:
4243
https://github.com/adafruit/circuitpython/releases
4344
44-
.. todo:: Uncomment or remove the Bus Device and/or the Register library dependencies based on the library's use of either.
45-
46-
# * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
47-
# * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
4845
"""
4946

50-
import board
5147
import time
52-
import adafruit_lis3dh
5348
import array
49+
import math
50+
from collections import namedtuple
51+
import board
52+
import adafruit_lis3dh
5453
import audioio
5554
import displayio
5655
import digitalio
5756
from gamepadshift import GamePadShift
5857
from micropython import const
59-
import math
6058
import neopixel
6159
import analogio
6260
from adafruit_display_shapes.rect import Rect
6361
from adafruit_display_text.label import Label
6462
import terminalio
65-
from collections import namedtuple
6663
import adafruit_miniqr
6764

6865
__version__ = "0.0.0-auto.0"
@@ -71,7 +68,9 @@
7168
Buttons = namedtuple("Buttons", "b a start select right down up left")
7269

7370

71+
# pylint: disable=too-many-instance-attributes
7472
class PyBadger:
73+
"""PyBadger class."""
7574
# Button Constants
7675
BUTTON_LEFT = const(128)
7776
BUTTON_UP = const(64)
@@ -106,7 +105,7 @@ def __init__(self, i2c=None):
106105
self._pygamer_joystick_y = analogio.AnalogIn(board.JOYSTICK_Y)
107106

108107
# NeoPixels
109-
# Todo: Tie pixelcount to automatically figuring out which board is being used
108+
# Count is hardcoded - should be based on board ID, currently no board info for PyBadge LC
110109
neopixel_count = 5
111110
self._neopixels = neopixel.NeoPixel(board.NEOPIXEL, neopixel_count,
112111
pixel_order=neopixel.GRB)
@@ -122,7 +121,8 @@ def __init__(self, i2c=None):
122121
self._sine_wave = None
123122
self._sine_wave_sample = None
124123

125-
def check_for_movement(self, movement_threshold=1.5):
124+
def _check_for_movement(self, movement_threshold=10):
125+
"""Checks to see if board is moving. Used to auto-dim display when not moving."""
126126
current_accelerometer = self.acceleration
127127
if self._last_accelerometer is None:
128128
self._last_accelerometer = current_accelerometer
@@ -132,8 +132,15 @@ def check_for_movement(self, movement_threshold=1.5):
132132
self._last_accelerometer = current_accelerometer
133133
return acceleration_delta > movement_threshold
134134

135-
def auto_dim_display(self, delay=5.0):
136-
if not self.check_for_movement():
135+
def auto_dim_display(self, delay=5.0, movement_threshold=10):
136+
"""Auto-dim the display when board is not moving.
137+
138+
:param int delay: Time in seconds before display auto-dims after movement has ceased.
139+
:param int movement_threshold: Threshold required for movement to be considered stopped.
140+
Change to increase or decrease sensitivity.
141+
142+
"""
143+
if not self._check_for_movement(movement_threshold=movement_threshold):
137144
current_time = time.monotonic()
138145
if current_time - self._start_time > delay:
139146
self.display.brightness = 0.1
@@ -143,44 +150,105 @@ def auto_dim_display(self, delay=5.0):
143150

144151
@property
145152
def pixels(self):
153+
"""Sequence like object representing the NeoPixels on the board."""
146154
return self._neopixels
147155

148156
@property
149157
def joystick(self):
158+
"""The joystick on the PyGamer."""
150159
if hasattr(board, "JOYSTICK_X"):
151160
x = self._pygamer_joystick_x.value
152161
y = self._pygamer_joystick_y.value
153162
return x, y
154-
else:
155-
raise RuntimeError("This board does not have a built in joystick.")
163+
raise RuntimeError("This board does not have a built in joystick.")
156164

157165
@property
158166
def button(self):
167+
"""The buttons on the board.
168+
169+
Example use:
170+
171+
.. code-block:: python
172+
173+
from adafruit_pybadger import PyBadger
174+
175+
pybadger = PyBadger()
176+
177+
while True:
178+
if pybadger.button.a:
179+
print("Button A")
180+
elif pybadger.button.b:
181+
print("Button B")
182+
elif pybadger.button.start:
183+
print("Button start")
184+
elif pybadger.button.select:
185+
print("Button select")
186+
187+
"""
159188
button_values = self._buttons.get_pressed()
160189
return Buttons(*[button_values & button for button in
161-
(BUTTON_B, BUTTON_A, BUTTON_START, BUTTON_SELECT, BUTTON_RIGHT,
162-
BUTTON_DOWN, BUTTON_UP, BUTTON_LEFT)])
190+
(PyBadger.BUTTON_B, PyBadger.BUTTON_A, PyBadger.BUTTON_START,
191+
PyBadger.BUTTON_SELECT, PyBadger.BUTTON_RIGHT,
192+
PyBadger.BUTTON_DOWN, PyBadger.BUTTON_UP, PyBadger.BUTTON_LEFT)])
163193

164194
@property
165195
def light(self):
196+
"""Light sensor data."""
166197
return self._light_sensor.value
167198

168199
@property
169200
def acceleration(self):
201+
"""Accelerometer data."""
170202
return self._accelerometer.acceleration
171203

172204
@property
173205
def brightness(self):
206+
"""Display brightness."""
174207
return self.display.brightness
175208

176209
@brightness.setter
177210
def brightness(self, value):
178211
self.display.brightness = value
179212

213+
def business_card(self, image_name=None, dwell=20):
214+
"""Display a bitmap image and a text string, such as a personal image and email address.
215+
CURRENTLY ONLY DISPLAYS BITMAP IMAGE. Text string to be added.
216+
217+
:param str image_name: The name of the bitmap image including .bmp, e.g. ``"Blinka.bmp"``.
218+
:param int dwell: The amount of time in seconds to display the business card.
219+
220+
"""
221+
business_card_splash = displayio.Group(max_size=30)
222+
self.display.show(business_card_splash)
223+
with open(image_name, "rb") as file_name:
224+
on_disk_bitmap = displayio.OnDiskBitmap(file_name)
225+
face_image = displayio.TileGrid(on_disk_bitmap, pixel_shader=displayio.ColorConverter())
226+
business_card_splash.append(face_image)
227+
# Wait for the image to load.
228+
self.display.wait_for_frame()
229+
time.sleep(dwell)
230+
231+
# pylint: disable=too-many-locals
180232
def badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF,
181233
background_text_color=0xFFFFFF, foreground_text_color=0x000000, hello_scale=1,
182234
hello_string="HELLO", my_name_is_scale=1, my_name_is_string="MY NAME IS",
183235
name_scale=1, name_string="Blinka"):
236+
"""Create a "Hello My Name is"-style badge.
237+
238+
:param background_color: The color of the background. Defaults to 0xFF0000.
239+
:param foreground_color: The color of the foreground rectangle. Defaults to 0xFFFFFF.
240+
:param background_text_color: The color of the "HELLO MY NAME IS" text. Defaults to
241+
0xFFFFFF.
242+
:param foreground_text_color: The color of the name text. Defaults to 0x000000.
243+
:param hello_scale: The size scale of the "HELLO" string. Defaults to 1.
244+
:param hello_string: The first string of the badge. Defaults to "HELLO".
245+
:param my_name_is_scale: The size scale of the "MY NAME IS" string. Defaults to 1.
246+
:param my_name_is_string: The second string of the badge. Defaults to "MY NAME IS".
247+
:param name_scale: The size scale of the name string. Defaults to 1.
248+
:param name_string: The third string of the badge - change to be your name. Defaults to
249+
"Blinka".
250+
251+
"""
184252
# Make the Display Background
185253
splash = displayio.Group(max_size=20)
186254

@@ -203,29 +271,29 @@ def badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF,
203271
hello_group = displayio.Group(scale=hello_scale)
204272
# Setup and Center the Hello Label
205273
hello_label = Label(terminalio.FONT, text=hello_string)
206-
(x, y, w, h) = hello_label.bounding_box
207-
hello_label.x = ((self.display.width // (2 * hello_scale)) - w // 2)
208-
hello_label.y = int(h // (1.2 * hello_scale))
274+
(_, _, width, height) = hello_label.bounding_box
275+
hello_label.x = ((self.display.width // (2 * hello_scale)) - width // 2)
276+
hello_label.y = int(height // (1.2 * hello_scale))
209277
hello_label.color = background_text_color
210278
hello_group.append(hello_label)
211279

212280
my_name_is_scale = my_name_is_scale
213281
my_name_is_group = displayio.Group(scale=my_name_is_scale)
214282
# Setup and Center the "My Name Is" Label
215283
my_name_is_label = Label(terminalio.FONT, text=my_name_is_string)
216-
(x, y, w, h) = my_name_is_label.bounding_box
217-
my_name_is_label.x = ((self.display.width // (2 * my_name_is_scale)) - w // 2)
218-
my_name_is_label.y = int(h // (0.42 * my_name_is_scale))
284+
(_, _, width, height) = my_name_is_label.bounding_box
285+
my_name_is_label.x = ((self.display.width // (2 * my_name_is_scale)) - width // 2)
286+
my_name_is_label.y = int(height // (0.42 * my_name_is_scale))
219287
my_name_is_label.color = background_text_color
220288
my_name_is_group.append(my_name_is_label)
221289

222290
name_scale = name_scale
223291
name_group = displayio.Group(scale=name_scale)
224292
# Setup and Center the Name Label
225293
name_label = Label(terminalio.FONT, text=name_string)
226-
(x, y, w, h) = name_label.bounding_box
227-
name_label.x = ((self.display.width // (2 * name_scale)) - w // 2)
228-
name_label.y = int(h // (0.17 * name_scale))
294+
(_, _, width, height) = name_label.bounding_box
295+
name_label.x = ((self.display.width // (2 * name_scale)) - width // 2)
296+
name_label.y = int(height // (0.17 * name_scale))
229297
name_label.color = foreground_text_color
230298
name_group.append(name_label)
231299

@@ -238,14 +306,11 @@ def badge(self, *, background_color=0xFF0000, foreground_color=0xFFFFFF,
238306

239307
@staticmethod
240308
def bitmap_qr(matrix):
241-
# monochome (2 color) palette
309+
"""The QR code bitmap."""
242310
border_pixels = 2
243-
244-
# bitmap the size of the screen, monochrome (2 colors)
245311
bitmap = displayio.Bitmap(matrix.width + 2 * border_pixels,
246312
matrix.height + 2 * border_pixels, 2)
247-
# raster the QR code
248-
for y in range(matrix.height): # each scanline in the height
313+
for y in range(matrix.height):
249314
for x in range(matrix.width):
250315
if matrix[x, y]:
251316
bitmap[x + border_pixels, y + border_pixels] = 1
@@ -254,17 +319,25 @@ def bitmap_qr(matrix):
254319
return bitmap
255320

256321
def qr_code(self, data=b'https://circuitpython.org', dwell=20):
257-
qr = adafruit_miniqr.QRCode(qr_type=3, error_correct=adafruit_miniqr.L)
258-
qr.add_data(data)
259-
qr.make()
260-
qr_bitmap = self.bitmap_qr(qr.matrix)
322+
"""Generate a QR code and display it for ``dwell`` seconds.
323+
324+
:param bytearray data: A bytearray of data for the QR code
325+
:param int dwell: The amount of time in seconds to display the QR code
326+
327+
"""
328+
qr_code = adafruit_miniqr.QRCode(qr_type=3, error_correct=adafruit_miniqr.L)
329+
qr_code.add_data(data)
330+
qr_code.make()
331+
qr_bitmap = self.bitmap_qr(qr_code.matrix)
261332
palette = displayio.Palette(2)
262333
palette[0] = 0xFFFFFF
263334
palette[1] = 0x000000
264-
qr_code_scale = min(self.display.width // qr_bitmap.width, self.display.height // qr_bitmap.height)
335+
qr_code_scale = min(self.display.width // qr_bitmap.width,
336+
self.display.height // qr_bitmap.height)
265337
qr_position_x = int(((self.display.width / qr_code_scale) - qr_bitmap.width) / 2)
266338
qr_position_y = int(((self.display.height / qr_code_scale) - qr_bitmap.height) / 2)
267-
qr_img = displayio.TileGrid(qr_bitmap, pixel_shader=palette, x=qr_position_x, y=qr_position_y)
339+
qr_img = displayio.TileGrid(qr_bitmap, pixel_shader=palette, x=qr_position_x,
340+
y=qr_position_y)
268341
qr_code = displayio.Group(scale=qr_code_scale)
269342
qr_code.append(qr_img)
270343
self.display.show(qr_code)

docs/conf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
# Uncomment the below if you use native CircuitPython modules such as
2121
# digitalio, micropython and busio. List the modules you use. Without it, the
2222
# autodoc module docs will fail to generate with a warning.
23-
# autodoc_mock_imports = ["digitalio", "busio"]
23+
autodoc_mock_imports = ["audioio", "displayio", "gamepadshift", "neopixel", "analogio",
24+
"adafruit_display_shapes", "adafruit_display_text", "terminalio",
25+
"adafruit_miniqr"]
2426

2527

2628
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}

docs/index.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,10 @@ Table of Contents
2323
.. toctree::
2424
:caption: Tutorials
2525

26-
.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave
27-
the toctree above for use later.
2826

2927
.. toctree::
3028
:caption: Related Products
3129

32-
.. todo:: Add any product links here. If there are none, then simply delete this todo and leave
33-
the toctree above for use later.
3430

3531
.. toctree::
3632
:caption: Other Links

examples/Blinka.bmp

60.1 KB
Binary file not shown.

examples/pybadger_simpletest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from adafruit_pybadger import PyBadger
2+
3+
pybadger = PyBadger()
4+
5+
while True:
6+
pybadger.badge(hello_scale=2, my_name_is_scale=2, name_scale=3)
7+
pybadger.auto_dim_display()
8+
9+
if pybadger.button.a:
10+
pybadger.business_card(image_name="Blinka.bmp")
11+
elif pybadger.button.b:
12+
print("b B")
13+
elif pybadger.button.start:
14+
print("b start")
15+
elif pybadger.button.select:
16+
pybadger.qr_code()

0 commit comments

Comments
 (0)