Skip to main content

Technical Documentation

Low-level technical details for SimpleGo development, debugging, and porting.


Table of Contents

  1. Build Environment
  2. Project Structure
  3. Hardware Abstraction Layer
  4. Module Architecture
  5. Configuration System
  6. Memory Architecture
  7. Cryptographic Implementation
  8. Network Stack
  9. Performance Characteristics
  10. Debugging
  11. Error Handling
  12. Porting Guide
  13. References

Build Environment

Required Tools

ToolVersionPurpose
ESP-IDF5.5.2+Development framework for ESP32 targets
Python3.8+Build scripts, tools
CMake3.16+Build system
Git2.xVersion control
Ninja1.10+Build backend (optional, faster)

Installation (Windows)

# Install ESP-IDF using Espressif installer
# Download from: https://dl.espressif.com/dl/esp-idf/

# After installation, use ESP-IDF PowerShell or CMD
# Default path: C:\Espressif\

Installation (Linux/macOS)

# Clone ESP-IDF
mkdir -p ~/esp
cd ~/esp
git clone -b v5.5.2 --recursive https://github.com/espressif/esp-idf.git

# Install tools
cd esp-idf
./install.sh esp32s3

# Set up environment (add to .bashrc/.zshrc)
. ~/esp/esp-idf/export.sh

Build Commands

CommandDescription
idf.py buildCompile project
idf.py flash -p COM6Flash to device
idf.py monitor -p COM6Serial monitor (115200 baud)
idf.py flash monitor -p COM6Flash and monitor
idf.py menuconfigConfiguration menu
idf.py cleanClean build artifacts
idf.py fullcleanFull clean (remove build dir)
idf.py sizeBinary size analysis
idf.py size-componentsSize per component
idf.py reconfigureRegenerate build files

Build Targets

TargetCommandDescription
ESP32-S3idf.py set-target esp32s3LilyGo T-Deck Plus/Pro, T-Lora Pager
ESP32-S2idf.py set-target esp32s2Future support
NativeSee SDL2 HALDesktop testing

Project Structure

simplex_client/
├── main/ # Main application component
│ ├── CMakeLists.txt # Component build configuration
│ ├── Kconfig.projbuild # Project-specific Kconfig
│ ├── main.c # Entry point
│ │
│ ├── hal/ # HAL interface headers
│ │ ├── hal_common.h # Common types, error codes
│ │ ├── hal_display.h # Display abstraction
│ │ ├── hal_input.h # Input abstraction
│ │ ├── hal_storage.h # Storage abstraction
│ │ ├── hal_network.h # Network abstraction
│ │ ├── hal_audio.h # Audio abstraction
│ │ └── hal_system.h # System abstraction
│ │
│ ├── include/ # Protocol headers
│ │ ├── smp_types.h # Core type definitions
│ │ ├── smp_crypto.h # Cryptographic functions
│ │ ├── smp_network.h # Network functions
│ │ ├── smp_parser.h # Protocol parser
│ │ ├── smp_peer.h # Peer connection
│ │ ├── smp_contacts.h # Contact management
│ │ ├── smp_ratchet.h # Double Ratchet
│ │ ├── smp_handshake.h # X3DH handshake
│ │ ├── smp_queue.h # Queue management
│ │ ├── smp_x448.h # X448 operations
│ │ └── smp_utils.h # Utility functions
│ │
│ └── *.c # Implementation files

├── devices/ # Device-specific implementations
│ ├── t_deck_plus/
│ │ ├── config/
│ │ │ └── device_config.h # Pin mappings, hardware config
│ │ └── hal_impl/
│ │ ├── hal_display.c # ST7789V driver
│ │ ├── hal_input.c # Keyboard, trackball, touch
│ │ ├── hal_audio.c # I2S audio
│ │ ├── hal_storage.c # NVS, SD card
│ │ ├── hal_network.c # WiFi
│ │ └── hal_system.c # AXP2101 power management
│ │
│ ├── t_deck_pro/
│ │ └── ... # Similar structure
│ │
│ ├── t_lora_pager/
│ │ └── ... # Similar structure
│ │
│ └── template/ # Template for new devices
│ └── ...

