Keyboard Shortcut, Qwiic Keypad
CircuitPython Example
In an effort to utilize the CircuitPython capability of the RedBoard Turbo, I also have included CircuitPython example code. When you plug the RedBoard Turbo into the computer, it should show up as an USB drive. If not, check out the Troubleshooting section below on how to re-install CircuitPython. To upload your code to your board, you must save the python file on the drive that appears when the board is plugged in.
Import CircuitPython Libraries
Installing the Libraries
There may be better instructions than these, but this is what I did to get the CircuitPython libraries onto the RedBoard Turbo. You can also download the library directly using the button below.
- Go to the Releases tab for the GitHub Repository.
- Download the .zip file containing "bundule-3.x-mpy" in the name or click the button below.
- Unzip the file.
- Copy the lib folder from file onto the board.
Utilizing the Libraries
To utilize the libraries in your code, you need to import
them. Below, are the lines used for importing the libraries in the example python code.
language:python
import time
import board
import busio
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
Implementing CircuitPython
Querying the Keypad
Using the description of the FIFO operation from the Qwiic Keypad hookup guide, the Qwiic Keypad utilizes two registers for querying button presses. The first is register 0x03, that is read for the oldest entry in the FIFO (first-in, first-out) stack. The second is the FIFO increment command register, 0x06, used to update register 0x03 with the next button value.
Setup for I2C
To setup your I2C connection, you need to import the following libraries. You also need to define the pins used for the I2C bus, which was built into the board
library for the SAMD21 used on the Turbo. Finally, the I2C address for the Qwiic Keypad was store as a variable.
language:python
import time
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
i2caddress = 75 #equals 0x4B in HEX
Read Register
The following code is used to read the value of the oldest button press out of the FIFO stack from register 0x03.
language:python
i2c.writeto(i2caddress, bytes([0x03]), start=0, end=8, stop=True)
time.sleep(.2)
i2c.readfrom_into(i2caddress, result2, start=0, end=1)
Write/Set Register
The following code is used to write 0x01 to register 0x06 to increment the FIFO stack, updating the value stores in register 0x03.
language:python
i2c.writeto(i2caddress, bytes([0x06,0x01]), start=0, end=16, stop=True)
Creating Shortcuts
Utilizing HID Library
The CircuitPython HID library works similarly to the Arduino library used in the previous section. To reference keycodes and naming conventions I used a combination of the following documentation:
- CircuitPython HID library
- USB HID Keycode Usage Table
- Keyboard Keycodes from Arduino HID-Project Library
- Consumer Keycodes from Arduino HID-Project Library
Button Combinations
To create shortcut using button combinations, find out the button combination for your shortcut. These should be listed in the user manual for your program or operating system; otherwise, the internet is a great resource. Make sure to test that the shortcut works before programming it.
To code your shortcut in CircuitPython, use the kbd.press(Define_Key)
function, designating the individual key. To press multiple keys together, call this function again while designating each of the individual keys. Then use kbd.release_all()
to release all the keys pressed at once. Please refer to the documentation listed above for the naming convention (or keycode) of each keyboard key.
Example: Ctrl + Alt + F1
Code:
language:python
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.ALT)
kbd.press(Keycode.INSERT)
kbd.release_all()
Functional Buttons
To create a functional shortcut in CircuitPython, use the cc.send(Define_Key)
function, designating the functional key to implement. Please refer to the documentation listed above for the naming convention (or keycode) of the available keys.
Example:
Code:
language:python
cc.send(ConsumerControlCode.VOLUME_DECREMENT)
Text String
To type out a string of text in CircuitPython, use the layout.write('Text')
function.
<table>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
layout.write('<table border="1">\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' </tr>\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td style="padding:10px" valign="top"></td>\n')
layout.write(' <td style="padding:10px"></td>\n')
layout.write(' <td style="padding:10px"></td>\n')
layout.write(' </tr>\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td></td>\n')
layout.write(' <td></td>\n')
layout.write(' <td></td>\n')
layout.write(' </tr>\n')
layout.write('</table>\n')
Example Code
In the example code below I have implemented specific keyboard shortcuts for my personal needs. You will also notice, that in certain instances, I have combined a series of different shortcuts for greater functionality.
code.py
on the drive that appears when the RedBoard Turbo is plugged into your computer.language:python
""" Hot-Shortcut KeyPad
By: Wes Furuya
SparkFun Electronics
Date: March 27th, 2019
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
Feel like supporting our work? Buy a board from SparkFun!
https://www.sparkfun.com/products/14641
https://www.sparkfun.com/products/14812
This sketch allows the RedBoard Turbo to emulate a HID keyboard. The buttons on the Qwiic Keypad are set for specific keyboard entries. For more details, please refer to the project guide:
https://learn.sparkfun.com/tutorials/keyboard-shortcut-qwiic-keypad """
import time
import board
import busio
# https:#github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/tag/20190326
# 1. Download "bundule-3.x":
# https:#github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20190326/adafruit-circuitpython-bundle-3.x-mpy-20190326.zip
# 2. Unzip
# 3. Copy lib folder on to board
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
cc = ConsumerControl()
kbd = Keyboard()
layout = KeyboardLayoutUS(kbd)
i2c = busio.I2C(board.SCL, board.SDA)
i2caddress = 75 #equals 0x4B in HEX
CALCULATOR = 402 #equals 0x192 in HEX
while not i2c.try_lock():
pass
while True:
result2 = bytearray(1)
i2c.writeto(i2caddress, bytes([0x03]), start=0, end=8, stop=True)
i2c.readfrom_into(i2caddress, result2, start=0, end=1)
if result2 != bytes([0x00]):
if result2 == b'1':
cc.send(ConsumerControlCode.MUTE)
print(result2)
elif result2 == b'2':
cc.send(ConsumerControlCode.VOLUME_DECREMENT)
print(result2)
elif result2 == b'3':
cc.send(ConsumerControlCode.VOLUME_INCREMENT)
print(result2)
elif result2 == b'4':
cc.send(CALCULATOR) #cc.send(402)
print(result2)
elif result2 == b'5':
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.ALT)
kbd.press(Keycode.INSERT)
kbd.release_all()
print(result2)
elif result2 == b'6':
kbd.send(227) #Windows Button
time.sleep(.05)
layout.write('ter')
time.sleep(.1)
kbd.send(Keycode.ENTER)
print(result2)
elif result2 == b'7':
# Cuts selected entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.X)
kbd.release_all()
time.sleep(.05)
layout.write('<!-- product_big(')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write(') -->\n')
layout.write('<!-- products_by_id(')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('ID1, ID2) -->\n')
layout.write('<div class="clearfix"></div>')
elif result2 == b'8':
#Types text
layout.write('<table border="1">\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' <td style="padding:10px" valign="center"></td>\n')
layout.write(' </tr>\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td style="padding:10px" valign="top"></td>\n')
layout.write(' <td style="padding:10px"></td>\n')
layout.write(' <td style="padding:10px"></td>\n')
layout.write(' </tr>\n')
layout.write(' <tr style="padding:10px">\n')
layout.write(' <td></td>\n')
layout.write(' <td></td>\n')
layout.write(' <td></td>\n')
layout.write(' </tr>\n')
layout.write('</table>\n')
elif result2 == b'9':
#Cuts selected entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.X)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('<div class="alert alert-info"><b>Note:</b>')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('</div>')
elif result2 == b'*':
#Cuts selected entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.X)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('-> [![alt text](')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write(')](')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write(') <-')
layout.write('<div class="center-block text-center"> *Caption* </div>')
elif result2 == b'0':
#Cuts selected entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.X)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('<center><a href="')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('"><img src="')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('" alt=""></a></center>')
layout.write('<center><i>Caption</i></center>')
elif result2 == b'#':
#Cuts selected entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.X)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('<kbd>')
time.sleep(.05)
#Pastes entry
kbd.press(Keycode.CONTROL)
kbd.press(Keycode.V)
kbd.release_all()
time.sleep(.05)
#Types text
layout.write('</kbd>')
else:
print(result2)
time.sleep(.05)
i2c.writeto(i2caddress, bytes([0x06,0x01]), start=0, end=16, stop=True)