Making Apps
PocketMage apps come in two forms: native apps that ship inside PocketMageOS, and OTA apps that are loaded onto the device later. The two share the same core shape, so this page walks through that shape once and then explains where the paths diverge.
Compiled into the OS and wired into the app dispatch switch.
Compiled separately and loaded into one of four OTA slots at runtime.
Both are three functions: init, handle input, draw.
The basic app shape
Every PocketMage app has the same three jobs, and they map directly to three functions.
- Initialize state - run once when the app opens. Set up whatever the app needs and mark the screen for a redraw.
- Process keyboard input - run on every keypress. Read the key, update app state, and queue a redraw.
- Draw the screen - run when the E-Ink needs to update. Render the current app state.
This pattern is visible in Code/PocketMageOS/include/globals.h (the prototypes) and in the app files under Code/PocketMageOS/src/OS_APPS/.
Start with the template
The app template is your starting point:
It defines the three entry points an OTA app needs:
#include <globals.h>
#if OTA_APP
void APP_INIT() {
// 1. set up app state
}
void processKB_APP() {
// 2. handle a keypress
}
void einkHandler_APP() {
// 3. draw the screen
}
#endif
Building the app step by step
- Decide native vs OTA. If the app belongs to the device experience, make it native. If it is third-party or experimental, make it an OTA app so it can be installed and removed without reflashing the OS.
- Pick the shared helpers. Browse the PocketMage Library before writing anything. Prompts (
textPrompt()), file selection (fileWizardMini()), and timeouts (checkTimeout()) already exist; do not reimplement them. - Wire it into the OS (native only). Add an
AppStateentry, the three prototypes, and theswitchcases marked// ADD APP CASES HEREinPocketMageV3.cpp. Then add a home-screen command if you want it launchable by name. - Test the keyboard path first. Get a keypress into your handler and onto the OLED before worrying about the E-Ink.
- Test the E-Ink path second. Make sure drawing and refresh behave, including fast partial refreshes.
- Check timeout, wake, and save last. Confirm the app resets the idle clock, handles sleep/wake without corrupting state, and saves before exit where it should.
Good app rules
- Keep app state local and explicit; do not scatter globals.
- Use shared helpers instead of duplicating them.
- Keep draw code separate from input code.
- Make exit, save, and sleep behavior obvious.
- For native apps, follow the existing app in
src/OS_APPS/that does the closest job.
Native vs OTA: which path
| Native | OTA | |
|---|---|---|
| Where the code lives | src/OS_APPS/ inside PocketMageOS |
Standalone project using APP_TEMPLATE.cpp |
| How it is built | With the OS (PM_PRODUCTION/PM_BETA) |
With the OTA_APP environment |
| How it ships | Flashed as part of the firmware | Packaged as a .tar and loaded through the app loader |
| Dispatch | Wired into the switch in PocketMageV3.cpp |
Entry points called by the loader |
| Hardware access | PocketMage Library | PocketMage Library |
Read the Native Apps and OTA Apps pages for the details of each path.