├── components/ # External components
│ ├── wolfssl/ # X448 cryptography
│ └── lvgl/ # Graphics library (planned)

├── docs/ # Documentation
│ ├── ARCHITECTURE.md
│ ├── SECURITY_MODEL.md
│ ├── TECHNICAL.md
│ ├── BUILD_SYSTEM.md
│ ├── ADDING_NEW_DEVICE.md
│ ├── hardware/ # Hardware documentation
│ └── release-info/ # Release notes

├── CMakeLists.txt # Root CMake configuration
├── Kconfig # Root Kconfig (optional)
├── sdkconfig.defaults # Default configuration values
├── partitions.csv # Partition table
├── README.md
├── CHANGELOG.md
├── ROADMAP.md
└── LICENSE

Hardware Abstraction Layer

The HAL provides a unified interface for device-specific hardware, enabling single codebase for multiple platforms.

HAL Architecture

┌─────────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (Protocol, UI - device independent) │
└───────────────────────────┬─────────────────────────────────────┘

┌───────────────────────────▼─────────────────────────────────────┐
│ HAL Interface Layer │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Display │ │ Input │ │ Storage │ │ Network │ ... │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└───────────────────────────┬─────────────────────────────────────┘

┌───────────────────────────▼─────────────────────────────────────┐
│ Device Implementation Layer │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ T-Deck Plus │ │ T-Deck Pro │ │ T-Lora Pager│ ... │
│ │ ESP32-S3 │ │ ESP32-S3 │ │ ESP32-S3 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘

HAL Interfaces

hal_common.h

// Error codes
typedef enum {
HAL_OK = 0,
HAL_ERROR,
HAL_TIMEOUT,
HAL_BUSY,
HAL_NOT_SUPPORTED,
HAL_INVALID_PARAM,
HAL_NO_MEMORY
} hal_err_t;

// Logging macros
#define HAL_LOGE(tag, fmt, ...) ESP_LOGE(tag, fmt, ##__VA_ARGS__)
#define HAL_LOGW(tag, fmt, ...) ESP_LOGW(tag, fmt, ##__VA_ARGS__)
#define HAL_LOGI(tag, fmt, ...) ESP_LOGI(tag, fmt, ##__VA_ARGS__)
#define HAL_LOGD(tag, fmt, ...) ESP_LOGD(tag, fmt, ##__VA_ARGS__)

hal_display.h

// Initialize display hardware
hal_err_t hal_display_init(void);

// Flush buffer to display (LVGL callback compatible)
hal_err_t hal_display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
const void *color_data);

// Backlight control (0-100%)
hal_err_t hal_display_set_backlight(uint8_t brightness);

// Display capabilities
typedef struct {
uint16_t width;
uint16_t height;
uint8_t color_depth; // Bits per pixel
bool has_backlight;
bool has_touch; // Integrated touch
} hal_display_info_t;

hal_err_t hal_display_get_info(hal_display_info_t *info);

hal_input.h

// Input event types
typedef enum {
HAL_INPUT_KEY_PRESS,
HAL_INPUT_KEY_RELEASE,
HAL_INPUT_TOUCH_DOWN,
HAL_INPUT_TOUCH_UP,
HAL_INPUT_TOUCH_MOVE,
HAL_INPUT_ENCODER_CW,
HAL_INPUT_ENCODER_CCW,
HAL_INPUT_ENCODER_CLICK,
HAL_INPUT_TRACKBALL
} hal_input_type_t;

typedef struct {
hal_input_type_t type;
union {
char key; // For keyboard
struct { int16_t x, y; } touch; // For touch/trackball
int8_t delta; // For encoder
};
uint32_t timestamp;
} hal_input_event_t;

// Initialize input hardware
hal_err_t hal_input_init(void);

// Register callback for input events
typedef void (*hal_input_callback_t)(hal_input_event_t *event);
hal_err_t hal_input_register_callback(hal_input_callback_t callback);

