# Fruit Jam IRC Client in CircuitPython

## Overview

![IRC chat channel with incoming messages saying "Hi!" and "Welcome to IRC chat on CircuitPython"](https://cdn-learn.adafruit.com/assets/assets/000/138/580/medium800thumb/circuitpython_irc_recording.jpg?1753814103 )

IRC ([Internet Relay Chat](https://en.wikipedia.org/wiki/IRC)) was created in 1988 by Jarkko Oikarinen. It gained popularity throughout the 1990s, before waning in the 2000s as other more centralized social and chat networks grew into the behemoths they are today.

IRC and similar chat rooms offered a way to directly interact with people all over the world in real time. For many folks, this window to the rest of the world gave them an outlet for creativity and social interaction with like-minded people.&nbsp;

While the usage of IRC has declined, there are still servers running, with many active channels on them. This project allows you to join and chat on IRC servers from your Adafruit Fruit Jam device.&nbsp;

## Parts

This project requires an Adafruit Fruit Jam, an HDMI cable, a DVI compatible display, a USB keyboard, and a USB C cable to power the Fruit Jam.

### Adafruit Fruit Jam - Mini RP2350 Computer

[Adafruit Fruit Jam - Mini RP2350 Computer](https://www.adafruit.com/product/6200)
We were catching up on a recent [hackaday hackchat with eben upton](https://hackaday.io/event/202122-raspberry-pi-hack-chat-with-eben-upton)&nbsp;and learned some fun facts: such as the DVI hack for the RP2040 was inspired by <a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/6200)
[Related Guides to the Product](https://learn.adafruit.com/products/6200/guides)
![Angled shot of assembled mini computer PCB with plate.](https://cdn-shop.adafruit.com/640x480/6200-10.jpg)

### Mini Chiclet Keyboard - USB Wired - Black

[Mini Chiclet Keyboard - USB Wired - Black](https://www.adafruit.com/product/1736)
Add a good quality, slim keyboard to your&nbsp;Raspberry Pi, Beagle Bone Black, or other single-board-computer with this sleek black chiclet keyboard. It's a full QWERTY keyboard with a USB cable and is compatible with all operating systems. We tried many keyboards to find one that felt...

In Stock
[Buy Now](https://www.adafruit.com/product/1736)
[Related Guides to the Product](https://learn.adafruit.com/products/1736/guides)
![Angled shot of a Black woman's silver-blue manicured hands on a slim, black keyboard.](https://cdn-shop.adafruit.com/640x480/1736-04.jpg)

### HDMI Cable - 1 meter

[HDMI Cable - 1 meter](https://www.adafruit.com/product/608)
Connect two HDMI devices together with this basic HDMI cable. It has nice molded grips for easy installation, and is 1 meter long (about 3 feet). This is a HDMI 1.3 cable.

We're now stocking a very fancy Official Raspberry Pi cable with overmolding and a Pi logo. Please note...

In Stock
[Buy Now](https://www.adafruit.com/product/608)
[Related Guides to the Product](https://learn.adafruit.com/products/608/guides)
![Official Raspberry Pi HDMI Cable - 1 meter](https://cdn-shop.adafruit.com/640x480/608-03.jpg)

### USB Type A to Type C Cable - approx 1 meter / 3 ft long

[USB Type A to Type C Cable - approx 1 meter / 3 ft long](https://www.adafruit.com/product/4474)
As technology changes and adapts, so does Adafruit. This&nbsp;&nbsp; **USB Type A to Type C** cable will help you with the transition to USB C, even if you're still totin' around a USB Type A hub, computer or laptop.

USB C is the latest industry-standard connector for...

In Stock
[Buy Now](https://www.adafruit.com/product/4474)
[Related Guides to the Product](https://learn.adafruit.com/products/4474/guides)
![Angled shot of a coiled black, USB-C to USB-A cable.](https://cdn-shop.adafruit.com/640x480/4474-02.jpg)

### 7" Display 1280x800 (720p) IPS + Speakers - HDMI/VGA/NTSC/PAL

[7" Display 1280x800 (720p) IPS + Speakers - HDMI/VGA/NTSC/PAL](https://www.adafruit.com/product/1667)
Yes, this is an adorable small HDMI television with incredibly high resolution **and built in 3W stereo speakers**! We tried to get the smallest possible HDMI/VGA display with high-res, high-contrast visibility. The visible display measures only 7" (17.8cm) diagonal, and the TFT comes...

In Stock
[Buy Now](https://www.adafruit.com/product/1667)
[Related Guides to the Product](https://learn.adafruit.com/products/1667/guides)
![Front view of assembled and powered on HDMI 4 Pi - 7" Display. The monitor displays a desktop background with a raspberry logo.](https://cdn-shop.adafruit.com/640x480/1667-00.jpg)

# Fruit Jam IRC Client in CircuitPython

## Install 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.

Warning: Please use the latest release of 10.x or higher for the Fruit Jam. Also use the latest libraries for the best functionality.

[Download the latest version of CircuitPython for this board via circuitpython.org](https://circuitpython.org/board/adafruit_fruit_jam/)
 **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)

![reset and boot highlighted](https://cdn-learn.adafruit.com/assets/assets/000/138/708/medium800/adafruit_products_Resetboot.jpg?1754331128 )

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 RP2350 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 **RP2350**.

&nbsp;

Drag the **adafruit-circuitpython-_boardname_-_language_-_version_.uf2** file to **RP2350.**

![install_circuitpython_on_rp2350_Screenshot_2024-09-11_111518.png](https://cdn-learn.adafruit.com/assets/assets/000/132/253/medium640/install_circuitpython_on_rp2350_Screenshot_2024-09-11_111518.png?1726067809)

![install_circuitpython_on_rp2350_Screenshot_2024-09-11_111742.png](https://cdn-learn.adafruit.com/assets/assets/000/132/254/medium640/install_circuitpython_on_rp2350_Screenshot_2024-09-11_111742.png?1726067866)

The **RP2350** drive will disappear and a new disk drive called **CIRCUITPY** will appear.

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

![install_circuitpython_on_rp2350_Screenshot_2024-09-11_111843.png](https://cdn-learn.adafruit.com/assets/assets/000/132/255/medium640/install_circuitpython_on_rp2350_Screenshot_2024-09-11_111843.png?1726067932)

## 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 RP2350. 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 for RP2350](https://cdn-learn.adafruit.com/assets/assets/000/132/526/original/rp2350_flash_nuke.uf2)
# Fruit Jam IRC Client in CircuitPython

## Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of [CircuitPython 8](https://circuitpython.org/downloads), there is support for a **settings.toml** file. This is a file that is stored on your **CIRCUITPY** drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your **code.py** file so you are able to share your code without sharing your credentials.

CircuitPython previously used a **secrets.py** file for this purpose. The **settings.toml** file is quite similar.

Warning: Your **settings.toml** file should be stored in the main directory of your **CIRCUITPY** drive. It should not be in a folder.

## CircuitPython **settings.toml** File

This section will provide a couple of examples of what your **settings.toml** file should look like, specifically for CircuitPython WiFi projects in general.

The most minimal **settings.toml** file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your **settings.toml** , and update:

- `your_wifi_ssid`
- `your_wifi_password`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
```

Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must _also_ include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:

- `your_wifi_ssid`
- `your_wifi_password`
- `your_aio_username`
- `your_aio_key`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"
```

Some projects use different variable names for the entries in the **settings.toml** file. For example, a project might use `ADAFRUIT_AIO_ID` in the place of `ADAFRUIT_AIO_USERNAME`. **If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.**

Warning: Not every project uses the same variable name for each entry in the **settings.toml** file! Always verify it matches the code.

## **settings.toml** File Tips
Here is an example **settings.toml** file.

```auto
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"
```

In a **settings.toml** file, it's important to keep these factors in mind:

- Strings are wrapped in double quotes; ex: `"your-string-here"`
- Integers are _ **not** _ quoted and may be written in decimal with optional sign (`+1`, `-1`, `1000`) or hexadecimal (`0xabcd`).
  - Floats (decimal numbers), octal (`0o567`) and binary (`0b11011`) are not supported.

- Use `\u` escapes for weird characters, `\x` and `\ooo` escapes are not available in **.toml** files
  - Example: `\U0001f44d` for 👍 (thumbs up emoji) and `\u20ac` for € (EUR sign)

- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format

&nbsp;

&nbsp;

When your&nbsp; **settings.toml&nbsp;** file is ready, you can save it in your text editor with the **.toml** &nbsp;extension.

![adafruit_products_dotToml.jpg](https://cdn-learn.adafruit.com/assets/assets/000/117/071/medium640/adafruit_products_dotToml.jpg?1671034293)

## Accessing Your **settings.toml** Information in **code.py**
In your **code.py** file, you'll need to `import` the `os` library to access the **settings.toml** file. Your settings are accessed with the `os.getenv()` function. You'll pass your settings entry to the function to import it into the **code.py** file.

```python
import os

print(os.getenv("test_variable"))
```

![](https://cdn-learn.adafruit.com/assets/assets/000/117/072/medium800/adafruit_products_tomlOutput.jpg?1671034496)

In the upcoming CircuitPython WiFi examples, you'll see how the **settings.toml&nbsp;** file is used for connecting to your SSID and accessing your API keys.

# Fruit Jam IRC Client in CircuitPython

## Code

## CircuitPython Usage

To use the application, you need to update **code.py** with the game program&nbsp;to the **CIRCUITPY** drive.

Thankfully, this can be done in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file.

Connect your board to your computer via a known good data+power USB cable. The board should show up in your File Explorer/Finder (depending on your operating system) as a flash drive named **CIRCUITPY**.

Extract the contents of the zip file, copy the **lib** directory files to **CIRCUITPY/lib**. Copy the **code.py** file to your **CIRCUITPY** drive. The program should self start.

## Drive Structure

After copying the files, your drive should look like the listing below. It can contain other files as well, but must contain these at a minimum.

![IRC Application files and required libraries screenshot](https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/folder-images/Fruit_Jam_Fruit_Jam_IRC_Client.png?raw=true )

## Code

The **code.py** for the IRC Client application is shown below.

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

# Fruit Jam IRC Client in CircuitPython

## Usage

## Add Your&nbsp; **settings.toml** &nbsp;File

As of CircuitPython 8.0.0, there is support for&nbsp;[Environment Variables](https://docs.circuitpython.org/en/latest/docs/environment.html). Environment variables are stored in a&nbsp; **settings.toml** &nbsp;file. Similar to&nbsp; **secrets.py** , the&nbsp; **settings.toml&nbsp;** file separates your sensitive information from your main&nbsp; **code.py** &nbsp;file. Add your&nbsp; **settings.toml** &nbsp;file as described in the&nbsp;[Create Your settings.toml File page](https://learn.adafruit.com/fruit-jam-irc-client-in-circuitpython/create-your-settings-toml-file)&nbsp;earlier in this guide. You'll need to include values for your&nbsp;`CIRCUITPY_WIFI_SSID`&nbsp;and&nbsp;`CIRCUITPY_WIFI_PASSWORD`.&nbsp;

## Configure

You must configure some basic settings in order to use the IRC application:

- `server` - The IRC Server URL that you want to connect to e.g. `irc.libera.chat`
- `port` - The network port to use for the connection. Many IRC servers use `6697` for TLS encrypted connections, and `6667` for clear text connections.
- `username` - The nickname that you want to connect to the server with. This is what other chatters will see next to messages you write.
- `channel` - The channel that you want to join automatically. Join an existing channel like `#adafruit-fruit-jam` or `#python`, or create your own channel for you and your friends. Channels always start with a pound sign.

To configure these items set their values in the `IRC_CONFIG` dictionary near the top of the **code.py** file.

```auto
# Configuration - modify these values as needed
IRC_CONFIG = {
    "server": "irc.libera.chat",  # Example: irc.libera.chat, irc.freenode.net
    # "port": 6667,  # 6667 - clear text
    "port": 6697,  # 6697 - TLS encrypted
    "username": "",
    "channel": "#adafruit-fruit-jam",
}
```

All of the configurations except for `username` have defaults that you can leave if you wish to join the `#adafruit-fruit-jam` channel. You must fill in a `username` value or the code will raise an exception reminding you to do so.

## User Interface
![IRC client application user interface with highlights for: user input line, status bar, chat messages, and server header / welcome message](https://cdn-learn.adafruit.com/assets/assets/000/138/578/medium800/circuitpython_irc_client_interface.png?1753807283 )

When the IRC client first starts up and connects to the server it will show the welcome message and server header information. The bottom bar that is grey with black text is the status bar. Normally it will show your username, the server URL that you're connected to, and the channel name that you have joined. During some operations it will change to give you success/failure or other output about an operation. As you type, your message will appear on the user input line. If you type a message and press enter the message will get sent to the channel. If your message begins with a forward slash&nbsp;`/`, then it will be treated as a command by the application instead of being sent to the server as a chat message.

As new messages are received in the channel, they will be shown beneath the welcome message, they'll start scrolling automatically as necessary. The up and down arrow keys and page up/down keys will scroll the chat so you can see older messages that were received while you were connected, then scroll back to the current time at the bottom.

## Commands

General commands available for all users:

- `/msg [to-user] [message]`: Send a direct message to the specified user. Username and message should be separated by a space.&nbsp;
- `/beep [to-user]`: Send a beep direct message to the specified user. If they have a speaker plugged in it will play a beep sound.
- `/whois [user]`: Run a whois query on the specified username.
- `/join [channel-name]`: Join the specified channel.

Channel admin commands only available to channel operators:

- `/op [user]`: Give the specified user operator privilege in the current channel.
- `/deop [user]`: Remove operator privilege from the specified user in the current channel.
- `/kick [user]`: Kick the specified user from the channel.
- `/ban [user]`: Ban the specified user from the channel.
- `/unban [user]`: Un-ban the specified user from the channel.

# Fruit Jam IRC Client in CircuitPython

## Code Explanation

The code for this project is split into 3 files **code.py** , **irc\_client.py** , and **curses\_irc\_client.py**. Each is responsible for their own part of the work required to make the full usable IRC client application. This page will give a high level explanation of each. The code also contains comments with more details about specific sections and components if you want to go deeper.

## **code.py**

This file is what get launched when CircuitPython runs the application. It is responsible for initializing the hardware that the app uses like the ESP32-C6 co-processor for WiFi access, and the DAC for playing audio. It also creates the `displayio` elements that make up the user interface.

The&nbsp;[Adafruit\_CircuitPython\_ColorTerminal](https://github.com/adafruit/Adafruit_CircuitPython_Color_Terminal) library is used for the main Terminal instance that the interface is drawn into. This library supports colored terminal text using [ANSI color escape codes.](https://en.wikipedia.org/wiki/ANSI_escape_code) The IRC app uses it to have a few different colors to show nicknames of users in the channel, which makes the conversation easier to follow at a glance. At the end of **code.py** it calls the `run_irc_client()` function to launch the curses application.

## **curses\_irc\_client.py**

This file contains the curses application for the IRC client. This layer has a main loop section that gets input from the user and takes action as necessary. It also calls&nbsp;`irc_client.update()` to check for new data that is come in from the server, more on that in the next section. **curses\_irc\_client.py** reads input from the keyboard as you type and enters the message you type on the user input line. When you press enter it's handles the message you have entered passing it off to `irc_client.send_message()` if it is a normal message, or handling it has a command if it starts with a forward slash like `/beep`. During the main loop this will get a page of messages from the `irc_client.message_buffer` and display them on the screen.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Fruit_Jam/Fruit_Jam_IRC_Client/curses_irc_client.py

## **irc\_client.py**

This file contains class which manages the network connection with the IRC server. The higher level code in the curses application will call functions on this class instead of directly interacting with the server. This class could be re-purposed to make a different IRC client program with a different user interface. It provides the&nbsp;`message_buffer` property which will contain a list of lines to show on the display. The higher level code must call the `update()` function from the main loop in order to fetch new messages from the server.

Whenever data is received by the server, it goes into the `process_message()` function to decide how to handle it. Some messages are shown to the user, others are internal server information not shown visually. Others like `PING` require that the client take action in response, which is handled automatically.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Fruit_Jam/Fruit_Jam_IRC_Client/irc_client.py


## Featured Products

### Adafruit Fruit Jam - Mini RP2350 Computer

[Adafruit Fruit Jam - Mini RP2350 Computer](https://www.adafruit.com/product/6200)
We were catching up on a recent [hackaday hackchat with eben upton](https://hackaday.io/event/202122-raspberry-pi-hack-chat-with-eben-upton)&nbsp;and learned some fun facts: such as the DVI hack for the RP2040 was inspired by <a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/6200)
[Related Guides to the Product](https://learn.adafruit.com/products/6200/guides)
### Mini Chiclet Keyboard - USB Wired - Black

[Mini Chiclet Keyboard - USB Wired - Black](https://www.adafruit.com/product/1736)
Add a good quality, slim keyboard to your&nbsp;Raspberry Pi, Beagle Bone Black, or other single-board-computer with this sleek black chiclet keyboard. It's a full QWERTY keyboard with a USB cable and is compatible with all operating systems. We tried many keyboards to find one that felt...

In Stock
[Buy Now](https://www.adafruit.com/product/1736)
[Related Guides to the Product](https://learn.adafruit.com/products/1736/guides)
### HDMI Cable - 1 meter

[HDMI Cable - 1 meter](https://www.adafruit.com/product/608)
Connect two HDMI devices together with this basic HDMI cable. It has nice molded grips for easy installation, and is 1 meter long (about 3 feet). This is a HDMI 1.3 cable.

We're now stocking a very fancy Official Raspberry Pi cable with overmolding and a Pi logo. Please note...

In Stock
[Buy Now](https://www.adafruit.com/product/608)
[Related Guides to the Product](https://learn.adafruit.com/products/608/guides)
### USB Type A to Type C Cable - approx 1 meter / 3 ft long

[USB Type A to Type C Cable - approx 1 meter / 3 ft long](https://www.adafruit.com/product/4474)
As technology changes and adapts, so does Adafruit. This&nbsp;&nbsp; **USB Type A to Type C** cable will help you with the transition to USB C, even if you're still totin' around a USB Type A hub, computer or laptop.

USB C is the latest industry-standard connector for...

In Stock
[Buy Now](https://www.adafruit.com/product/4474)
[Related Guides to the Product](https://learn.adafruit.com/products/4474/guides)
### 7" Display 1280x800 (720p) IPS + Speakers - HDMI/VGA/NTSC/PAL

[7" Display 1280x800 (720p) IPS + Speakers - HDMI/VGA/NTSC/PAL](https://www.adafruit.com/product/1667)
Yes, this is an adorable small HDMI television with incredibly high resolution **and built in 3W stereo speakers**! We tried to get the smallest possible HDMI/VGA display with high-res, high-contrast visibility. The visible display measures only 7" (17.8cm) diagonal, and the TFT comes...

In Stock
[Buy Now](https://www.adafruit.com/product/1667)
[Related Guides to the Product](https://learn.adafruit.com/products/1667/guides)

## Related Guides

- [Using a Keyboard with USB Host](https://learn.adafruit.com/using-a-keyboard-with-usb-host.md)
- [Adafruit Fruit Jam](https://learn.adafruit.com/adafruit-fruit-jam.md)
- [Audio Synthesis with CircuitPython synthio](https://learn.adafruit.com/audio-synthesis-with-circuitpython-synthio.md)
- [Circadian Pi Desk Light](https://learn.adafruit.com/circadian-pi-desk-light.md)
- [MicroPython Basics: How to Load MicroPython on a Board](https://learn.adafruit.com/micropython-basics-how-to-load-micropython-on-a-board.md)
- [Labo Piano Light FX](https://learn.adafruit.com/labo-piano-light-fx.md)
- [Step Switch Party](https://learn.adafruit.com/step-switch-party.md)
- [Hexpad](https://learn.adafruit.com/hexpad.md)
- [PYOA for PyGamer/PyBadge - Adding Cursor Support to CircuitPython](https://learn.adafruit.com/cursor-for-circuitpython.md)
- [Adafruit PyPortal Titano](https://learn.adafruit.com/adafruit-pyportal-titano.md)
- [Edit CircuitPython Code on iOS with Runestone](https://learn.adafruit.com/editing-circuitpython-on-ios-with-runestone.md)
- [MatrixPortal CircuitPython Animated Message Board](https://learn.adafruit.com/matrixportal-circuitpython-animated-message-board.md)
- [Labo RC Car Action Lights](https://learn.adafruit.com/labo-rc-car-underglow.md)
- [Canary Nightlight ](https://learn.adafruit.com/canary-nightlight.md)
- [Make It Shake, Rattle, and Roll: Accelerometer Use](https://learn.adafruit.com/make-it-shake-rattle-and-roll.md)
- [Walkmp3rson: Personal MP3 'Tape' Player](https://learn.adafruit.com/walkmp3rson-personal-mp3-tape-player.md)
- [PyPortal Event Count-Up Clock](https://learn.adafruit.com/pyportal-event-count-up-clock.md)
