Simple test

Ensure your device works with this simple test.

examples/alt_neokey_simpletest.py
 1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
 2#
 3# SPDX-License-Identifier: MIT
 4
 5# Basic test of a single NeoKey 1x4 board. Some sleeps
 6# are in the demo to give a feel for real work being done.
 7# The more work your program does, the slower the keys
 8# will be to respond. Fortunately, this board uses I2C,
 9# so it will be easy to interface with a faster processor
10# if you need to.
11
12from time import sleep
13import gc
14import board
15
16print("Alt API NeoKey simple test")
17
18# report memory before instantiating NeoKey1x4
19used1, free1 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
20print(f"Memory: Start: alloc={used1} free={free1}")
21
22from alt_neokey.alt_neokey1x4 import NeoKey1x4  # pylint: disable=wrong-import-position
23
24i2c_bus = board.I2C()
25
26# Create a NeoKey object with optional auto_color function
27neokey = NeoKey1x4(
28    i2c_bus,
29    addr=0x30,
30    auto_color=lambda e: 0x00FF33 if e.pressed else 0x000000,
31)
32
33# report memory again
34used2, free2 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
35delta = used2 - used1
36print(f"Memory: After: alloc={used2} free={free2} delta={delta}")
37
38# Read keys, process any events
39# if you want responsive keys, you can't spend much time doing work!
40while True:
41    for event in neokey.read():
42        if event.pressed:
43            print(f"key {event.key_num} pressed")
44            sleep(0.1)  # pretend to do stuff
45        else:
46            print(f"key {event.key_num} released")
47            sleep(0.1)  # pretend to do stuff
48    sleep(0.1)  # pretend to do stuff

Multi-test

Ensure two NeoKey devices can work together.

examples/alt_neokey_multitest.py
 1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
 2#
 3# SPDX-License-Identifier: MIT
 4
 5# This example shows how easy it is to use more than
 6# one NeoKey 1x4 module in a group. To use it, you will
 7# need to have two modules! And one needs to have the
 8# A0 bridge soldered, resulting in address 0x31. If that's
 9# not your case, adjust the code below as needed. If you
10# have more than two modules, give them all unique addresses
11# by bridging different address bits (range is 0x30 to 0x3f),
12# then list them all in the addr tuple below.
13
14from time import sleep
15import gc
16import board
17
18print("Alt API NeoKey multi-test")
19
20# report memory before instantiating NeoKey1x4
21used1, free1 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
22print(f"Memory: Start: alloc={used1} free={free1}")
23
24from alt_neokey.alt_neokey1x4 import NeoKey1x4  # pylint: disable=wrong-import-position
25
26# optional automatic key color handling
27# this time we take advantage of global variables
28key_colors = (0x0000FF, 0xFF0000, 0x00FF00, 0xFF6600)
29color_index = 0
30
31
32def my_colors(kev):
33    """Next color each time a key is pressed"""
34    global color_index, key_colors  # pylint: disable=global-statement
35    if kev.pressed:
36        color_index = (color_index + 1) % len(key_colors)
37        return key_colors[color_index]
38    return 0x333333
39
40
41i2c_bus = board.I2C()
42
43# Create a NeoKey object for two NeoKey1x4 modules
44neokey = NeoKey1x4(
45    i2c_bus,
46    addr=(0x30, 0x31),
47    auto_color=my_colors,
48)
49
50# report memory again
51used2, free2 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
52delta = used2 - used1
53print(f"Memory: After: alloc={used2} free={free2} delta={delta}")
54
55# Read keys, process any events
56# if you want responsive keys, you can't spend much time doing work!
57while True:
58    events = neokey.read()
59    for event in events:
60        if event.pressed:
61            print(f"key {event.key_num} pressed")
62            sleep(0.1)  # pretend to do stuff
63        else:
64            print(f"key {event.key_num} released")
65            sleep(0.1)  # pretend to do stuff
66    sleep(0.1)  # pretend to do stuff

Color-mode test

Alternate between two key-color modes by pressing a key.

examples/alt_neokey_colormodetest.py
 1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
 2#
 3# SPDX-License-Identifier: MIT
 4
 5# Demonstrate changing auto_color action to produce
 6# different modes. This example uses key 0 to do it,
 7# but a real program might change modes based upon
 8# some measured condition.
 9
10import board
11from alt_neokey.alt_neokey1x4 import NeoKey1x4
12
13print("Alt API NeoKey color modes test")
14
15
16def normal_mode(kev):
17    return 0xFF0000 if kev.pressed else 0x777777
18
19
20def special_mode(kev):
21    return 0xFF7700 if kev.pressed else 0x007700
22
23
24i2c = board.I2C()
25neokey = NeoKey1x4(i2c, auto_color=normal_mode)
26
27while True:
28    for event in neokey.read():
29        if event.pressed and event.key_num == 0:
30            if neokey.auto_color is normal_mode:
31                neokey.auto_color = special_mode
32            else:
33                neokey.auto_color = normal_mode

Action test

Demonstrate automatic actions.

examples/alt_neokey_actiontest.py
 1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
 2#
 3# SPDX-License-Identifier: MIT
 4
 5# This example shows use of a function called via the
 6# auto_action feature. This example is trivial, but
 7# a more real use might be to use an audio device to
 8# make a sound when a key is pressed.
 9#
