# TC66C Transport and Payload Working Note

This note translates the reviewed `TC66` manuals and the current app code into an implementation-oriented working reference.

## Scope

This note is about `TC66C`, not `TC66`.

Reason:

- the manuals say `TC66` is USB-only
- the iOS and Android apps are `TC66C`-only
- the current app code has a separate `TC66C` BLE path

## Evidence Sources

Primary sources used for this note:

- `Documentation/Research Resources/Specifications/TC66 Manuals Working Summary.md`
- `USB Meter/Model/Meter.swift`
- `USB Meter/Model/BluetoothRadio.swift`
- `USB Meter/Model/BluetoothSerial.swift`

## Current App Assumptions

The current app already treats `TC66C` as a different protocol family than `UM25C` / `UM34C`.

Confirmed from code:

- model enum contains a dedicated `TC66C` case
- `TC66C` is mapped to radio type `PW0316`
- peripheral names `TC66C` and `PW0316` are both recognized as `TC66C`
- the scan path includes services `FFE0` and `FFE5` for this radio family

## BLE Transport Assumptions In Code

The current code assumes the following BLE transport for `TC66C`:

- notify characteristic: service `FFE0`, characteristic `FFE4`
- write characteristic: service `FFE5`, characteristic `FFE9`

This differs from the `UM` family path already documented elsewhere:

- `UM25C` / `UM34C` use `FFE0` / `FFE1`
- `TC66C` uses a separate `PW0316`-style path in the current app

## Request / Response Shape

The current app polls `TC66C` using ASCII commands.

Confirmed command surface already used by the app:

- measurement snapshot request: `bgetva\r\n`
- next page: `bnextp\r\n`
- previous page: `blastp\r\n`
- rotate screen: `brotat\r\n`

Expected snapshot response size in current code:

- `192` bytes

Important implication:

- the app assumes fixed-length snapshot framing for `TC66C`
- this is not derived from the manuals directly; it comes from the existing reverse-engineered implementation

## Encrypted Snapshot Structure

The current parser decrypts the `192`-byte response with `AES ECB`.

Observed implementation details:

- the app uses a hard-coded `32`-byte AES key
- the decrypted payload is treated as three `64`-byte packets
- those packets are referred to as `pac1`, `pac2`, and `pac3`

Each packet is validated as:

- first four bytes are ASCII header `pac1`, `pac2`, or `pac3`
- bytes `0...59` are CRC-covered
- CRC seed is `0xFFFF`
- stored CRC is little-endian at offset `60`

If any of the three packets fail validation, the app rejects the snapshot as invalid.

## Field Map Currently Parsed By The App

The offsets below are offsets inside the decrypted packet blocks, not offsets into the encrypted `192`-byte BLE frame.

### `pac1`

- offset `4`, size `4`: candidate model name as ASCII
- offset `8`, size `4`: candidate firmware version as ASCII
- offset `12`, size `4`: candidate serial number, little-endian `UInt32`
- offset `44`, size `4`: candidate boot count, little-endian `UInt32`
- offset `48`, size `4`: voltage, raw / `10000`
- offset `52`, size `4`: current, raw / `100000`
- offset `56`, size `4`: power, raw / `10000`

Confidence:

- voltage / current / power are high-confidence because the app actively uses them
- model / firmware / serial / boot count are medium-confidence because they exist as commented decoding hints in code, not active UI fields

### `pac2`

- offset `4`, size `4`: load resistance, raw / `10`
- offset `8`, size `4`: data group `0` accumulated charge, raw / `1000`
- offset `16`, size `4`: data group `1` accumulated charge, raw / `1000`
- offset `48`, size `4`: data group `0` accumulated energy, raw / `1000`
- offset `56`, size `4`: data group `1` accumulated energy, raw / `1000`
- offset `24`, size `4`: temperature sign flag, `1` means negative in current parser
- offset `28`, size `4`: temperature magnitude
- offset `32`, size `4`: `D+` voltage, raw / `100`
- offset `36`, size `4`: `D-` voltage, raw / `100`

Confidence:

- load resistance, temperature, `D+`, and `D-` are high-confidence in the sense that the app displays them
- exact data-group interpretation is medium-confidence because the parser only fills groups `0` and `1`

### `pac3`

- no fields are currently decoded from `pac3`

This is a major open area for further reverse engineering.

## Mismatch Between Manuals And Current App

### 1. Device pages vs exposed controls

The manuals describe many on-device capabilities:

- offline recording
- protocol detection
- trigger / decoy
- system settings
- information page
- simple mode

The current app only implements these direct `TC66C` controls:

- request live snapshot
- previous page
- next page
- rotate screen

Not implemented in the current app for `TC66C`:

- clear data group
- select data group
- brightness change
- screen timeout change
- recording-threshold change

The code explicitly guards these setters off for `TC66C`.

### 2. Data-group coverage

The manuals discuss data groups, but the current parser only populates two groups for `TC66C`.

Working interpretation:

- either `TC66C` exposes only two remotely readable groups in the current snapshot layout
- or the current parser only decodes the first two groups and leaves the rest unknown

This needs verification from captures or app analysis.

### 3. Bluetooth scope

The manuals are clear that:

- `TC66` is not a Bluetooth target
- `TC66C` uses BLE for mobile apps

This matches the current app architecture and strengthens confidence that `TC66C` should remain a separate transport family in the codebase.

## Working State Model For `TC66C`

The current implementation implicitly models at least these state domains:

- connection state
- active device page
- instantaneous electrical measurements:
  - voltage
  - current
  - power
  - current direction is documented in manuals but not currently decoded into a separate published field
- accumulated data:
  - charge
  - energy
  - at least two data groups
- cable and charger context:
  - load resistance
  - `D+`
  - `D-`
  - quick-charge related behavior
- environment:
  - temperature
- device metadata:
  - firmware version candidate
  - serial number candidate
  - boot count candidate

## Practical Implications For Implementation

### Keep `TC66C` separate from UM-family decoding

- transport is different
- request commands are different
- payload framing is different
- encryption is different

The code already reflects this split and the manuals support it.

### Treat `pac3` as the highest-value unknown

We already have enough for a basic live meter UI from `pac1` and `pac2`.

What is still likely hidden:

- additional device settings
- active page information
- recording configuration
- protocol-detection or trigger state
- more complete data-group information

### Do not over-trust current group mapping

The app's `TC66C` parser only maps two groups, while the manuals talk more generally about groups and offline storage.

Until verified, avoid hard-coding a stronger assumption than:

- `TC66C` snapshots currently expose at least two group-like accumulators in our parser

### Separate manual truth from protocol truth

The manuals are strong for:

- feature list
- UX flow
- transport family split
- required `PD / CC pull-down` behavior

The manuals are not enough for:

- exact BLE field map
- command framing completeness
- full payload offsets

## Suggested Verification Priorities

1. confirm `FFE0/FFE4` notify and `FFE5/FFE9` write behavior against real `TC66C` hardware
2. capture and archive one or more raw `192`-byte encrypted snapshots
3. decrypt and annotate unknown bytes in `pac3`
4. verify whether more than two data groups exist in BLE snapshots
5. determine whether current device page is present in payload
6. verify whether recording state and interval are exposed remotely
7. promote candidate metadata fields in `pac1` from code comments to confirmed fields

## Recommended Next Notes

The next helpful artifacts for the repository would be:

- a raw `TC66C` sample-capture note in `Payload Notes`
- a byte-offset map for `pac1`, `pac2`, and `pac3`
- an implementation checklist for exposing currently undocumented `TC66C` features in the UI
