# Spell Jam App on Fruit Jam

## Overview

![Spell Jam running on the Adafruit Fruit Jam. A USB keyboard, a pair of USB powered speakers, and small DVI compatible display are connected. The display shows the word "microcontroller"](https://cdn-learn.adafruit.com/assets/assets/000/139/282/medium800/circuitpython_spell_jam_hiro_img.png?1756491222 )

Spell Jam is a twist on a classic electronic toy that runs on the Adafruit Fruit Jam. You can type in any word and Spell Jam will say and spell the word out loud from a connected speaker or headphones.

The [Amazon Polly TTS](https://aws.amazon.com/polly/) service is used to download MP3 files of the words, which are then played using the built-in TLV320 DAC on the Fruit Jam. The graphics are a fun nod towards the toy that inspired the project.

https://www.youtube.com/shorts/bwvHL7dwsJ4

## Parts
### 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)

# Spell Jam App on Fruit Jam

## 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)
# Spell Jam App on Fruit Jam

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

# Spell Jam App on Fruit Jam

## AWS Keys

This project utilizes the [Amazon Polly TTS service](https://aws.amazon.com/polly/). In order to use the service you must first [signup for AWS](https://signin.aws.amazon.com/signup?request_type=register). The process is similar to signing up for other internet based services, enter/verify your email and other information and complete the instructions given by the signup pages.

Once your signup is completed, you'll need to get an&nbsp;`AWS_ACCESS_KEY` and `AWS_SECRET_KEY` that will be used to authenticate the connection to AWS Polly. It is **strongly recommended** to create a "sub user" within your AWS account to use specifically for a single purpose like this and lock down its access to only the thing(s) that it needs.

To start, [sign in to the AWS console](https://aws.amazon.com/console/). Then **click on your name** in the top right corner of the page.

When the menu opens click **"Security credentials"** inside of the drop down.

On the **Security Credentials page** , find and click on **"Users"** in the left side navigation under the **"Access management" heading**.

![AWS Console page with user profile name in the upper right corner highlighted](https://cdn-learn.adafruit.com/assets/assets/000/139/219/medium640/circuitpython_aws_console_profile_name.png?1756397205)

![AWS Console drop down menu with "Security Credentials" menu item highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/220/medium640/circuitpython_aws_console_sec_credentials.png?1756397264)

![AWS security and credentials page left navigation with "Users" highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/221/medium640/circuitpython_aws_sec_users.png?1756397484)

Next click on the **"Create User" button** near the top right corner of the page, in the main pane.

When prompted, **enter a username** to use for the access user. I chose "circuitpython\_polly\_user1", but you can use any name you like. Ideally choose something that you'll recognize later when it's listed in the console.

**DO NOT check the box** labeled "Provide user access to the AWS Management Console - _optional_". This option would give the new access user the ability to manage other services, billing and other details of the AWS account. It should only have access to fetch sound files from AWS Polly.

After you enter a username, click the **"Next" button** in the bottom right corner.

![AWS Users page with "Create user" button highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/222/medium640/circuitpython_aws_create_user_button.png?1756397726)

![AWS user details form prompting for a username. The "Provide user access to AWS Management Console" is not checked. There is a next button in the bottom right corner.](https://cdn-learn.adafruit.com/assets/assets/000/139/224/medium640/circuitpython_aws_create_user_username.png?1756398203)

Now to set the permissions on this new access user account.&nbsp;

Choose **"Attach policies directly"** from the choices in the **"Permission options" box**.

Next scroll down to the "Permission policies" box and enter the term **"Polly"** in the search box.

Click the **checkbox next to "AmazonPollyReadOnly"**. The name may be truncated with ellipses.

Once the "AmazonPollyReadOnly" permission is checked, click the **"Next" button** in the bottom right corner.

![AWS Set permissions menu with "Attach policies directly" selected.](https://cdn-learn.adafruit.com/assets/assets/000/139/225/medium640/circuitpython_aws_attach_policies_directly.png?1756398362)

![AWS Permission policies form with "Polly" entered into the search box and "AmazonPollyReadOnly" permission selected with its box checked.](https://cdn-learn.adafruit.com/assets/assets/000/139/227/medium640/circuitpython_aws_permission_policies_polly_readonly.png?1756398669)

The last step to create the user account is to confirm the details entered.

Verify that you are happy with the username.

Ensure that **"AmazonPollyReadOnlyAccess"** is the only thing listed in the **"Permission summary" section**. This account does not need any other permissions beyond that.

When everything looks good, click the **"Create user" button** in the bottom right.

After this is complete, you'll be taken back to a page listing all of the user accounts under your AWS console. You should see the new user account that you just created.

![AWS User details confirmation page showing the username and permissions for the new user account being created. There is a "Create user" button in the bottom right. ](https://cdn-learn.adafruit.com/assets/assets/000/139/228/medium640/circuitpython_aws_create_user_confirmation.png?1756399439)

Now to get the API keys for this new restricted user account.&nbsp;

**Click on the username** in the list of users on the **Users page** under **Access management** in the Security credentials page.

Once you are on the user detail page for the new user, click on the **"Security credentials"** navigation tab in the main pane.

Inside the Security credentials tab, scroll down and find the **"Access keys"** box. Click the **"Create access key" button** inside of it.

![AWS user details page with "Security credentials" navigation tab highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/229/medium640/circuitpython_aws_access_user_sec_credentials.png?1756399954)

![AWS user access keys panel with "Create access key" button highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/230/medium640/circuitpython_aws_user_create_access_key.png?1756400141)

Select the **"Other"** use case from the list of available options.

Scroll down and click the **"Next" button** in the bottom right corner.

Next, you may optionally set a descriptive tag to use with this access key. I chose **"circuitpython polly access"** , you can use anything you like or leave it blank.

Click the **"Create access key" button** once you are satisfied with the tag choice.

![AWS Access key best practices & alternatives menu with "Other" use case selected.](https://cdn-learn.adafruit.com/assets/assets/000/139/231/medium640/circuitpython_aws_access_key_use_case_other.png?1756400333)

![AWS key "Other" use case selected with a "Next" button in the bottom right.](https://cdn-learn.adafruit.com/assets/assets/000/139/232/medium640/circuitpython_aws_access_keys_use_case_next.png?1756400435)

![AWS access key creation form with an optional descriptive tag entered and the "Create access key" button in the bottom right.](https://cdn-learn.adafruit.com/assets/assets/000/139/233/medium640/circuitpython_aws_access_key_tag_and_create_button.png?1756400643)

Finally, it's time to get the access keys needed!

After the access keys are created, you'll be taken to the **Retrieve access keys page** , where you can view/copy your **Access key** and **Secret access key**.&nbsp;

The Spell Jam project will need both of these values. Use the copy buttons to copy them and paste them into your&nbsp; **settings.toml** file under the names `AWS_ACCESS_KEY` and `AWS_SECRET_KEY`. See example below.

![AWS retrieve access keys page with access key and secret access key copy buttons highlighted.](https://cdn-learn.adafruit.com/assets/assets/000/139/234/medium640/circuitpython_aws_retrieve_access_key.png?1756401105)

```auto
AWS_ACCESS_KEY="YOUR_ACCESS_KEY"
AWS_SECRET_KEY="YOUR_SECRET_ACCESS_KEY"
```

# Spell Jam App on Fruit Jam

## Code

## Getting the Program's Files

To use the application, you need to obtain **code.py** with the game program to place on the Fruit Jam **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 **spell\_jam\_assets** directory to **CIRCUITPY/spell\_jam\_assets** directory. Copy the files **code.py** , settings.toml, **aws\_polly.py** , **hmac.py** , **icon.bmp** and **metadata.json** 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.

![CIRCUITPY drive screenshot showing required project files and libraries](https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/folder-images/Fruit_Jam_Fruit_Jam_Spell_Jam.png?raw=true )

## Settings.toml

You must have a **settings.toml** file with the following variables filled in with appropriate values for your network and AWS keys.

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
AWS_ACCESS_KEY="YOUR_ACCESS_KEY"
AWS_SECRET_KEY="YOUR_SECRET_ACCESS_KEY"
```

## Code

The **code.py** for the Spell Jam app is shown below.

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

# Spell Jam App on Fruit Jam

## Code Explanation

## **code.py**

The **code.py** file for this project is responsible for the high level behavior of the app. First, it initializes the `displayio` elements that make up the interface, and the Fruit Jam library which sets up the DAC and other hardware. It uses the `sync_time()` function to get the current time from NTP servers and updates the system time from accordingly, which is required for the AWS authentication.

During the main loop, it polls `sys.stdin` for pressed keys as described in the [USB Keyboard learn guide](https://learn.adafruit.com/using-a-keyboard-with-usb-host/circuitpython#demo-code-sys-dot-stdin-3197510). When the pressed key is a letter, the display is updated. Arrow up/down keys raise and lower the volume. Pressing Enter will fetch the MP3 file for the current word and then start playing it.

After the speech MP3 finishes, the word is spelled aloud one letter at a time by playing the pre-loaded MP3 files located in `spell_jam_assets/letter_mp3s/`. There is one MP3 for each letter of the alphabet, the code loops over the word one letter at a time playing each relevant letter MP3 file. After the spelling, the full word MP3 file is played once more.

If Enter is pressed when no new word has been typed, then the MP3 files for the previous word are played again.

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

## **aws\_polly.py**

This file provides two high level helper functions to download MP3 files from AWS Polly: `text_to_speech_polly_http()` and `text_to_speech_with_ssml()`. Only `text_to_speech_polly_http()` is used by the Spell Jam project. The functions accept a `requests` instance, the desired text to get a speech MP3 for, AWS keys, and some configuration options, which all have defaults used by the Spell Jam project. The `ssml` version of the function is the same, except that it accepts the text to speak in a format called SSML which stands for [Speech Synthesis Markup Language.](https://en.wikipedia.org/wiki/Speech_Synthesis_Markup_Language) It's an XML based format that allows finer grained control over some aspects of the speech.

The majority of the AWS functionality is encapsulated within the `PollyHTTPClient` class. It handles creating authorized requests, and signing them according the the requirements of [AWS Signature Version 4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html). The details of the authentication and request are somewhat gnarly, but if you're curious the code is embedded below.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Fruit_Jam/Fruit_Jam_Spell_Jam/aws_polly.py

## **tts\_aws.py**

This file contains a `WordFetcherTTS` class implementation that uses the **aws\_poly.py** functions above. The object exposes a minimal interface for the **code.py** to make use of. It's possible to change the TTS service from AWS to other cloud TTS providers, or even a local server on your own network running a free TTS model on a Raspberry Pi or PC.&nbsp;[See this playground page](https://adafruit-playground.com/u/retiredwizard/pages/your-own-tts-engine-for-the-fruit-jam-spell-jam-app) for details on setting up a local TTS server and using it with Spell Jam.

[Playground: Custom TTS Engine For Spell Jam App](https://adafruit-playground.com/u/retiredwizard/pages/your-own-tts-engine-for-the-fruit-jam-spell-jam-app)
https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Fruit_Jam/Fruit_Jam_Spell_Jam/tts_aws.py

## **hmac.py**

The AWS signature process requires using a cryptographic function called [HMAC](https://en.wikipedia.org/wiki/HMAC). This file contains an implementation of that function for **aws\_polly.py** use. The file was originally open sourced as part of the [micropython-lib project](https://github.com/micropython/micropython-lib/blob/master/python-stdlib/hmac/hmac.py).

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Fruit_Jam/Fruit_Jam_Spell_Jam/hmac.py

# Spell Jam App on Fruit Jam

## Usage

https://www.youtube.com/shorts/bwvHL7dwsJ4

When Spell Jam first launches, it will take a moment to initialize the WiFi and other necessary hardware, as well as sync the time on the device using NTP. When it's ready, the interface will be shown with the prompt "Type a word" visible in the 14-segment text in the center.

Type any word that you want using the connected USB keyboard. The text on the screen will update as you type. When your word is complete press Enter. The NeoPixels on the Fruit Jam will turn yellow while it makes the request to AWS Polly and downloads an MP3 file of the word.&nbsp;

![Spell Jam running on Fruit Jam connected to mini display, speakers, and a USB keyboard. "python" is typed on the keyboard and appears on the display.](https://cdn-learn.adafruit.com/assets/assets/000/139/354/medium800thumb/wireless_spelljam_typing.jpg?1756840228 )

When the download is complete, the NeoPixels will turn green and the downloaded MP3 file will be played out of the connected speakers or headphones. After that, each letter within the word will be played individually from the preloaded files inside of the&nbsp;`spell_jam_assets/letter_mp3s/` folder included in the project files. Afterward, the downloaded MP3 of the full word will be played again.

If you want to hear the last word again, simply press Enter without typing a new word. The word and spelling will be repeated. You can repeat it as many times as you want by continuing to press Enter.

Pressing the up and down arrow keys will raise and lower the volume.

## Optional Custom Sounds

Spell Jam can also play custom sounds optionally based on keywords. For instance you can download an MP3 of a cow mooing and set it to play when "cow" is entered into the app. To set this up create a **words/** directory inside of **spell\_jam\_assets/** and place audio files inside of **words/** in either .wav or .mp3 format. Each audio file is named with its keyword, so **cow.mp3** would play if the user entered "cow".

## Issues

If you have issues, ensure you entered your WiFi and AWS credentials in **settings.toml**. Accessing the internet time and Amazon Polly requires the Fruit Jam to connect to internet sites.


## 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)
- [PyPortal Hurricane Tracker](https://learn.adafruit.com/pyportal-hurricane-tracker.md)
- [Rotary Phone Dial Keypad](https://learn.adafruit.com/rotary-phone-dial-keypad.md)
- [Match3 Game on the Fruit Jam and  Adafruit Metro RP2350](https://learn.adafruit.com/match3-game-on-metro-rp2350.md)
- [SNES Mouse to USB HID with CircuitPython](https://learn.adafruit.com/snes-mouse-to-usb-hid-with-circuitpython.md)
- [A CLI in CircuitPython](https://learn.adafruit.com/a-cli-in-circuitpython.md)
- [MagTag Twitter Display](https://learn.adafruit.com/magtag-twitter-display.md)
- [Stomp-Reactive Light Up Slippers](https://learn.adafruit.com/stomp-reactive-light-up-slippers.md)
- [CircuitPython BLE Libraries on Any Computer](https://learn.adafruit.com/circuitpython-ble-libraries-on-any-computer.md)
- [Feather RP2350 Audio Reactive Video Synth](https://learn.adafruit.com/feather-rp2350-audio-reactive-video-synth.md)
- [Getting Started With Steven Universe](https://learn.adafruit.com/getting-started-with-steven-universe.md)
- [CircuitPython Rotary Trinkey Brightness Crank](https://learn.adafruit.com/circuitpython-rotary-trinkey-brightness-crank.md)
- [Adafruit TMC2209 Stepper Motor Driver Breakout Board](https://learn.adafruit.com/adafruit-tmc2209-stepper-motor-driver-breakout-board.md)
- [Adafruit WINC1500 WiFi Shield for Arduino](https://learn.adafruit.com/adafruit-winc1500-wifi-shield-for-arduino.md)
- [Adafruit IoT Button with NeoPixel BFF](https://learn.adafruit.com/adafruit-iot-button-with-neopixel-bff.md)
- [Faderwave Synthesizer](https://learn.adafruit.com/faderwave-synthesizer.md)
