# MACROPAD Hotkeys

## CircuitPython

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** drive to iterate.

## CircuitPython Quickstart

Follow this step-by-step to quickly get CircuitPython running on your board.

[Download the latest version of CircuitPython for this board via circuitpython.org](https://circuitpython.org/board/adafruit_macropad_rp2040/)
 **Click the link above to download the latest CircuitPython UF2 file.**

Save it wherever is convenient for you.

![install_circuitpython_on_rp2040_RP2040_UF2_downloaded.jpg](https://cdn-learn.adafruit.com/assets/assets/000/101/655/medium640/install_circuitpython_on_rp2040_RP2040_UF2_downloaded.jpg?1618943202)

![](https://cdn-learn.adafruit.com/assets/assets/000/103/264/medium800/adafruit_products_MacroPad_boot_reset.jpg?1625068553)

Info: 

To enter the bootloader, hold down the **BOOT/**** BOOTSEL button**(highlighted in red above), and while continuing to hold it (don't let go!), press and release the**reset button**(highlighted in red or blue above).&nbsp;**Continue to hold the BOOT/BOOTSEL button until the RPI-RP2 drive appears!**

If the drive does not appear, release all the buttons, and then repeat the process above.

You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.

A lot of people end up using charge-only USB cables and it is very frustrating! **Make sure you have a USB cable you know is good for data sync.**

You will see a new disk drive appear called **RPI-RP2**.

&nbsp;

Drag the **adafruit\_circuitpython\_etc.uf2** file to **RPI-RP2.**

![install_circuitpython_on_rp2040_RP2040_bootloader_drive.jpg](https://cdn-learn.adafruit.com/assets/assets/000/101/656/medium640/install_circuitpython_on_rp2040_RP2040_bootloader_drive.jpg?1618943666)

![install_circuitpython_on_rp2040_RP2040_drag_UF2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/101/657/medium640/install_circuitpython_on_rp2040_RP2040_drag_UF2.jpg?1618943674)

The **RPI-RP2** drive will disappear and a new disk drive called **CIRCUITPY** will appear.

That's it, you're done! :)

![install_circuitpython_on_rp2040_RP2040_CIRCUITPY.jpg](https://cdn-learn.adafruit.com/assets/assets/000/101/658/medium640/install_circuitpython_on_rp2040_RP2040_CIRCUITPY.jpg?1618943864)

## Safe Mode

You want to edit your **code.py** or modify the files on your **CIRCUITPY** drive, but find that you can't. Perhaps your board has gotten into a state where **CIRCUITPY** is read-only. You may have turned off the **CIRCUITPY** drive altogether. Whatever the reason, safe mode can help.

Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode _bypasses any code in_ **boot.py** (where you can set **CIRCUITPY** read-only or turn it off completely). Second, _it does not run the code in_ **code.py**. And finally, _it does not automatically soft-reload when data is written to the_ **CIRCUITPY** _drive_.

Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the **CIRCUITPY** drive.

### Entering Safe Mode
To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)

### In Safe Mode

If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.

If you connect to the serial console, you'll find the following message.

```terminal
Auto-reload is off.
Running in safe mode! Not running saved code.

CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.
```

You can now edit the contents of the **CIRCUITPY** drive. Remember, _your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode._

## Flash Resetting UF2

If your board ever gets into a really _weird_ state and CIRCUITPY doesn't show up as a disk drive after installing CircuitPython, try loading this 'nuke' UF2 to RPI-RP2. which will do a 'deep clean' on your Flash Memory. **You will lose all the files on the board** , but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.

[Download flash erasing "nuke" UF2](https://cdn-learn.adafruit.com/assets/assets/000/101/659/original/flash_nuke.uf2?1618945856)
# MACROPAD Hotkeys

## Project Code

## Text Editor

Adafruit recommends using the **Mu** editor for editing your CircuitPython code. You can get more info in [this guide](https://learn.adafruit.com/welcome-to-circuitpython/installing-mu-editor).

Alternatively, you can use any text editor that saves simple text files.

## Download the Project Bundle

Your project will use a specific set of CircuitPython libraries and the&nbsp; **code.py** &nbsp;file, along with a folder full of key configuration files. To get everything you need, click on the&nbsp; **Download Project Bundle** &nbsp;link below, and uncompress the .zip file.

Drag the contents of the uncompressed bundle directory onto your MACROPAD board's **CIRCUITPY** &nbsp;drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.

Inside the **macros** folder, you’ll likely want to pluck out any macro settings files to discard. They’re prefixed with “mac” and “win”for MacOS and Windows since these systems have different modifier keys. These files are just a starting point for reference…more likely, you’ll start creating your own.

**If updating from a prior version of this code, move any key configuration files that you’ve created or edited to a safe place first, so they’re not overwritten or lost, then move them back to the CIRCUITPY/macros folder after updating.**

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Macropad_Hotkeys/code.py

# MACROPAD Hotkeys

## Custom Configurations

You can add or remove&nbsp;MACROPAD configurations for different applications just by moving files in or out of the **CIRCUITPY/macros** folder. At its simplest, you can collect existing configuration files and never need to edit anything.

Each of these files is really just a snippet of **CircuitPython** code. They can be modified with any text editor, and text files are easily shared, for example in the [Adafruit Forums](https://forums.adafruit.com).

You could start by copying one of the examples in the **macros** folder. Give it a descriptive name…and, if you’ll be sharing this with others, consider&nbsp;mentioning right in the filename what system it’s for, since key sequences vary among platforms (e.g.&nbsp;COMMAND vs. CONTROL on Mac vs Windows).

Here’s one of the examples, **mac-safari.py** , for the Safari web browser on MacOS:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Macropad_Hotkeys/macros/mac-safari.py

This is just a single Python dictionary (which **must** be named ' **app**' for the project code to find it) containing two keys: ' **name**' and ' **macros**'.

' **name**' is what’s shown across the top of MACROPAD’s display when turning the knob to switch settings. This must be a short string in quotes, no more than 20 characters, for example **'Safari'**.

' **macros**' is a list [enclosed in square brackets] of tuples (each enclosed in parenthesis) — one for each of MACROPAD’s 12 keys, and optionally one more for the encoder button. These appear sequentially, first item for the top-left key, second for top-center, and so forth. The examples have some Python comments to explain what’s happening.

Each of these tuples contains **three** elements:

1. A **hexadecimal RGB color** value for the corresponding **LED**. You may want to avoid bright values, as a whole keypad of these can be distracting. If you like, color-code related groups of keys, or theme whole applications so you can tell what’s active at a glance.
2. A brief **description** , in quotes. This is what’s displayed on MACROPAD’s OLED screen. _BRIEF_ is the operative word here, ideally **six characters or less**. You can _sometimes_ sneak in a 7-character label if adjoining items are shorter.
3. A **key sequence** , which can either be:
  1. A **single character or a string, in quotes** , if the key sequence is just regular keypresses (including SHIFT for uppercase characters).
  2. A **list [enclosed in square brackets]** of key code constants and quoted-strings, which will be issued in-order.

Most letters, numbers and symbols are best done as quoted strings…but for special navigation-type keys…arrows, COMMAND/CONTROL/OPTION, function keys and so forth…key constants are required. We can see a complete list of these&nbsp;by typing in the CircuitPython REPL:

```python
>>> from adafruit_hid.keycode import Keycode
>>> print(dir(Keycode))
['__class__', '__module__', '__name__', '__qualname__', '__bases__', '__dict__', 'C', 'M', 'A', 'B', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE', 'ZERO', 'ENTER', 'RETURN', 'ESCAPE', 'BACKSPACE', 'TAB', 'SPACEBAR', 'SPACE', 'MINUS', 'EQUALS', 'LEFT_BRACKET', 'RIGHT_BRACKET', 'BACKSLASH', 'POUND', 'SEMICOLON', 'QUOTE', 'GRAVE_ACCENT', 'COMMA', 'PERIOD', 'FORWARD_SLASH', 'CAPS_LOCK', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'PRINT_SCREEN', 'SCROLL_LOCK', 'PAUSE', 'INSERT', 'HOME', 'PAGE_UP', 'DELETE', 'END', 'PAGE_DOWN', 'RIGHT_ARROW', 'LEFT_ARROW', 'DOWN_ARROW', 'UP_ARROW', 'KEYPAD_NUMLOCK', 'KEYPAD_FORWARD_SLASH', 'KEYPAD_ASTERISK', 'KEYPAD_MINUS', 'KEYPAD_PLUS', 'KEYPAD_ENTER', 'KEYPAD_ONE', 'KEYPAD_TWO', 'KEYPAD_THREE', 'KEYPAD_FOUR', 'KEYPAD_FIVE', 'KEYPAD_SIX', 'KEYPAD_SEVEN', 'KEYPAD_EIGHT', 'KEYPAD_NINE', 'KEYPAD_ZERO', 'KEYPAD_PERIOD', 'KEYPAD_BACKSLASH', 'APPLICATION', 'POWER', 'KEYPAD_EQUALS', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'LEFT_CONTROL', 'CONTROL', 'LEFT_SHIFT', 'SHIFT', 'LEFT_ALT', 'ALT', 'OPTION', 'LEFT_GUI', 'GUI', 'WINDOWS', 'COMMAND', 'RIGHT_CONTROL', 'RIGHT_SHIFT', 'RIGHT_ALT', 'RIGHT_GUI', 'modifier_bit']
```

The Safari example was chosen because it demonstrates most permutations quite nicely…

The third key, “Up,” for example…in Safari, this is done with SHIFT+SPACE. There’s no such thing as an “uppercase space,” so we can’t just use a quoted string here. **Keycode.SHIFT** is a constant telling the code to press and hold the SHIFT key, and then the quoted space is issued. SHIFT is automatically released at the end of the sequence.

You can see other keys doing similar operations, sometimes with **Keycode.COMMAND** or sometimes multiple modifiers (“Previous Tab,” for example, is CONTROL+SHIFT+TAB).

The bottom three keys show how to press _and release_ keys mid-sequence. Each of these opens a new window (COMMAND+n) and enters a URL. We want the COMMAND key released after pressing 'n', so the characters in the URL string type normally, not as a list of commands. A _negative_ Keycode value is used to indicate “release this key now”:&nbsp; **-Keycode.COMMAND** in the example.

Instead of a Keycode or string, a **floating-point number** inserts a **pause** in the key-pressing sequence. The duration is in seconds, either whole or partial. For example:

`[Keycode.CONTROL, 0.5, 'a', 1.0, 'b']`

This would press (and keep held) the 'Control' key, &nbsp;pause one half second, type an “a,” pause one second, then type a “b” (Control is implicitly released at the end of the sequence). Even if pausing for whole seconds, the decimal _must_ be included…this is how it distinguishes from Keycodes, which are integer values.

_Though you_ could _store passwords in there, this is **strongly discouraged** , since&nbsp;the CircuitPython code is not protected or secure.&nbsp;Anyone with access to your MACROPAD can read these files!_

# MACROPAD Hotkeys

## Mouse and Media Controls

It started simply enough with a few key presses, but folks had bigger ideas for things to automate. Could we work in media controls like play/pause and volume, or mouse control?

The adafruit\_hid library certainly provides _access_ to such things,&nbsp;but a bigger question was: could these be added _without breaking compatibility with all the existing macro files that users have created and shared?&nbsp;_The first problem is simple and the code was extended to handle it, but to handle this second problem, the approach is a little obtuse. I apologize, but this seemed the best way to keep those existing files working and not require a do-over.

It relies on the fact that these macro files aren’t simply structured text like XML or JSON, they’re_&nbsp;snippets of actual Python code._ Python can distinguish between different data types — integers, lists, dictionaries and so forth — so we leverage that to distinguish key codes from media control, mouse and so forth.

Consider that the **last item** for each entry in a macro file is normally either a quoted string (which gets typed verbatim), _or_ a list of Keycodes and/or strings in a set of square brackets […], like so:

```auto
(0x000040, 'Brush', 'B'),
(0x004000, 'Undo', [Keycode.CONTROL, 'z']),
```

Along the way, it was decided that timed pauses were sometimes needed, and (as shown on the prior page) these could be inserted in that bracketed list as **floating-point** numbers. _Keycode values are really just integers,_ and CircuitPython can distinguish the two data types:

```auto
[Keycode.CONTROL, 0.5, 'a', 1.0, 'b']
```

So…to handle different controls, we just extended this types-in-list distinction to _more types._

## Media Control (“Consumer Control” codes)

For media functions like play/pause, volume or brightness your macro file should first import the ConsumerControlCode values. The example macro file **media.py** demonstrates this.

```auto
from adafruit_hid.consumer_control_code import ConsumerControlCode
```

Like HID Keycodes, ConsumerControl codes are _also_ just integers. But there are a few ranges where they may overlap. So, to distinguish between the two, Consumer Control codes go in a [] list nested _inside the Keycode list,_ like this:

```auto
[[ConsumerControlCode.SCAN_NEXT_TRACK]]
```

(Notice the double brackets: [[…]] )

If you need to get fancy, it’s possible to mix Keycodes, strings and/or Consumer Control codes in the same list (delays, too).

```auto
[Keycode.CONTROL, [ConsumerControlCode.SCAN_NEXT_TRACK], -Keycode.CONTROL, 1.0, 'foo']
```

(Press Control key, activate “next track,” release Control key, pause one second, type the string “foo”.)

For a complete list of Consumer Control codes, you can type in the CircuitPython REPL:

```auto
>>> from adafruit_hid.consumer_control_code import ConsumerControlCode
>>> print(dir(ConsumerControlCode))
['__class__', '__module__', '__name__', '__qualname__', '__bases__', '__dict__', 'RECORD', 'FAST_FORWARD', 'REWIND', 'SCAN_NEXT_TRACK', 'SCAN_PREVIOUS_TRACK', 'STOP', 'EJECT', 'PLAY_PAUSE', 'MUTE', 'VOLUME_DECREMENT', 'VOLUME_INCREMENT', 'BRIGHTNESS_DECREMENT', 'BRIGHTNESS_INCREMENT']
```

## Mouse Control

For mouse-related actions like movement and button clicks, your macro file should first import the HID Mouse module. The example macro file **mouse.py** demonstrates this.

```auto
from adafruit_hid.mouse import Mouse
```

A mouse is a more complex thing, with _spatial axes_ in addition to buttons. A bracketed list won’t do…we have to step this up to a full Python _dictionary,_ in curly braces {}. But this appears inside the original outermost Keycode [] list.

```auto
[{'buttons':Mouse.LEFT_BUTTON}]
```

(Notice the bracket-brace combo: [{ … }] )

The dictionary _key_ (the quoted bit of text before the colon) can be one of four values:&nbsp;`'x'`, `'y'`, `'wheel'` and `'buttons'`, controlling cursor movement, scroll wheel position, and button states, respectively.

The dictionary _value_ (after the colon) depends on what’s being controlled. For `'x'`, `'y'`, `'wheel'`, it’s a **signed integer** for **relative motion**. For example, `10` to move the cursor right or down by 10 pixels, or `-10` to move up or left. For `'buttons'`, it can be `Mouse.LEFT_BUTTON`, `Mouse.MIDDLE_BUTTON` or `Mouse.RIGHT_BUTTON`&nbsp;(you can combine multiple buttons with `+`) and, like Keycode, can be _negative_ if you want to indicate a button _release_ in the middle of a longer sequence.

And again, like with Consumer Control codes, this can be mixed with Keycodes and delays as part of a complex sequence.

## Experimental Stuff

The use of Python dictionaries for mouse control really opened this up for just about anything. As an experiment, the ability to play tones through MACROPAD’s onboard speaker was added. The example macro file **tones.py** demonstrates this. Not very useful on its own, but when used in combination with&nbsp;keyboard and mouse actions this could&nbsp;provide some audio feedback to each macro.

This plays a 262 Hz tone (roughly middle-C-ish) for as long as the corresponding key is held:

```auto
[{'tone':262}]
```

Only one tone can play at a time. These can be mixed in the [] macro list with other types. A value of 0 (or releasing the key) stops any currently-playing tone.&nbsp;For example, this will play middle-C for one half second:

```auto
[{'tone':262}, 0.5, {'tone':0}]
```

# MACROPAD Hotkeys

## Going Further

Once it’s all started up, the code has little work to do…just watch for key press events and encoder movement, taking some action when necessary.

If one were so inclined, the hardware and code could be extended for extra functionality.&nbsp;MACROPAD features a Stemma QT connector on the side, which might accommodate some interesting sensors or a&nbsp;[NeoKey 1x4 QT](https://www.adafruit.com/product/4980) for four extra key switches. The code as written does _not_ handle any of this automatically…the additions would be a software project of your own.

![circuitpython_4980-06.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/305/medium640/circuitpython_4980-06.jpg?1625616208)

Our hotkeys code uses MACROPAD’s encoder wheel to select among different application settings. It’s usually fine, but if you’re a big multitasker it can be awkward when the wrong app is selected (which is why color-coding with the LEDs is recommended, for at-a-glance familiarity).

Could there be some way to _automatically_ switch based on the current application in use? CircuitPython can receive serial messages while also emulating a keyboard, so there’s ways to send information to MACROPAD.&nbsp;The host-side implementation though, _that_ gets complex, and would vary with&nbsp;all the myriad system types and their particular scripting or development options, which is why it’s not done here. Food for thought!


## Featured Products

### Adafruit MacroPad RP2040 Starter Kit - 3x4 Keys + Encoder + OLED

[Adafruit MacroPad RP2040 Starter Kit - 3x4 Keys + Encoder + OLED](https://www.adafruit.com/product/5128)
Strap yourself in, we're launching in T-minus 10 seconds...Destination? A new Class M planet called MACROPAD! M here stands for Microcontroller because this 3x4 keyboard controller features the newest technology from the Raspberry Pi sector: say hello to the RP2040. It's a speedy...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5128)
[Related Guides to the Product](https://learn.adafruit.com/products/5128/guides)
### Adafruit MACROPAD RP2040 Bare Bones - 3x4 Keys + Encoder + OLED

[Adafruit MACROPAD RP2040 Bare Bones - 3x4 Keys + Encoder + OLED](https://www.adafruit.com/product/5100)
Strap yourself in, we're launching in T-minus 10 seconds...Destination? A new Class M planet called MACROPAD! M here, stands for Microcontroller because this 3x4 keyboard controller features the newest technology from the Raspberry Pi sector: say hello to the RP2040. It's a speedy...
In Stock
[Buy Now](https://www.adafruit.com/product/5100)
[Related Guides to the Product](https://learn.adafruit.com/products/5100/guides)
### Adafruit MacroPad RP2040 Enclosure + Hardware Add-on Pack

[Adafruit MacroPad RP2040 Enclosure + Hardware Add-on Pack](https://www.adafruit.com/product/5103)
Dress up your Adafruit Macropad with PaintYourDragon's fabulous decorative silkscreen enclosure and hardware kit. You get the two custom PCBs that are cut to act as a protective bottom plate and and a mechanically-stabilizing keyboard plate.

Use the included M3 screws to attach the...

In Stock
[Buy Now](https://www.adafruit.com/product/5103)
[Related Guides to the Product](https://learn.adafruit.com/products/5103/guides)
### Kailh Mechanical Key Switches - 10 packs - Cherry MX Compatible

[Kailh Mechanical Key Switches - 10 packs - Cherry MX Compatible](https://www.adafruit.com/product/4996)
For crafting your very own custom keyboard, these **&nbsp;Kailh mechanical key switches** &nbsp;are deeee-luxe!

Come&nbsp;in a pack of 10 switches, plenty to make a small keyboard, or grab a few packs to build a full keyboard.

- Use these with our&nbsp;<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4996)
[Related Guides to the Product](https://learn.adafruit.com/products/4996/guides)
### Translucent Keycaps for MX Compatible Switches - 10 pack

[Translucent Keycaps for MX Compatible Switches - 10 pack](https://www.adafruit.com/product/4956)
Get ready&nbsp;to clacky to your heart's content. Here is a 10 pack of translucent keycaps for your next mechanical keyboard or [NeoKey](https://www.adafruit.com/?q=neokey&sort=BestMatch) project. Snap 'em onto a&nbsp; **Cherry MX or compatible...**

In Stock
[Buy Now](https://www.adafruit.com/product/4956)
[Related Guides to the Product](https://learn.adafruit.com/products/4956/guides)
### Clear DSA Keycaps for MX Compatible Switches - 10 pack

[Clear DSA Keycaps for MX Compatible Switches - 10 pack](https://www.adafruit.com/product/5013)
Get ready&nbsp;to clacky to your heart's content. Here is a 10 pack of clear transparent&nbsp;DSA keycaps for your next mechanical keyboard or&nbsp;[NeoKey](https://www.adafruit.com/?q=neokey&sort=BestMatch)&nbsp;project. Snap 'em onto any&nbsp; **Cherry MX or...**

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/5013)
[Related Guides to the Product](https://learn.adafruit.com/products/5013/guides)

## Related Guides

- [Adafruit MacroPad RP2040](https://learn.adafruit.com/adafruit-macropad-rp2040.md)
- [Dragon Drop: a CircuitPython Game for MacroPad](https://learn.adafruit.com/dragon-drop-a-circuitpython-game-for-macropad.md)
- [Minecraft Turbopad](https://learn.adafruit.com/minecraft-turbopad.md)
- [MacroPad 2FA TOTP Authentication Friend](https://learn.adafruit.com/macropad-2fa-totp-authentication-friend.md)
- [MacroPad Braille Keycaps](https://learn.adafruit.com/macropad-braille-keycaps.md)
- [AdaBox 019](https://learn.adafruit.com/adabox019.md)
- [Scrambled Number Security Keypad](https://learn.adafruit.com/scrambled-number-security-keypad.md)
- [Ableton Live MacroPad Launcher](https://learn.adafruit.com/ableton-live-macropad-launcher.md)
- [MacroPad Remote Procedure Calls over USB to Control Home Assistant](https://learn.adafruit.com/macropad-remote-procedure-calls-over-usb-to-control-home-assistant.md)
- [An Introduction to RP2040 PIO with CircuitPython](https://learn.adafruit.com/intro-to-rp2040-pio-with-circuitpython.md)
- [Keypad and Matrix Scanning in CircuitPython](https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython.md)
- [Using QMK on RP2040 Microcontrollers](https://learn.adafruit.com/using-qmk-on-rp2040-microcontrollers.md)
- [MacroPad Summer Olympics Hotkeys](https://learn.adafruit.com/macropad-olympic-hotkeys.md)
- [CircuitPython 101: State Machines, Two Ways](https://learn.adafruit.com/circuitpython-101-state-machines.md)
- [CLUE Rock, Paper, Scissors Game using Bluetooth](https://learn.adafruit.com/rock-paper-scissors-circuitpython.md)
- [LoRa Signal Bridge with the Feather RP2040 RFM ](https://learn.adafruit.com/lora-signal-bridge-with-the-feather-rp2040-rfm.md)
