home / skills / basedhardware / omi / omi-firmware-patterns

omi-firmware-patterns skill

/.cursor/skills/omi-firmware-patterns

This skill guides firmware pattern usage for Omi devices, enabling BLE audio streaming, codec handling, and reliable device communication.

npx playbooks add skill basedhardware/omi --skill omi-firmware-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
4.0 KB
---
name: omi-firmware-patterns
description: "Firmware C C++ BLE services audio codecs Opus PCM Mu-law nRF ESP32 Zephyr Arduino embedded systems"
---

# Omi Firmware Patterns Skill

This skill provides guidance for working with Omi firmware, including BLE services, audio codecs, and device communication.

## When to Use

Use this skill when:
- Working on firmware code in `omi/` or `omiGlass/`
- Implementing BLE services
- Working with audio codecs (Opus, PCM, Mu-law)
- Debugging device communication issues

## Key Patterns

### BLE Services

#### Audio Streaming Service

**UUID**: `19B10000-E8F2-537E-4F6C-D104768A1214`

**Characteristics**:
- Audio Data: `19B10001-E8F2-537E-4F6C-D104768A1214`
- Codec Type: `19B10002-E8F2-537E-4F6C-D104768A1214`

#### Standard Services

- **Battery Service**: `0x180F` (standard)
- **Device Information Service**: `0x180A` (standard)

### Audio Packet Format

**Header** (3 bytes):
- Bytes 0-1: Packet number (little-endian, 0-65535)
- Byte 2: Index (position within packet)

**Payload**:
- 160 audio samples per packet
- Format depends on codec type

**Fragmentation**: If packet exceeds BLE MTU - 3 bytes, split across multiple notifications

### Codec Types

- `0`: PCM 16-bit, 16 kHz, mono
- `1`: PCM 16-bit, 8 kHz, mono
- `10`: Mu-law, 16 kHz, 8-bit mono
- `11`: Mu-law, 8 kHz, 8-bit mono
- `20`: Opus, 16 kHz, 16-bit mono (default since v1.0.3)

### Zephyr RTOS (Omi Device)

#### BLE Service Definition

```c
BT_GATT_SERVICE_DEFINE(audio_svc,
    BT_GATT_PRIMARY_SERVICE(BT_UUID_AUDIO_SERVICE),
    BT_GATT_CHARACTERISTIC(BT_UUID_AUDIO_DATA,
        BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
        BT_GATT_PERM_READ,
        read_audio_data, NULL, NULL),
);
```

#### Audio Packet Sending

```c
void send_audio_packet(audio_packet_t *packet) {
    uint8_t buffer[3 + sizeof(packet->audio_data)];
    
    // Header
    buffer[0] = packet->packet_number & 0xFF;
    buffer[1] = (packet->packet_number >> 8) & 0xFF;
    buffer[2] = packet->index;
    
    // Audio data
    memcpy(&buffer[3], packet->audio_data, sizeof(packet->audio_data));
    
    // Send via BLE notification
    bt_gatt_notify(conn, &audio_char, buffer, sizeof(buffer));
}
```

### ESP32-S3 (Omi Glass)

#### Arduino Framework

```cpp
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pChar = pService->createCharacteristic(
    AUDIO_DATA_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
);
```

## Common Tasks

### Adding a New BLE Characteristic

1. Define UUID
2. Add to service definition
3. Implement read/write/notify callbacks
4. Handle data format correctly

### Implementing Audio Codec

1. Initialize codec encoder
2. Encode audio samples
3. Format as packet with header
4. Send via BLE notification

### Debugging BLE Issues

1. Check service/characteristic UUIDs
2. Verify packet format (header + payload)
3. Check MTU size and fragmentation
4. Verify codec type negotiation

## Related Documentation

**The `docs/` folder is the single source of truth for all user-facing documentation, deployed at [docs.omi.me](https://docs.omi.me/).**

- **BLE Protocol**: `docs/doc/developer/Protocol.mdx` - [View online](https://docs.omi.me/doc/developer/Protocol)
- **Firmware Compilation**: `docs/doc/developer/firmware/Compile_firmware.mdx` - [View online](https://docs.omi.me/doc/developer/firmware/Compile_firmware)
- **Hardware Docs**: `docs/doc/hardware/` - [View online](https://docs.omi.me/doc/hardware/)
- **Firmware Architecture**: `.cursor/rules/firmware-architecture.mdc`

## Related Cursor Resources

### Rules
- `.cursor/rules/firmware-architecture.mdc` - Firmware system architecture
- `.cursor/rules/firmware-ble-service.mdc` - BLE service implementation
- `.cursor/rules/firmware-audio-codecs.mdc` - Audio codec implementation
- `.cursor/rules/flutter-ble-protocol.mdc` - Flutter BLE integration

### Subagents
- `.cursor/agents/firmware-engineer/` - Uses this skill for firmware development
- `.cursor/agents/flutter-developer/` - Uses this skill for BLE integration

### Commands
- `/flutter-setup` - Uses this skill for firmware setup

Overview

This skill documents practical firmware patterns for Omi devices, focusing on BLE services, audio packet formats, and codec handling for embedded platforms like Zephyr and ESP32. It aims to speed implementation and debugging of audio streaming, codec negotiation, and characteristic design across C/C++ and Arduino frameworks. Use it as a concise reference when integrating audio over BLE in constrained wearables.

How this skill works

The skill describes BLE service definitions and characteristic UUIDs for an audio streaming service, including a compact 3-byte header (packet number + index) followed by codec-specific payloads. It explains how to build and notify audio packets from Zephyr and ESP32 implementations, how fragmentation works when BLE MTU limits are exceeded, and how codec types map to sample formats (PCM, mu-law, Opus). It also outlines typical read/write/notify callback patterns and packet construction for reliable device communication.

When to use it

  • Implementing or extending firmware in omi/ or omiGlass directories for audio streaming
  • Designing BLE services and characteristics for wearable audio devices
  • Selecting and implementing codecs (Opus, PCM, mu-law) for embedded systems
  • Debugging packetization, fragmentation, or MTU-related audio dropouts
  • Integrating mobile/Flutter clients that consume streamed audio via BLE

Best practices

  • Keep the 3-byte header consistent: 2-byte little-endian packet number + 1-byte index
  • Negotiate codec type before streaming and validate codec ID on both ends
  • Respect BLE MTU: fragment packets when payload + 3 header bytes exceed MTU-3
  • Use notify-only characteristics for low-latency audio transfer and read for control info
  • Validate UUIDs and permissions (read, notify) against the device OS expectations

Example use cases

  • Zephyr device sending 160-sample audio packets via bt_gatt_notify with a 3-byte header
  • ESP32-S3 (Arduino) creating an AUDIO_DATA characteristic with notify property for streaming
  • Switching between PCM and Opus codecs based on bandwidth or CPU constraints
  • Debugging BLE audio by verifying packet numbering, index progression, and fragmentation
  • Adding a new characteristic: define UUID, register in service, implement callbacks, ensure correct format

FAQ

What does the 3-byte header represent?

Bytes 0-1 are the little-endian packet number (0-65535) and byte 2 is the index indicating position within a fragmented packet.

How should I handle packets larger than the MTU?

Split the packet across multiple notifications, preserving the header on the first fragment and using the index to reassemble on the receiver.

Which codec is recommended by default?

Opus (codec ID 20) is the default since v1.0.3 for efficient quality at lower bitrates; use PCM or mu-law when simplicity or legacy support is required.