// Poll for input (alternative to callback)
hal_err_t hal_input_poll(hal_input_event_t *event, uint32_t timeout_ms);

// Input capabilities
typedef struct {
bool has_keyboard;
bool has_touch;
bool has_trackball;
bool has_encoder;
uint8_t num_buttons;
} hal_input_info_t;

hal_err_t hal_input_get_info(hal_input_info_t *info);

hal_storage.h

// NVS operations
hal_err_t hal_nvs_init(void);
hal_err_t hal_nvs_open(const char *namespace, hal_nvs_handle_t *handle);
hal_err_t hal_nvs_set_blob(hal_nvs_handle_t handle, const char *key,
const void *data, size_t len);
hal_err_t hal_nvs_get_blob(hal_nvs_handle_t handle, const char *key,
void *data, size_t *len);
hal_err_t hal_nvs_erase_key(hal_nvs_handle_t handle, const char *key);
hal_err_t hal_nvs_commit(hal_nvs_handle_t handle);
hal_err_t hal_nvs_close(hal_nvs_handle_t handle);

// Filesystem operations (for devices with SD card)
hal_err_t hal_fs_init(void);
hal_err_t hal_fs_open(const char *path, const char *mode, hal_file_t *file);
hal_err_t hal_fs_read(hal_file_t file, void *buf, size_t len, size_t *read);
hal_err_t hal_fs_write(hal_file_t file, const void *buf, size_t len);
hal_err_t hal_fs_close(hal_file_t file);

// Storage info
typedef struct {
bool has_nvs;
bool has_sd_card;
bool has_internal_fs;
uint32_t nvs_size;
uint32_t sd_capacity; // 0 if no SD
} hal_storage_info_t;

hal_err_t hal_storage_get_info(hal_storage_info_t *info);

hal_network.h

// WiFi operations
hal_err_t hal_wifi_init(void);
hal_err_t hal_wifi_connect(const char *ssid, const char *password);
hal_err_t hal_wifi_disconnect(void);
hal_err_t hal_wifi_get_status(hal_wifi_status_t *status);

// Network events
typedef enum {
HAL_NET_EVENT_CONNECTED,
HAL_NET_EVENT_DISCONNECTED,
HAL_NET_EVENT_GOT_IP,
HAL_NET_EVENT_LOST_IP
} hal_net_event_t;

typedef void (*hal_net_callback_t)(hal_net_event_t event);
hal_err_t hal_net_register_callback(hal_net_callback_t callback);

// Network capabilities
typedef struct {
bool has_wifi;
bool has_ethernet;
bool has_cellular;
bool has_lora;
} hal_network_info_t;

hal_err_t hal_network_get_info(hal_network_info_t *info);

hal_audio.h

// Audio output
hal_err_t hal_audio_init(void);
hal_err_t hal_audio_play_tone(uint32_t frequency, uint32_t duration_ms);
hal_err_t hal_audio_play_buffer(const int16_t *samples, size_t count);
hal_err_t hal_audio_set_volume(uint8_t volume); // 0-100%

// Audio capabilities
typedef struct {
bool has_speaker;
bool has_buzzer;
bool has_microphone;
uint32_t sample_rate;
} hal_audio_info_t;

hal_err_t hal_audio_get_info(hal_audio_info_t *info);

hal_system.h

// Power management
hal_err_t hal_system_init(void);
hal_err_t hal_system_sleep(hal_sleep_mode_t mode);
hal_err_t hal_system_get_battery(uint8_t *percent, bool *charging);
hal_err_t hal_system_power_off(void);

// System information
typedef struct {
uint32_t free_heap;
uint32_t min_free_heap;
uint32_t uptime_ms;
int8_t temperature; // Celsius, if available
uint16_t vbat_mv; // Battery voltage in mV
} hal_system_status_t;

hal_err_t hal_system_get_status(hal_system_status_t *status);

// Watchdog
hal_err_t hal_watchdog_init(uint32_t timeout_ms);
hal_err_t hal_watchdog_feed(void);

