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
Blink test¶
Enable automatic blinking on select keys.
examples/alt_neokey_blinktest.py¶
1# SPDX-FileCopyrightText: Copyright (c) 2021 Greg Paris
2#
3# SPDX-License-Identifier: MIT
4
5# A fanciful example that shows two NeoKey 1x4 keypads
6# being used to alert on the status of critical ship
7# systems. Because the auto_action function needs to
8# reference the NeoKey1x4 instance, the function is
9# defined after the constructor and put into effect
10# using the auto_action property.
11
12from collections import namedtuple
13from random import randrange
14import gc
15import board
16
17print("Alternative API NeoKey blink test")
18
19# report memory before instantiating NeoKey1x4
20used1, free1 = gc.mem_alloc(), gc.mem_free() # pylint: disable=no-member
21print(f"Memory: Start: alloc={used1} free={free1}")
22
23from alt_neokey.alt_neokey1x4 import NeoKey1x4 # pylint: disable=wrong-import-position
24
25System = namedtuple("System", ("name", "color"))
26SYSTEMS = (
27 System("AM CONTAIMENT", 0x0000FF),
28 System("WARP COILS", 0xFF0000),
29 System("SUBSPACE COMMS", 0x00FF00),
30 System("TRANSPORTER", 0xFF7700),
31 System("DECOM CHAMBER", 0x7700FF),
32 System("MED BAY", 0xFF0077),
33 System("HULL PLATING", 0x00FF77),
34 System("PHASE CANNONS", 0xFFFFFF),
35)
36
37
38def my_colors(kev):
39 # blink will default to white if the released color is 0
40 # so, this time, we'll choose to go dark when pressed.
41 # Other than the weird colors for this demo, this looks great!
42 # Just in case you have more than two modules connected,
43 # defaults to white.
44 if kev.pressed:
45 return 0
46 try:
47 return SYSTEMS[kev.key_num].color
48 except IndexError:
49 return 0xFFFFFF
50
51
52i2c_bus = board.I2C()
53
54# Create a NeoKey object for all NeoKey1x4 modules
55# on the i2c buss using the class method all().
56neokey = NeoKey1x4.all(
57 i2c_bus,
58 auto_color=my_colors,
59)
60
61# This time, our automatic action will be to change whether
62# the key is blinking. We may do it on pressed or released,
63# but not both, since that would negate itself. Also, we
64# must define this function *after* we have neokey, since
65# we need a reference to it.
66def my_action(kev):
67 if kev.pressed:
68 key = neokey[kev.key_num] # this is a NeoKey_Key object
69 key.blink = not key.blink
70 try:
71 system = SYSTEMS[kev.key_num].name
72 except IndexError:
73 system = f"#{kev.key_num}"
74 if key.blink:
75 print(f"ALERT on {system}!")
76 else:
77 print(f"{system} alert cleared.")
78
79
80neokey.auto_action = my_action
81
82# We have some warnings!
83for _ in range(3):
84 key_num = randrange(len(neokey))
85 neokey[key_num].blink = True
86
87# report memory again
88used2, free2 = gc.mem_alloc(), gc.mem_free() # pylint: disable=no-member
89delta = used2 - used1
90print(f"Memory: After: alloc={used2} free={free2} delta={delta}")
91
92# Read keys, process any events. Manage colors and blinking.
93# If you want responsive keys, you can't spend much time doing work!
94# All of the simulated work sleeps have been removed in this example
95# to demonstrate the best-case performance.
96while True:
97 neokey.read()
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)