|
| 1 | +# SPDX-FileCopyrightText: 2023 Pete Warden |
| 2 | +# SPDX-License-Identifier: Apache-2.0 |
| 3 | +# |
| 4 | +# Example of accessing the Tiny Code Reader from Useful Sensors on a Trinkey |
| 5 | +# using CircuitPython. See https://usfl.ink/tcr_dev for the full developer guide. |
| 6 | + |
| 7 | +import struct |
| 8 | +import time |
| 9 | +import board |
| 10 | +import usb_hid |
| 11 | + |
| 12 | +from adafruit_hid.keyboard import Keyboard |
| 13 | +from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS |
| 14 | + |
| 15 | +# The code reader has the I2C ID of hex 0c, or decimal 12. |
| 16 | +TINY_CODE_READER_I2C_ADDRESS = 0x0C |
| 17 | + |
| 18 | +# How long to pause between sensor polls. |
| 19 | +TINY_CODE_READER_DELAY = 0.2 |
| 20 | + |
| 21 | +TINY_CODE_READER_LENGTH_OFFSET = 0 |
| 22 | +TINY_CODE_READER_LENGTH_FORMAT = "H" |
| 23 | +TINY_CODE_READER_MESSAGE_OFFSET = TINY_CODE_READER_LENGTH_OFFSET + \ |
| 24 | + struct.calcsize(TINY_CODE_READER_LENGTH_FORMAT) |
| 25 | +TINY_CODE_READER_MESSAGE_SIZE = 254 |
| 26 | +TINY_CODE_READER_MESSAGE_FORMAT = "B" * TINY_CODE_READER_MESSAGE_SIZE |
| 27 | +TINY_CODE_READER_I2C_FORMAT = TINY_CODE_READER_LENGTH_FORMAT + TINY_CODE_READER_MESSAGE_FORMAT |
| 28 | +TINY_CODE_READER_I2C_BYTE_COUNT = struct.calcsize(TINY_CODE_READER_I2C_FORMAT) |
| 29 | + |
| 30 | +i2c = board.I2C() |
| 31 | + |
| 32 | +# Wait until we can access the bus. |
| 33 | +while not i2c.try_lock(): |
| 34 | + pass |
| 35 | + |
| 36 | +# For debugging purposes print out the peripheral addresses on the I2C bus. |
| 37 | +# 98 (0x62 in hex) is the address of our person sensor, and should be |
| 38 | +# present in the list. Uncomment the following three lines if you want to see |
| 39 | +# what I2C addresses are found. |
| 40 | +# while True: |
| 41 | +# print(i2c.scan()) |
| 42 | +# time.sleep(TINY_CODE_READER_DELAY) |
| 43 | + |
| 44 | +# Create a keyboard device so we can send the screen lock command. |
| 45 | +keyboard = Keyboard(usb_hid.devices) |
| 46 | +layout = KeyboardLayoutUS(keyboard) |
| 47 | + |
| 48 | +last_message_string = None |
| 49 | +last_code_time = 0.0 |
| 50 | + |
| 51 | +while True: |
| 52 | + read_data = bytearray(TINY_CODE_READER_I2C_BYTE_COUNT) |
| 53 | + i2c.readfrom_into(TINY_CODE_READER_I2C_ADDRESS, read_data) |
| 54 | + |
| 55 | + message_length, = struct.unpack_from(TINY_CODE_READER_LENGTH_FORMAT, read_data, |
| 56 | + TINY_CODE_READER_LENGTH_OFFSET) |
| 57 | + message_bytes = struct.unpack_from(TINY_CODE_READER_MESSAGE_FORMAT, read_data, |
| 58 | + TINY_CODE_READER_MESSAGE_OFFSET) |
| 59 | + |
| 60 | + if message_length > 0: |
| 61 | + message_string = bytearray(message_bytes)[0:message_length].decode("utf-8") |
| 62 | + is_same = (message_string == last_message_string) |
| 63 | + last_message_string = message_string |
| 64 | + current_time = time.monotonic() |
| 65 | + time_since_last_code = current_time - last_code_time |
| 66 | + last_code_time = current_time |
| 67 | + # Debounce the input by making sure there's been a gap in time since we |
| 68 | + # last saw this code. |
| 69 | + if (not is_same) or (time_since_last_code > 1.0): |
| 70 | + print(message_string) |
| 71 | + try: |
| 72 | + layout.write(message_string) |
| 73 | + except ValueError as e: |
| 74 | + pass |
| 75 | + layout.write("\n") |
0 commit comments