Device Configuration

Each device has a device_config.h defining hardware specifics:

// Example: T-Deck Plus device_config.h

#ifndef DEVICE_CONFIG_H
#define DEVICE_CONFIG_H

// Device identification
#define DEVICE_NAME "T-Deck Plus"
#define DEVICE_VENDOR "LilyGo"
#define DEVICE_MCU "ESP32-S3"

// Display configuration
#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 240
#define DISPLAY_DRIVER ST7789V
#define DISPLAY_SPI_HOST SPI2_HOST
#define DISPLAY_PIN_MOSI GPIO_NUM_41
#define DISPLAY_PIN_SCLK GPIO_NUM_40
#define DISPLAY_PIN_CS GPIO_NUM_12
#define DISPLAY_PIN_DC GPIO_NUM_11
#define DISPLAY_PIN_RST GPIO_NUM_42
#define DISPLAY_PIN_BL GPIO_NUM_46

// Keyboard configuration
#define KEYBOARD_I2C_ADDR 0x55
#define KEYBOARD_I2C_PORT I2C_NUM_0
#define KEYBOARD_PIN_SDA GPIO_NUM_18
#define KEYBOARD_PIN_SCL GPIO_NUM_8
#define KEYBOARD_PIN_INT GPIO_NUM_47

// Trackball configuration
#define TRACKBALL_I2C_ADDR 0x0A
#define TRACKBALL_PIN_INT GPIO_NUM_3

// Touch configuration
#define TOUCH_I2C_ADDR 0x14
#define TOUCH_PIN_INT GPIO_NUM_16
#define TOUCH_PIN_RST GPIO_NUM_21

// Audio configuration
#define AUDIO_I2S_PORT I2S_NUM_0
#define AUDIO_PIN_BCLK GPIO_NUM_7
#define AUDIO_PIN_LRCK GPIO_NUM_5
#define AUDIO_PIN_DOUT GPIO_NUM_6

// Power management (AXP2101)
#define PMU_I2C_ADDR 0x34
#define PMU_PIN_INT GPIO_NUM_4

// SD Card
#define SD_SPI_HOST SPI3_HOST
#define SD_PIN_MOSI GPIO_NUM_41
#define SD_PIN_MISO GPIO_NUM_38
#define SD_PIN_SCLK GPIO_NUM_40
#define SD_PIN_CS GPIO_NUM_39

// Capability flags
#define HAS_KEYBOARD 1
#define HAS_TRACKBALL 1
#define HAS_TOUCH 1
#define HAS_SPEAKER 1
#define HAS_SD_CARD 1
#define HAS_BATTERY 1
#define HAS_LORA 0 // Optional module

#endif // DEVICE_CONFIG_H

Module Architecture

Protocol Modules

ModuleFilePurposeLines
Typessmp_types.hStructures, constants~80
Globalssmp_globals.cGlobal state~25
Utilssmp_utils.cBase64, encoding~100
Cryptosmp_crypto.cEd25519, X25519~80
X448smp_x448.cX448 with wolfSSL~150
Networksmp_network.cTLS/TCP I/O~160
Contactssmp_contacts.cContact + NVS~380
Parsersmp_parser.cAgent Protocol~260
Peersmp_peer.cPeer connection~220
Ratchetsmp_ratchet.cDouble Ratchet~400
Handshakesmp_handshake.cX3DH, HELLO~350
Queuesmp_queue.cSMPQueueInfo~150
Mainmain.cEntry point~350
Total~2700

Module Dependencies

main.c
├── smp_network.c
│ ├── smp_crypto.c
│ └── smp_utils.c
├── smp_parser.c
│ ├── smp_contacts.c
│ │ └── smp_utils.c
│ └── smp_types.h
├── smp_peer.c
│ ├── smp_network.c
│ └── smp_handshake.c
│ ├── smp_ratchet.c
│ │ ├── smp_x448.c
│ │ └── smp_crypto.c
│ └── smp_queue.c
└── smp_globals.c

