Introduction
Precious Blocks is your cute every-day companion.
Place it next to you while you work, take it with you to travel.
It’s clicky arms make for a great fidget toy,
and the collection of offline games is great for a little distraction
or if you need to kill some time.
Precious Block also really enjoy just hanging out together;
it is really good at looking cute doing nothing.
Precious Blocks is entirely open-source,
including the firmware, hardware and optional companion server.
Feel free to build your own block or customize the firmware.
This documentation is split into multiple parts.
- The User Guide is supposed to give you an introduction into how to use the block, and the features available.
- The Tinker Guide gives you an overview over the hardware and how to build your own block.
- The Hacker Guide covers the firmware aspect and how to contribute to it
Feel free to pick the chapters that interest you the most.
You can also use the side menu on the left to jump between chapters
or the search function to find wht you are looking for.
Overview
Precious-Block is desinged to keep you company throughout the day.
Be that keeping you company while you work (it does an amazing job at looking cute on your desk) or as a fidget toy, when you travel or need a distraction.
It comes with muultiple offline-features (including a Clock & Games)
and some online helper tools (i.e. Weather).
Where possible, the internet-connectivity is optional,
allowing you to access cached data on-the-go.
This chapter focuses on the official Precious-Blocks firmware,
introducing you to navigation gestures and the available apps.
Note that the availability of certain features depends on the hardware configuration and settings of your block.

