Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,33 @@ Alphaboop runs on a [LILYGO T-Display-S3](https://www.lilygo.cc/products/t-displ
- `02 D5 20` — camera is recording;
- `02 D5 00` — camera stopped recording.
- Shows a red `REC` state and a local take timer while recording.
- Keeps the multi-camera dashboard alive when one camera disappears, marks that
slot `DISCONNECTED`, and reconnects it in the background when its BLE address
returns.
- Lets you arm any subset of a two-to-four-camera group. Connected cameras stay
visible even when they are not receiving commands.
- Provides a two-button interface:
- **left**: start REC with a short press; stop with a hold; trigger AF-ON, photo, or C1 in their respective modes;
- **right**: short press selects the next item/mode; hold for 0.5 s cycles display brightness `100% → 50% → MIN`; at 1.5 s the full-screen power countdown begins.
- **left**: tap cycles `ALL → C1 → C2 → C3 → C4`; hold toggles the selected target;
- **right**: tap starts armed cameras; hold stops armed cameras;
- **left, held longer**: at 1.2 s cycles display brightness `100% → 50% → MIN`; at 2 s starts the power-off countdown.
- Shows a large single-camera dashboard or dedicated layouts for two, three, and four cameras.
- Hold the **right** button for 3.5 seconds to sleep. It dims at 0.5 seconds, then uses a full-screen green `POWER OFF 2 → 1`; releasing it cancels. To wake, hold the **left** button for two seconds while the Alphaboop title assembles itself, then the dashboard appears. Reset is still reset. It has paperwork.
- Hold the **left** button for 4 seconds to sleep. Brightness changes at 1.2 seconds, then a full-screen green `POWER OFF 2 → 1` appears after 2 seconds; releasing the button cancels. To wake, hold the **left** button through the 0.7-second star-flight animation. Cold boot gets the same production. Reset is still reset. It has paperwork.

The camera remains the authority. It has earned this privilege.

## Next on the bench
## Choosing command targets

- **Active-camera selector:** keep every linked camera visible, but mark which
slots receive REC, AF-ON, photo, and C1 commands. “All linked” remains the
quick default. Sometimes one camera deserves a quiet moment.
Targets are edited directly on the dashboard:

1. Tap left to move through `ALL`, C1…Cn.
2. Hold left for roughly 0.65–1.2 seconds, then release, to toggle that camera.
3. On `ALL`, holding left arms every camera if any are off, or mutes all if all
are already armed.
4. Tap or hold right for REC start/stop without leaving the dashboard.

An armed camera keeps that setting through a temporary disconnect. Zero
targets is valid and sends nothing. Sometimes every camera deserves a quiet
moment.

## Hardware

Expand All @@ -51,8 +65,8 @@ No extra LED or wiring is needed for the current display-tally prototype. The bo
1. On the camera, enable **Bluetooth Remote Control**. Sony moves menu labels between bodies and firmware versions, because stability is overrated.
2. Put the camera into Bluetooth remote pairing mode when Alphaboop asks for a connection.
3. Power Alphaboop.
4. Choose the number of camera slots with the right button, then confirm with the left button.
5. Wait for the device list, select a Sony camera with the right button, and connect with the left button.
4. Choose the number of camera slots with the left button, then confirm with the right button.
5. Wait for the device list, select a Sony camera with the left button, and connect with the right button.

The board deliberately does **not** auto-connect on boot. A remote should not decide which camera is in charge of your shoot.

Expand Down Expand Up @@ -84,7 +98,8 @@ The helper defaults to `/dev/cu.usbmodem2101`. Computers contain variety. Adjust

## Remote controls

Alphaboop uses Sony's BLE Remote Control service:
Alphaboop's front-panel UI deliberately exposes REC only. The underlying Sony
BLE Remote Control service also contains these commands for diagnostics:

| Control | Action |
| --- | --- |
Expand All @@ -103,6 +118,13 @@ For the full observed packet map and the important distinction between a button
- The confirmed recording feedback is from an ILCE-7M4. Other camera bodies and firmware versions may differ.
- Multi-camera operation is implemented but should be treated as **experimental** until verified with the exact number and model mix you plan to use.
- BLE currently exposes reliable recording, focus-lock, and shutter-state notifications observed during testing. It does **not** provide confirmed AF/MF mode, exposure settings, timecode, card status, or live view.
- `FF02` is normally notification-only. Alphaboop attempts an initial and
periodic read only when a camera explicitly advertises read support. Until a
valid `02 D5` packet arrives, the UI shows an unknown REC state instead of
inventing standby.
- The take timer is local, not camera timecode. A `~` prefix (or `FROM LINK` on
the single-camera screen) means Alphaboop joined a recording already in
progress and can only count from the moment it learned about it.
- Do not write random values to Sony's other BLE services. Some appear related to app pairing, Wi-Fi provisioning, or power. Curiosity is valuable. Camera recovery menus are less so.

Wi-Fi is a separate future transport, not a secret BLE button. See [Wi-Fi feasibility](sony-tally/docs/wifi-feasibility.md).
Expand All @@ -114,6 +136,8 @@ sony-tally/
src/main.cpp firmware
include/TFTSetup.h T-Display-S3 display pin configuration
docs/ble-capabilities.md verified BLE findings and command map
docs/control-design-v2.md two-button and reconnect behaviour contract
docs/revision-2026-07-29.md regression review and remaining hardware tests
docs/wifi-feasibility.md Wi-Fi research and boundaries
tools/ serial diagnostics
work/SonyBleProbe.swift macOS BLE probe; read-only by default
Expand Down
20 changes: 20 additions & 0 deletions sony-tally/docs/ble-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ recording state changes, not merely an acknowledgement that a button command
was sent. The tally firmware must always use this notification as its source
of truth.

### Initial-state limitation

`FF02` is normally advertised as `Notify`, not `Read`. Public implementations
subscribe to it; they do not expose a safe “tell me the current REC state”
command on `FF01`. Alphaboop checks the characteristic properties at runtime
and performs an initial/periodic read only if that particular camera explicitly
allows it.

If no snapshot notification arrives after subscribing, the initial REC state
is unknown. This matters when the remote joins a camera that was already
recording:

- the UI must show an unknown state until a `02 D5` packet arrives;
- a timer started after joining an existing recording is marked approximate;
- the real elapsed take duration and camera timecode cannot be reconstructed
from the FF remote service.

The local timer is useful tally information. It is not camera timecode wearing
a small hat.

What this service does **not** expose in public research or our tests:

- current AF/MF mode;
Expand Down
118 changes: 118 additions & 0 deletions sony-tally/docs/control-design-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Alphaboop control design v2

This document is the implementation contract for the multi-camera controls.
The tested pre-change firmware is preserved by the
`v0.2.0-multicam-tested` Git tag.

## Physical controls

The labels follow the buttons' positions on the front of the T-Display-S3.

| Context | Left button | Right button |
| --- | --- | --- |
| Camera count | Next option | Select |
| Camera discovery | Next device | Connect/select |
| Dashboard | Tap: next target; medium hold: toggle target; long hold: DIM/power | Tap: REC start; hold: REC stop |
| Any powered-on screen | At 1.2 s: DIM; at 2 s: power-off countdown; at 4 s: sleep | REC only on dashboard |
| Deep sleep | Hold through the 0.7-second animation to wake | No action |

The left-button timeline deliberately has separate windows: a tap is shorter
than 0.65 seconds, target toggle happens on release between 0.65 and 1.2
seconds, and reaching 1.2 seconds enters the device-level DIM/power path.

## Selecting command targets

All configured cameras remain visible. `armed` is independent of `connected`:

- armed + connected: receives commands;
- unarmed + connected: monitored, but receives no command;
- armed + disconnected: remains selected and automatically receives commands
again after reconnecting;
- unarmed + disconnected: remains visible and quiet.

Target selection stays on the dashboard:

1. Tap left to cycle `ALL → C1 → C2 → C3 → C4 → ALL`.
2. Hold left for roughly 0.65–1.2 seconds, then release, to toggle the
highlighted camera.
3. Holding on `ALL` arms all when any are off, or mutes all when all are on.

Zero armed cameras is allowed. An action then reports `NO TARGETS` and sends
nothing. The default after camera selection is all cameras armed.

## REC semantics

REC is not sent as a blind group toggle:

- a short right press sends REC only to armed, connected cameras whose known
state is not recording;
- a held right press sends REC only to armed, connected cameras whose known
state is recording.

`FF02 / 02 D5` remains the source of truth. A command being transmitted does
not make the UI red.

## Disconnect and reconnect

After the initial set of slots has reached the dashboard, the dashboard is
sticky. Losing one camera never returns the whole device to discovery.

- The disconnected row becomes grey and says `DISCONNECTED`.
- Other cameras remain controllable.
- Background scanning looks for the saved BLE address.
- Reconnection is serialized and rate-limited.
- A recovered camera returns to the same slot and preserves its armed state.

## Initial recording state and timer limits

The firmware subscribes to `FF02` and also attempts an initial/periodic read
only when the camera advertises the characteristic as readable.

Sony's public FF remote profile is normally notification-only. It provides
recording state changes but no query command and no camera timecode. Therefore:

- a notification received after connection can establish the current REC
state;
- if the camera does not emit a snapshot, the initial state remains unknown;
- a take started by Alphaboop gets an exact local elapsed timer;
- a take already running before connection can only get an approximate local
timer beginning at the first observed REC notification;
- the actual camera timecode requires a different control plane such as the
supported Wi-Fi/Camera Remote SDK path.

The UI must never imply that a locally counted timer is camera timecode.

## Unified startup animation

Cold boot and deep-sleep wake use the same 0.7-second, code-rendered 8-bit
sequence:

1. stars accelerate from the centre into short perspective streaks;
2. the small title approaches on the fixed vertical centre line;
3. without stopping or changing X, the title flies upward into the exact
header position of the next screen;
4. the remaining UI draws without clearing that final frame.

Deep-sleep wake requires the left button to remain held for the whole
animation. Cold boot plays the same sequence without the hold requirement.
Frames are rendered through a TFT sprite so animation does not depend on
full-screen clears visible to the user.

## Hardware acceptance checklist

Run this before merging the branch into the stable release:

1. Cold boot and deep-sleep wake show the same animation; an early release
during wake returns to sleep.
2. On the count and discovery screens, left moves and right confirms.
3. Connect two or more cameras. On the dashboard, tap left to select and hold
left to create C1-only, C1+C3, none, and all target sets.
4. Verify right tap/hold starts and stops only armed slots.
5. Turn off one camera while another is recording. The dashboard and remaining
controls must stay alive; the lost slot must say `DISCONNECTED`.
6. Turn that camera back on. It must reconnect into its original slot without
changing its armed state.
7. Connect Alphaboop while a camera is already recording. Record whether FF02
provides a snapshot, is readable, or remains unknown; keep the serial log.
8. Hold left through DIM and cancel the power countdown by releasing it, then
complete the four-second hold and wake again with left.
58 changes: 58 additions & 0 deletions sony-tally/docs/revision-2026-07-29.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Firmware revision — 2026-07-29

This is the regression review performed after the first four-camera field test.

## Corrected

- Removed the front-panel `AF-ON`, `PHOTO`, `C1`, and mode carousel. The
production UI now spends both buttons on target selection and REC.
- Replaced the startup title's mixed coordinates and curved path with one
continuously scaled bitmap travelling only on the screen's vertical centre
line. It approaches, passes the centre, and reaches the real header without
changing X.
- Restored DIM and power-off to the left-button hold timeline: target toggle
occupies the medium-release window, DIM begins at 1.2 seconds, the countdown
at 2 seconds, and sleep at 4 seconds. The right button remains REC-only.
- Restored footer labels after the DIM toast disappears. The toast previously
overlapped the top pixels of the right-hand label.
- Added a 15-second connection timeout. A security or GATT attempt can no
longer occupy the only connection slot forever.
- Stop the asynchronous scan before copying the selected advertisement and
reserve the device list capacity. This reduces the chance of a scan callback
invalidating data while a connection begins.
- Kept REC start and stop state-aware: start skips known-recording cameras;
stop skips known-stopped cameras. Mixed groups therefore converge instead of
blindly toggling in opposite directions.

## Rechecked

- Losing one camera does not leave the dashboard.
- Disconnected cameras remain grey, retain their armed state, and reconnect by
BLE address.
- Commands are filtered by both `armed` and `ready`.
- FF02 `02 D5` remains the only authority that turns the UI red.
- Timer refreshes redraw only timer/row regions, not the whole display.
- Wake requires the left button through the animation, then waits for release
before accepting REC input.
- Releasing left cancels the power countdown.

## Protocol limits, not firmware defects

- FF02 is normally notification-only. A camera may not reveal whether it was
already recording when Alphaboop connects.
- The displayed duration is a local timer, not Sony timecode.
- Four BLE REC commands are sequential and close together, but they are not
frame-accurate synchronization.

## Hardware regression still required

1. Observe the complete title path on the real 170 × 320 panel.
2. Test the left tap/medium-hold/DIM/power timeline and the right REC tap/hold.
3. Build target sets `C1`, `C1+C3`, none, and all.
4. Start a mixed group where one camera is already recording.
5. Power-cycle one camera and confirm automatic return to its original slot.
6. Leave one camera unavailable for more than 15 seconds and verify the other
cameras remain controllable.

The code has passed compilation and static state-flow review. Cameras retain
the final vote. They usually insist.
Loading