Configuration System

Kconfig Structure

SimpleGo uses ESP-IDF's Kconfig system for compile-time configuration.

main/Kconfig.projbuild
├── Device Selection
│ ├── T-Deck Plus
│ ├── T-Deck Pro
│ ├── T-Lora Pager
│ ├── Raspberry Pi
│ └── Custom
├── SimpleGo Core
│ ├── Max contacts
│ ├── Max messages
│ ├── Message length
│ └── Auto-reconnect
├── Network Configuration
│ ├── WiFi SSID
│ ├── WiFi Password
│ ├── SMP Server
│ └── SMP Port
├── UI Configuration
│ ├── Theme
│ ├── Animations
│ └── Indicators
├── Security Configuration
│ ├── PIN required
│ ├── PIN length
│ ├── Auto-lock
│ └── Wipe on failed
├── Power Management
│ ├── Sleep enable
│ ├── Sleep timeouts
│ └── Battery saver
└── Debug Options
├── Debug logging
├── Log crypto
└── Log network

Accessing Configuration

All Kconfig values are available as CONFIG_* macros:

#include "sdkconfig.h"

// WiFi credentials
const char *ssid = CONFIG_SIMPLEGO_WIFI_SSID;
const char *pass = CONFIG_SIMPLEGO_WIFI_PASSWORD;

// Device selection
#if defined(CONFIG_SIMPLEGO_DEVICE_T_DECK_PLUS)
#include "devices/t_deck_plus/config/device_config.h"
#elif defined(CONFIG_SIMPLEGO_DEVICE_T_DECK_PRO)
#include "devices/t_deck_pro/config/device_config.h"
#endif

// Feature checks
#if CONFIG_SIMPLEGO_DEBUG_LOG
ESP_LOGD(TAG, "Debug: %s", message);
#endif

sdkconfig.defaults

Default values applied on first build:

# Target
CONFIG_IDF_TARGET="esp32s3"

# Flash
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y

# PSRAM
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y

# TLS 1.3
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y

# Stack size
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

Memory Architecture

ESP32-S3 Memory Map

┌─────────────────────────────────────────────────────────────┐
│ Flash (16 MB) │
├─────────────────────────────────────────────────────────────┤
│ 0x00000000 ┌─────────────────────────────────────────┐ │
│ │ Bootloader (32 KB) │ │
│ 0x00008000 ├─────────────────────────────────────────┤ │
│ │ Partition Table (4 KB) │ │
│ 0x00009000 ├─────────────────────────────────────────┤ │
│ │ NVS (24 KB) │ │
│ 0x0000F000 ├─────────────────────────────────────────┤ │
│ │ PHY Init (4 KB) │ │
│ 0x00010000 ├─────────────────────────────────────────┤ │
│ │ Application (up to 4 MB) │ │
│ │ │ │
│ 0x00410000 ├─────────────────────────────────────────┤ │
│ │ Storage / SPIFFS (remaining) │ │
│ │ │ │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ SRAM (512 KB) │
├─────────────────────────────────────────────────────────────┤
│ IRAM (Instruction) │ 128 KB │ Fast code execution │
│ DRAM (Data) │ 320 KB │ Variables, heap │
│ RTC Memory │ 16 KB │ Deep sleep retention │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ PSRAM (8 MB) │
├─────────────────────────────────────────────────────────────┤
│ Heap extension │ Used for large allocations │
│ Display buffers │ LVGL frame buffers │
│ Message storage │ Contact/message database │
└─────────────────────────────────────────────────────────────┘

Memory Allocation Strategy

Data TypeLocationReason
StackDRAMFast access required
Crypto keys (temporary)DRAMSecurity, fast zeroing
Display buffersPSRAMLarge size (150+ KB)
Message databasePSRAMVariable size
WiFi buffersDRAMDMA requirements
TLS contextDRAMPerformance

Heap Usage Monitoring

// Check available heap
size_t free_heap = esp_get_free_heap_size();
size_t min_free = esp_get_minimum_free_heap_size();