Parts
To better understand the following chapters, it might be helpful to familiarize yourself with the naming of the different component of the block.
On the front of the Precious Block is the Display.
You can interact with the block by pressing or holding the arms on either side.
You can charge your Precious Block by plugging a USB-C cable into the port on the back.
This port also allows you to access debug output or flash firmware files, if you want to.
Both the Boot and the Reset button of the internal microcontroller are exposed on the bottom.
They are especially useful if you want to access bootloader features of the device.
Ideally you should never need to use them, but the Reset button might be handy if the block freezes entirely.
If you want to attach a wrist band, you can easily loop it through the looped holes on the top.
Start Up
When you start the block, it enters sleep mode.
The block will hapilly stay in sleep mode until you decide to wake it up.
Because most parts are asleep in this mode, it also perserves battery life.
You can wake the device by pressing and holding both arms until the screen goes blank.
After releasing the arms, you will be dropped into the menu.
Menu navigation is covered in the upcoming Basic Navigation chapter.
If you spend too much time idle in the top level menu, the block will go back to sleep, as it was when you first powered it up.
Background Jobs
The block will periodically wake itself up from sleep,
to perform background tasks, like updating weather data (if configured).
Whilst performing background tasks, it displays an eyes emoticon.
Basic Navigation
You can use the two arms to interact with your Precious Block.
The available gestures depend on the app you are using.
This chapter gives you a brief overview of how to wake the block
and navigate the menu system.
Specific application specific instructions can be found in the corresponding app sections.
Wake the Block
To wake the block, simply hold both arms until the screen goes blank and the block vibrates.
Then release the arms and you will be launched in to the top-level menu.
Gestures
All applets except the games use the same Gesture system, to make navigation as easy and consistent as possible.
The left arm is responsible for navigating left (or lowering the value),
where as the right arm is used for navigating right (or increasing the value).
Both arms use the same gesture system:
Click the arm once to move into the corresponding direction
or hold the arm and it will continue sending the click event, allowing you to easily move long distances without having to click the arm a bunch.
Besides the single-arm gestures,
there are more gestures available by pressing both arms at the same time.
Pressing and releasing both arms together briefly is used to confirm the current selection.
Pressing both arms for a long period of time (more than 1 second) counts as a long press and is generally used as a back gesture.
Recovering
In an ideal world, the firmware should never panic.
But if it ever should, you should be able to restart the block by pressing one of the arms.
Applets
Applets are apps that can be launched from the menu.
They provide different functioncality, like time, weather or games.
Navigating the Menu
The menu itself is structured into multiple layers to group logically related programs together.
The menu interactions are the same for all layers.
As indicated by the arrows on either side of the screen,
you can use the arms to cycle through the menu entries.
To select a specific entry, you can briefly press both arms and release them.
Nested menus have an additional Back option, indicated by an arrow pointing left.
You can select it, as you would with other menu entries to return to the previous menu.
Clock
The clock applet provides time-related functionality.
It is organized as part of the menu structure and shows the current time and date as a menu entry.
You can navigate off of the clock display using the arms and selecting the other functionality from the other pages.
Timer
The timer applet allows you to select a duration using the number selector.
When you start the countdown, it updates the display until it reaches 0.
Once the timer elapses, the block will start vibrating and the original time will be shown.
Weather
The weather applet fetches current data fram Open Meteo.
The hourly data is stored locally for the next 5 days and updated whenever the block has an active internet connection.
That way you can check the weather when you are on the go.
The applet consists of two pages.
The first page shows a weather indicator symbol and the current temperature.
The second page shows more detailed information about current temperature, wind and precipitation.
You can switch between the pages using the arms. To exit the app press long click both arms.
Games
Precious Block comes with multiple games you can play, when you are on the go or just need a distraction.
Pong
Pong is a single player game, where you control both paddles at the same time.
To do so, the paddles are linked in an inverted configuration.
This means that as one paddle moves up, the other one moves down.
You can move the right paddle up (and left paddle down) by holding the right arm.
To move the right paddle down (and left paddle up) you hold the left arm.
The goal of the game is to bounce the ball of both paddles, without the ball ever touching the left- or rightmost screen edge.
Once you reach the game over screen, you can press any arm to return the menu.
Plane
A FlappyBird inspired game, where you have to navigate a small ball through pipes.
You can flap the bird by pressing both arms at the same time.
When you collide with a tube, the game is over and shows the number of tubes cleared.
The game is designed to be fairly friendly, both in terms of collission detection and with tube spacing.
Overview
This chapter focuses on how you can build your own Precious Block from scratch.
Including materials required and the step to assemble them correctly.
Components
The entire block is made up of readily available materials.
Electronics
- SeeedStudio XIAO ESP32S3 (Plus) & WiFi antenna
- 2 Microswitches (12.8 x 6.5 x 5.8 mm)
- 128x64 SSD1306 OLED with I2C connection
- Adafruit PCF8523 & CR1220 12mm diameter coin cell battery
Components required for assembly:
- Protoboard
- Standoffs
- 7x1 (twice for the microcontroller)
- 4x1 (for the display)
- 5x1 (for the clock)
- Wire
Optionally, you can also wire up a battery for the ESP itself, to use Precious Block on the go (recommended)
- Lithium Battery (3.7V; should not be larger than 3x3x0.5cm)
- 2x 220kOhm Resistors (if you want to be able to read the voltage)
Difference between different Seeed XIAO ESP32 S3 chips
As the name indicates, the Plus chip is slightly more advanced. The differences relevant to this project are listed below. (Details taken from the Seeed Wiki)
| Category | XIAO ESP32S3 | XIAO ESP32S3 Plus |
|---|---|---|
| Flash | 8 MB | 16 MB |
| PSRAM | 8 MB | 8 MB |
| Modem Sleep | 3.8V/25 mA | 3.8V/26.5 mA |
| Deep Sleep | 3.8V/14 µA | 3.8V/69 µA |
| Wifi Power Consumption | ~100 mA | ~85 mA |
The larger flash size on the Plus model is certainly helpful for development work, as debug builds tend to be larger than release versions.
Both chips allow connecting to a rechargeable 3.7V lithium battery.
The current battery state is indicated by a red light, on the chip.
- No battery: Red light turns on when connected and turns off after 30 seconds
- battery fully charged: red light turns of
- battery charging: the red light is blinking
Case
The case is designed using FreeCAD. The project file contains multiple Spreadsheets which are used to make important variables easily adjustable.
- 3D printed front, back & 2 arms
- 8 3x3x3 mm magnet cubes
Assembly
Electronics
TODO: more detailed protoboard guide
Wiring
| Pin | Where |
|---|---|
| GND | OLED GND |
| 3.3V | OLED VCC, Both switches on neutral |
| D4 | OLED SCL |
| D5 | OLED SDA |
| D1 | Left switch |
| D3 | Right switch |
Battery Management
If you want to add the battery to the system, you also have to connect the following pins:
| Pin | Where |
|---|---|
| Bat + (Soldered on back) | + on your Battery |
| Bat - (Soldered on back) | - on your Battery |
Additionally, you’ll want to build a Voltage Dividers, using 2 220kOhm resistors, and connect the following pins:
| Vin | Vout |
|---|---|
| Bat+ | D8 |
Case
Both the front and back have recesses to fit four magnets.
The magnets are used to align the two shell pieces and ensure they stay together.
(Magnets were choosen as they keep the inside accessible should something break)
Start by glueing the magnets to the front
(the orientation doesn’t matter as long as the magnets on the back have the correct orientation).
Once hardended, you can place one magnet on each of the ones you just glued in,
to ensure proper orientation and slide it onto a metalic surface (without flipping it).
Now put some glue on the top and push the magnet into the back with the glue facing down.
(You might have to use a wooden rod to push them down till they reach the bottom.
When the glue is set, the magnets should stay in place and allow the case to snap together.
The front and back of the case also have pins sticking out, which slot into the cutout on the top of the arms.
The arms should be placed with their extended cylinder pointing toward the front, so that they’ll interface with the microswitches.
Dev Environment
The device firmware can be found in the firmware repository.
You can download the source code as a ZIP or simply clone the repository:
git clone "https://codeberg.org/precious-blocks/firmware"
Precious Blocks are built around the ESP32S3 microcontroller,
which uses an Xtensia architecture.
Because the architecture is not supported by upstream Rust (and LLVM),
we have to use the downstream Expressif forks.
If you plan on setting up the build system on your host device,
you can follow the esp32-rs book.
The firmware repo also contains a Dockerfile, which allows you to easily build the project inside a container.
You can use the provided docker/quickaccess file to build the docker container and create aliases, which allow you to cargo, clippy and espflash commands.
source docker/quickaccess
# simply use cargo and espflash as you normally would
# the commands will execute in the container
Once you have set up everything, you can simply use cargo run --release to build and flash the binary to the chip.
Note that you have to wake up the block before being able to flash it, because the serial interface is not available in deep sleep mode.