10# Any code can be put into the auto_function, but for
11# readability, it might be best to keep the primary thrust
12# of your program in the main loop, using the auto_action
13# function for "housekeeping".
14
15from time import sleep
16import gc
17import board
18
19print("Alternative API NeoKey action test")
20
21# report memory before instantiating NeoKey1x4
22used1, free1 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
23print(f"Memory: Start: alloc={used1} free={free1}")
24
25from alt_neokey.alt_neokey1x4 import NeoKey1x4  # pylint: disable=wrong-import-position
26
27# optional automatic key color handling
28# this time we give each key a different pressed color
29key_colors = (
30    0x0000FF,
31    0xFF0000,
32    0x00FF00,
33    0xFF7700,
34    0x7700FF,
35    0xFF0077,
36    0x00FF77,
37    0xFFFFFF,
38)
39
40
41def my_colors(kev):
42    return key_colors[kev.key_num] if kev.pressed else 0
43
44
45# this time, instead of reading the event list, we'll perform an automatic action
46def my_action(kev):
47    if kev.pressed:
48        print(f"key {kev.key_num} pressed")
49    else:
50        print(f"key {kev.key_num} released")
51    sleep(0.1)  # pretend to do stuff
52
53
54i2c_bus = board.I2C()
55
56# Create a NeoKey object for two NeoKey1x4 modules
57neokey = NeoKey1x4(
58    i2c_bus,
59    addr=(0x30, 0x31),
60    auto_color=my_colors,
61    auto_action=my_action,
62)
63
64# report memory again
65used2, free2 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
66delta = used2 - used1
67print(f"Memory: After: alloc={used2} free={free2} delta={delta}")
68
69# Read keys, process any events
70# if you want responsive keys, you can't spend much time doing work!
71while True:
72    events = neokey.read()
73    sleep(0.1)  # pretend to do stuff

Read Event test

Same as blink test, but uses read_event() instead of read().

examples/alt_neokey_readevent.py
  1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
  2#
  3# SPDX-License-Identifier: MIT
  4
  5# This is the same example as blinktest, but uses
  6# the read_event() method. Jump to the bottom to see.
  7#
  8# A fanciful example that shows two NeoKey 1x4 keypads
  9# being used to alert on the status of critical ship
 10# systems. Because the auto_action function needs to
 11# reference the NeoKey1x4 instance, the function is
 12# defined after the constructor and put into effect
 13# using the auto_action property.
 14
 15from collections import namedtuple
 16from random import randrange
 17import gc
 18import board
 19
 20print("Alternative API NeoKey read event test")
 21
 22# report memory before instantiating NeoKey1x4
 23used1, free1 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
 24print(f"Memory: Start: alloc={used1} free={free1}")
 25
 26from alt_neokey.alt_neokey1x4 import NeoKey1x4  # pylint: disable=wrong-import-position
 27
 28System = namedtuple("System", ("name", "color"))
 29SYSTEMS = (
 30    System("AM CONTAIMENT", 0x0000FF),
 31    System("WARP COILS", 0xFF0000),
 32    System("SUBSPACE COMMS", 0x00FF00),
 33    System("TRANSPORTER", 0xFF7700),
 34    System("DECOM CHAMBER", 0x7700FF),
 35    System("MED BAY", 0xFF0077),
 36    System("HULL PLATING", 0x00FF77),
 37    System("PHASE CANNONS", 0xFF00FF),
 38)
 39
 40
 41def my_colors(kev):
 42    # blink will default to white if the released color is 0
 43    # so, this time, we'll choose to go dark when pressed.
 44    # Other than the weird colors for this demo, this looks great!
 45    # Just in case you have more than two modules connected,
 46    # defaults to white.
 47    if kev.pressed:
 48        return 0
 49    try:
 50        return SYSTEMS[kev.key_num].color
 51    except IndexError:
 52        return 0xFFFFFF
 53
 54
 55i2c_bus = board.I2C()
 56
 57# Create a NeoKey object for all NeoKey1x4 modules
 58# on the i2c buss using the class method all().
 59neokey = NeoKey1x4.all(
 60    i2c_bus,
 61    auto_color=my_colors,
 62)
 63
 64# This time, our automatic action will be to change whether
 65# the key is blinking. We may do it on pressed or released,
 66# but not both, since that would negate itself. Also, we
 67# must define this function *after* we have neokey, since
 68# we need a reference to it.
 69def my_action(kev):
 70    if kev.pressed:
 71        key = neokey[kev.key_num]  # this is a NeoKey_Key object
 72        key.blink = not key.blink
 73        try:
 74            system = SYSTEMS[kev.key_num].name
 75        except IndexError:
 76            system = f"#{kev.key_num}"
 77        if key.blink:
 78            print(f"ALERT on {system}!")
 79        else:
 80            print(f"{system} alert cleared.")
 81
 82
 83neokey.auto_action = my_action
 84
 85# We have some warnings!
 86for _ in range(3):
 87    key_num = randrange(len(neokey))
 88    neokey[key_num].blink = True
 89
 90# report memory again
 91used2, free2 = gc.mem_alloc(), gc.mem_free()  # pylint: disable=no-member
 92delta = used2 - used1
 93print(f"Memory: After: alloc={used2} free={free2} delta={delta}")
 94
 95# With read_event(), we no longer need a "while True:".
 96# But, by default, read_event() doesn't return without an event,
 97# so no processing can happen unless a key is pressed or
 98# released. Depending on your application, this is either
 99# perfectly fine or is a critical flaw.
100#
101# To overcome this issue, specify a timeout in 10ths of a
102# second, as done below. This will cause read_event() to
103# return None after the specified number of second tenths
104# has elapsed with no key presses or releases. The timeout
105# in this example is one second.
106for event in neokey.read_event(timeout=10):
107    if event is None:
108        print("got timeout")
109    else:
110        print(event)