ESP_LOGI(TAG, "Free heap: %d, Min free: %d", free_heap, min_free);

// PSRAM check
size_t free_psram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
ESP_LOGI(TAG, "Free PSRAM: %d", free_psram);

Typical Memory Usage

ComponentDRAMPSRAM
FreeRTOS~15 KB-
WiFi stack~40 KB-
TLS context~40 KB-
Application~20 KB-
Display buffer-~150 KB
Free~180 KB~7.5 MB

Cryptographic Implementation

Library Selection

AlgorithmLibraryReason
Ed25519libsodiumWell-audited, standard
X25519libsodiumWell-audited, standard
X448wolfSSLOnly library with ESP32 support
AES-GCMmbedTLSHardware acceleration
SHA-512mbedTLSHardware acceleration
HKDFmbedTLSStandard implementation

X448 Implementation Notes

wolfSSL X448 outputs keys in reverse byte order. SimpleGo includes correction:

// wolfSSL outputs little-endian, SimpleX expects big-endian
void reverse_bytes(uint8_t *buf, size_t len) {
for (size_t i = 0; i < len / 2; i++) {
uint8_t tmp = buf[i];
buf[i] = buf[len - 1 - i];
buf[len - 1 - i] = tmp;
}
}

// After wolfSSL X448 operation:
reverse_bytes(shared_secret, 56);

Key Derivation

// X3DH Key Derivation
// info: "SimpleXX3DHKey1"
// salt: 64 zero bytes
hkdf_sha512(shared_secret, sizeof(shared_secret),
salt_zeros, 64,
"SimpleXX3DHKey1", 15,
output, 96);

// Root KDF
// info: "SimpleXRootRatchet"
hkdf_sha512(dh_output, 56,
current_root_key, 32,
"SimpleXRootRatchet", 18,
output, 64); // 32 new root + 32 chain key

// Chain KDF
// info: "SimpleXChainRatchet"
hkdf_sha512(chain_key, 32,
NULL, 0, // No salt
"SimpleXChainRatchet", 19,
output, 80); // 16 header IV + 32 msg key + 16 msg IV + 16 next chain

Performance Benchmarks (ESP32-S3 @ 240MHz)

OperationTime
Ed25519 keygen~3 ms
Ed25519 sign~3 ms
Ed25519 verify~6 ms
X25519 keygen~1 ms
X25519 DH~1 ms
X448 keygen~15 ms
X448 DH~15 ms
AES-256-GCM (1 KB)~0.3 ms
SHA-512 (1 KB)~0.2 ms
HKDF-SHA512~0.5 ms

Network Stack

Connection Flow

┌─────────────┐
│ WiFi Connect│
└──────┬──────┘


┌─────────────┐ ┌─────────────────────────────────┐
│ DNS Resolve │────►│ smp1.simplexonflux.com → IP │
└──────┬──────┘ └─────────────────────────────────┘


┌─────────────┐
│ TCP Connect │────► Port 5223
└──────┬──────┘


┌─────────────┐ ┌─────────────────────────────────┐
│ TLS 1.3 │────►│ ChaCha20-Poly1305 cipher suite │
│ Handshake │ │ Certificate verification │
└──────┬──────┘ └─────────────────────────────────┘


┌─────────────┐ ┌─────────────────────────────────┐
│ SMP Handshake────►│ Version negotiation │
│ │ │ Server key exchange │
└──────┬──────┘ └─────────────────────────────────┘


┌─────────────┐
│ Ready │
└─────────────┘

TLS Configuration

// mbedTLS configuration for SimpleX
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_4); // TLS 1.3

// Cipher suites (TLS 1.3)
int ciphersuites[] = {
MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
0
};
mbedtls_ssl_conf_ciphersuites(&conf, ciphersuites);

Buffer Sizes

BufferSizePurpose
SSL Input16 KBTLS record reception
SSL Output16 KBTLS record transmission
SMP Command4 KBProtocol command buffer
SMP Response16 KBProtocol response buffer

Performance Characteristics

Timing Summary

OperationDuration
Cold boot to WiFi~3 sec
WiFi reconnect~1 sec
TLS handshake~500 ms
SMP handshake~200 ms
X3DH + Ratchet init~50 ms
Send message (E2E)~30 ms
Receive message (E2E)~25 ms

Power Consumption (T-Deck Plus)

StateCurrent
Active (display on, WiFi)~150 mA
Active (display off, WiFi)~80 mA
Light sleep~2 mA
Deep sleep~10 μA

Battery Life Estimates (2000 mAh)

Usage PatternDuration
Continuous use~10 hours
Intermittent (5 min/hour)~3 days
Mostly sleep, hourly check~7 days

Debugging

Log Levels

LevelMacroTypical Use
ErrorESP_LOGECritical failures
WarningESP_LOGWUnexpected but handled
InfoESP_LOGINormal operation
DebugESP_LOGDDevelopment details
VerboseESP_LOGVDetailed tracing

Per-Module Log Control

// In code
esp_log_level_set("SMP_NETWORK", ESP_LOG_DEBUG);
esp_log_level_set("SMP_CRYPTO", ESP_LOG_VERBOSE);
esp_log_level_set("wifi", ESP_LOG_WARN);

// Or via menuconfig
// Component config → Log output → Default log verbosity

Debug Output Example

I (1234) SMP_NETWORK: Connecting to smp1.simplexonflux.com:5223
D (1234) SMP_NETWORK: DNS resolved: 123.45.67.89
D (1456) SMP_NETWORK: TCP connected
I (1890) SMP_NETWORK: TLS handshake complete
D (1890) SMP_NETWORK: Cipher: TLS_CHACHA20_POLY1305_SHA256
I (2100) SMP: SMP handshake complete, version 8
D (2100) SMP_CRYPTO: X3DH initiated
D (2150) SMP_CRYPTO: Root key derived
I (2200) SMP: E2E connection established

Common Debug Techniques

// Hex dump
ESP_LOG_BUFFER_HEX_LEVEL(TAG, buffer, len, ESP_LOG_DEBUG);

// Stack high water mark
UBaseType_t stack = uxTaskGetStackHighWaterMark(NULL);
ESP_LOGI(TAG, "Stack remaining: %d", stack);

// Heap fragmentation
heap_caps_print_heap_info(MALLOC_CAP_DEFAULT);

Error Handling

ESP-IDF Error Codes

CodeNameMeaning
0x0000ESP_OKSuccess
0x0101ESP_ERR_NO_MEMOut of memory
0x0102ESP_ERR_INVALID_ARGInvalid argument
0x0103ESP_ERR_INVALID_STATEInvalid state
0x0104ESP_ERR_INVALID_SIZEInvalid size
0x0105ESP_ERR_NOT_FOUNDNot found

mbedTLS Error Codes

CodeMeaning
-0x7780SSL handshake failure
-0x7200Certificate verification failed
-0x0010GCM authentication failed
-0x0042Bad input data
-0x0044Buffer too small

Error Handling Pattern

esp_err_t result = some_operation();
if (result != ESP_OK) {
ESP_LOGE(TAG, "Operation failed: %s (0x%x)",
esp_err_to_name(result), result);
// Cleanup
return result;
}

Porting Guide

Adding New Device

  1. Create device directory:

    devices/new_device/
    ├── config/
    │ └── device_config.h
    └── hal_impl/
    ├── hal_display.c
    ├── hal_input.c
    └── ...
  2. Add to Kconfig:

    config SIMPLEGO_DEVICE_NEW_DEVICE
    bool "New Device Name"
    help
    Description of device.
  3. Implement HAL functions for each interface.

  4. Test:

    idf.py menuconfig  # Select new device
    idf.py build flash monitor

See ADDING_NEW_DEVICE.md for detailed instructions.


References

ESP-IDF

Cryptography

SimpleX Protocol

Hardware


Document History

VersionDateChanges
2.0January 2026Complete rewrite for HAL architecture
1.0January 2026Initial technical documentation