# PowerFC Tuner Implementation Notes

Current app version: `V2.13`

## V2.13 Autotune Filtering Notes

- Fuel autotune now accepts samples only after a 500 ms same-cell dwell period and a 250 ms accepted-sample interval.
- Accepted samples are gated by AFR range, throttle threshold, knock threshold, and TPS/RPM/load stability.
- Per-cell AFR buffers reject outliers more than 20% from the median, use a trimmed mean for displayed AFR, and use median AFR error ratio for correction.
- Base Map corrections are capped by operating region: idle/light-load cells are most conservative, high-load cells are capped tighter than cruise cells.
- A cell is not corrected repeatedly from the same confidence window; it needs another full sample window before another automatic correction.

## V2.12 Cell Lock Notes

- Editable map grids now support right-click locking and unlocking selected cells.
- Locked cells are saved with the session and block direct edits, +/- changes, context-menu add/paste/interpolate, AFR grid bulk changes, copy-to-base updates, and live autotune writes.
- Manual attempts to edit locked cells show a lock warning popup.

## V2.11 Written Cell Sample Clearing Notes

- Successful Base Map writes now clear logged AFR, knock, and sample-count cells for the cells that had calculated base-map changes, even when manual writing outside an active autotune run.
- Successful Write All Maps operations also clear the same applied Base Map logging cells so old AFR averages cannot feed the next correction cycle.

## V2.10 Session State And Logged Data Notes

- The app now writes a best-effort `last_session.pfcsession` snapshot on close and offers to reload it on startup. This includes the existing session fields for autotune mode, thresholds, TPS calibration, AUX setup, target AFR, logged data, and working maps.
- Minimum Water Temp is now consistently treated as Fahrenheit and the label now says `(F)`.
- Logged Data sampling no longer rebuilds the grid on each sample; the bound table cell updates in place, with derived views updating only the active cell.
- Copy Changes to Working Base Map now overlays calculated cells onto the existing working base map instead of replacing the full map with a sparse changes table.

## V2.09 Session AFR Target And Logged Data Notes

- Re-reading all maps from the PFC now preserves the current Target AFR table instead of replacing it with a blank AFR shell.
- Session saves commit any active map cell edits first so the latest Target AFR cell edit is included even if focus has not left the cell.
- Live monitoring no longer selects and scrolls the Logged Data grid for the live tracer cell. The trace text still updates, while the grid refresh is throttled during monitoring to reduce tab-switch freezes.

## V2.08 Logging And Autotune Arming Notes

Logging and autotuning can now be armed regardless of current throttle position. The configured minimum throttle remains a sample gate: live samples are recorded and applied only when TPS is at or above the threshold. Live fuel autotune also defers heavy Base Map grid refreshes while monitoring is active so tab changes stay responsive during high-rate sampling.

## V2.07 Map Tracer Scope Notes

Live monitoring no longer selects/highlights cells on the Tuning tab maps. The app still resolves the current RPM/load trace cell for logging, autotuning, and the Live Monitors readout, but the visual tracer is limited to Logged Data instead of the editable Tuning grids.

## V2.06 Popup Settings Serial Handoff Notes

Settings popup windows now pause and await live monitoring before opening the COM port for popup-level read/write actions, then resume monitoring afterward when it was running before the command. This matches the main settings tab behavior and prevents PowerFC Tuner from colliding with its own live monitor on the same COM port.

## V2.05 Live Data Stability Notes

Displayed AFR now uses a light exponential smoothing filter to reduce gauge jitter while preserving raw AFR for logging and autotuning decisions. Live `F0` frames must pass checksum validation before they can update RPM, speed, or other live values. Short transient ACC/accessory-mode frames such as `Unexpected length byte 0x01` are ignored during live polling instead of flashing the live-data status.

## V2.04 Tuning Step Notes

The `+` and `-` buttons on all Tuning map tabs now adjust selected cells by `0.1`. Non-fuel tuning grids keep one decimal place visible so tenth-step changes are not rounded away in the UI.

## V2.03 Injector Label Notes

Fuel & Inj Correction now labels the injector lag column as `Lag(mS)` instead of `Offset` in the Injectors section.

## V2.02 Function Select Layout Notes

Function Select now displays FC Box Custom Features to the right of the main Function Select switches. Tuner String is hidden until Tuner String Enabled is checked, and the IGN Anti Lag Retard / INJ Anti Lag fields are hidden until Anti Lag Switch (SW3) is checked.

## V2.01 Live Aux Monitor Notes

The Live Monitors page now includes an Aux Monitors section with one row for each Wite analog input (`AN1` through `AN4`). Each row shows the configured input name, configured units, and the calibrated live value produced by the same voltage-to-value conversion path used for AFR.

## V2.00 Fuel Autotune Live Write Notes

Fuel autotuning now keeps Safe as the default review-first mode, where valid AFR samples update only the working Base Map. Conservative and Aggressive modes enable live Base Map writes to the PFC after the active cell meets its sample requirement and the working Base Map has at least the configured minimum number of changed cells.

Live autotune writes are scoped to the Base Map payload group only. The write path builds and sends the current working Base Map packets, verifies only those written Base Map table IDs, clears the written logging cells, and then resumes live monitoring when autotuning is still active.

Aggressive still uses the lower sample-count gradient, while Conservative uses double the Aggressive requirement. Safe also uses the Conservative sample requirement but does not auto-write to the PFC.

## V1.88 Auxiliary Analog Input Notes

Auxiliary Connections is now strictly analog 0-5 V focused. The older Wite synthetic AFR preset migrations and raw-byte AFR/lambda bypass were removed, so every selected AFR source now uses the same voltage-to-value conversion path as the visible calibration fields. Existing saved Digital markers are ignored when loading auxiliary rows, leaving the saved voltage/value calibration to behave as a normal analog input.

Auxiliary inputs are limited to the four Wite analog channels. Each input has a fixed channel association (`AN1` through `AN4`) used for live voltage/raw-byte reads, so renaming the label or loading older settings cannot cause two rows to point at the same channel. Older saved `Input 1`-style labels are migrated to `AN1`-style labels.

Selected analog AFR sources no longer fall back to the separate PowerFC O2 voltage when the Wite aux packet is missing. The live monitor now reports that it is waiting for the Wite aux packet and shows the PFC O2 voltage separately, preventing the selected analog input from appearing stuck around the live packet's O2 value. When aux data is present, the monitor includes all decoded `AN1`-`AN4` voltages/raw bytes for testing.

Analog aux byte conversion now uses full-scale ADC voltage, `volts = raw * 5 / 255`, for bench testing real 0-5 V inputs. The live monitor also shows each raw byte and percent of full scale so Arduino voltage tests can distinguish a decode/scaling issue from a Wite aux packet that is not changing.

Live monitoring now prioritizes maximum WBO2/PFC polling rate for logging and autotuning. The artificial live loop delay is removed, live `F0` reads use a shorter `250 ms` timeout, aux packet reads use a short `60 ms` timeout so a missed aux frame does not stall the whole monitor, and UI updates are queued asynchronously with latest-sample coalescing so the serial polling thread does not wait for WPF rendering. Map/table reads use a shorter `15 ms` pacing delay between records. Write pacing remains conservative.

Selected map writes now verify only the table IDs that were written instead of re-reading the broader core map set. Map writes use a shorter post-ACK pacing delay while settings writes keep the more conservative delay. `Write All Maps` still writes all working map payloads, but its verification is also limited to the records it wrote.

## V1.83 Inj vs AirTemp Decode Notes

Fuel & Inj Correction now reads Inj vs AirTemp from table `B9` as six little-endian `UInt16` values scaled by `/256`. Table `91` is no longer used for that six-temperature correction display, and `B9` is no longer treated as a Rev / Idle alias. This matches the 1ZZ default map values `0.938`, `0.969`, `1.000`, `1.020`, `1.039`, and `1.059`.

## V1.82 Airflow Names, Notes, and Serial Notes

Airflow option names in table `CE` now decode as 17-byte ASCII names in 18-byte slots, matching the padded layout before the Voltage / Value block. The Function Select notes field is left-aligned on its own row so it stays visible and wraps without expanding sideways. Rev / RPM labels table `BC` as O2 Feedback / Inj Correction and continues showing lambda plus gasoline AFR. Serial setup is fixed to 8N1/no parity, with the parity menu removed.

## V1.81 Injector Settings Decode Notes

Injector settings table `8D` now decodes the first six `UInt16` words as injector correction percentages using `raw / 32768 * 100`, and the next six `UInt16` words as injector offsets centered at `0x8000` with `0.004 ms` per count. This matches FCEdit values such as `54.9 / 0.36` for the 1ZZ FET map and `73.1 / 0.04` for the RB26 sample map entries.

## V1.80 Airflow Offset Notes

Airflow Voltage / Value decoding now starts at `CE` offset `91`, after the five padded airflow option names, so default 1ZZ/2ZZ maps display eight `100.0%` entries instead of ASCII padding values. Boost Control now reads boost bytes from `AB` offsets `3-6` with scale `0.05` and duty bytes from offsets `7-10`, matching the expected `0.80/24`, `1.00/44`, `1.10/50`, and `1.20/56` display.

## V1.79 Airflow Boost Decode Notes

Boost Control boost targets now decode with a `0.04` byte scale so the 1ZZ `AB` table values display as `0.80`, `1.00`, `1.10`, and `1.20` with duties `24`, `44`, `50`, and `56`. The Airflow Voltage / Value rows remain decoded from the eight final `CE` `UInt16` values, where `E8 03` displays as `100.0%`.

## V1.78 Settings Layout Notes

Fuel & Inj Correction moves Inj vs AirTemp into the lower correction group and makes the injector recalculation helper more compact with explanatory text. Ignition Correction tightens IGN vs BatV and temperature-retard grids. Notes editing now uses a fixed-width wrapping text box, and the Airflow page separates curve selection, voltage/value rows, boost control, and curve rows more explicitly.

## V1.77 Ignition Correction Label Notes

Cranking temperature rows now keep their `C` suffix in the Rev / RPM page. Ignition Correction table IDs `96`, `98`, and `9A` are decoded as IGN vs WaterT Cool, IGN vs WaterT, and IGN vs AirT respectively, matching the 1ZZ map values shown in FC-Edit.

## V1.76 Settings Decode And Layout Notes

Settings pages use tighter group margins and smaller reserved panel widths. Rev / RPM now includes Cranking ms from table `8E`/`D2` plus O2 Feedback Inj Correction with lambda-to-gasoline-AFR display. Fuel & Inj Correction includes Inj vs AirTemp from table `91`. Ignition Correction now renders IGN vs AirT as Temp/Retard rows and IGN Dwell vs RPM with FC-Edit-style High/Low labels plus the placeholder ms column. The Settings menu order is Rev/RPM, Airflow, Fuel & Inj Correction, Ignition Correction, Function Select, then separated Auxiliary Connections.

## V1.75 Settings Label And TPS Column Notes

Fuel & Inj Correction pair grids now look up TPS rows by their decoded labels while keeping the richer `TPS (V)` and `TPS (V/t)` column headers. Settings labels are right-aligned with tighter spacing so labels sit directly beside their input boxes across settings pages.

## V1.74 Fuel Correction Decode Notes

Fuel & Inj Correction now decodes Inj vs Accel TPS1 as three TPS-rate/setting pairs from table `94`, with TPS scaled as volts-per-time and setting scaled as a byte fraction. INJ vs TPS from table `BA` now displays TPS in volts instead of percent. Water Temp Correction exposes the low-load and high-load breakpoints stored at the end of table `8F`/`D3`.

## V1.73 Correction Page Consolidation Notes

Fuel & Inj Correction now owns injector lag, injector TPS, acceleration injector, and water temperature correction layouts in stacked groups, replacing the standalone Correction Factors menu entry. Ignition Correction is arranged as two rows with temperature-based tables first and dwell/battery/TPS tables below. Function Select keeps the primary function flags at the top, removes Boost Control from that submenu, and moves FC Box custom features plus notes below the supporting settings.

## V1.72 Settings Page Layout Notes

Map Reference load/RPM data moved to the Rev / RPM settings group. Fuel & Airflow is now Fuel & Inj Correction, with airflow tables removed and an injector-size recalculation helper beside the injector correction grid. The dedicated Airflow page now keeps airflow selection, voltage/value, and boost control on the top row while placing the airflow curves below in their own horizontal scroll area.

## V1.71 Airflow Settings Notes

The Settings menu now has a dedicated Airflow page. It decodes table `CE` as the active airflow selector, five option names, and the eight voltage-to-percentage points; table `A0` as the 32-point airflow voltage axis; tables `A1-A5` as the five airflow curves; and table `AB` as the four boost/duty options using FC-Edit's boost-control byte offsets.

## V1.70 FC Box Custom Features Notes

The Function Select submenu now includes the FC Box custom feature block from table `AD`, including the tuner string, tuner-string enable flag, boost switch, anti-lag switch, anti-lag retard, and anti-lag injector settings. Plain-text `.dat` notes stored on a `TT...` line are preserved during parsing and serialization and are editable from the same submenu.

## V1.69 Function Select Inversion Notes

Function Select checkboxes now use an inverted byte-backed boolean so the tab matches the ECU's enabled/disabled display. A checked box writes `0x00`, and an unchecked box writes `0x01`; other byte-backed checkbox settings keep their normal nonzero-is-enabled behavior.

## V1.68 Correction Settings Layout Notes

Correction-factor aliases are now resolved to a single active table before rendering, so Water Temp Correction and Acceleration Enrichment do not appear twice when both the primary and alias table IDs are present. Water Temp Correction is displayed as a temperature-by-load matrix, and Accelerate Injector is displayed as an RPM-by-amount/decay matrix while preserving the original editable rows for save/write.

## V1.67 Wite Synthetic Lambda Channel Notes

Wite's synthetic channel wording is now applied directly: when an active digital lambda controller is detected, AN2 is replaced with a synthetic channel where `volts * 10 = AFR`. The app still derives lambda, but only after calculating gasoline AFR:

```text
gasoline AFR = volts * 10
lambda = gasoline AFR / 14.7
```

This restores the explicit `0-5 V -> 0-50 AFR` Wite/FC-Edit scale while keeping lambda visible in the live monitor for comparison.

## V1.66 Wite Lambda AFR Preset Notes

Historical note: this preset was superseded by the current four-channel analog setup. In the old V1.66 behavior, Input 2 defaulted and migrated to a Wite lambda-style gasoline AFR preset. The Wite aux byte was decoded as centivolts (`volts = raw / 100`), then interpreted as lambda volts by converting back to millivolts:

```text
lambda = (volts * 1000) / 1000
gasoline AFR = lambda * 14.7
```

This is equivalent to a linear calibration of `0-5 V -> 0-73.5 AFR`. The live monitor labels the selected Wite lambda source with lambda, AFR, and raw byte so it can be compared directly with the gauge while testing AN1/AN2.

## Project

```text
PowerFCTuner\PowerFCTuner.csproj
```

Framework:

```text
net8.0-windows
```

UI:

```text
WPF
```

Primary source files:

- `MainWindow.xaml`
- `MainWindow.xaml.cs`
- `PfcSerialReader.cs`
- `PfcEcuProfile.cs`
- `PfcMapDecoder.cs`
- `PfcSettingsDecoder.cs`
- `PfcDatParser.cs`
- `PfcSession.cs`
- `WitePacketDecoder.cs`

## V1.65 COM Port Error Popup Notes

Serial read/write and live-monitor startup paths now show a modal COM Port Error popup when opening or using the selected COM port fails. This makes cases where another application, driver, or disconnected interface prevents access visible instead of only updating the status bar.

The popup format is intentionally simple:

```text
Error: connection with COM port COMx failed.
Reason: COMx is unavailable or in use outside of PowerFC Tuner.
```

The same helper is used for read maps, read/write individual maps, write all maps, settings read/write, settings popup read/write, and live monitoring startup failures.

## V1.64 Wite Lambda Synthetic Channel Notes

Wite confirmed that when the interface detects an active digital lambda controller, it replaces AN2 with a synthetic channel where `volts * 10 = AFR`. This is equivalent to FC-Edit AN2 poly `b = 10`, or a linear scale of `0-5 V -> 0-50 AFR`.

Historical note: the old V1.64 behavior defaulted Input 2 to:

```text
0 V = 0 AFR
5 V = 50 AFR
AFR = volts * 10
```

The Wite auxiliary packet voltage scale remains `volts = raw / 100`, so AN2 raw `247-249` becomes `2.47-2.49 V` and therefore `24.7-24.9 AFR` when the Wite digital-lambda synthetic channel is active.

Old app settings that still have the V1.62/V1.63 Innovate MTX-L preset on Input 2 are migrated to the Wite synthetic channel preset.

## V1.63 Wite Aux Voltage Scale Notes

The Wite auxiliary packet conversion now treats AN1-AN4 raw bytes as centivolts: `volts = raw / 100`. The earlier `raw * 5 / 255` interpretation was incorrect for observed Wite/FCEdit traffic.

Validation from `16.1.spm`: AN2 raw values `245-250` correspond to `2.45-2.50 V`. With the Innovate MTX-L curve, this yields about `14.72-14.87 AFR`, matching the reported gauge range around 15-16. The old 8-bit ADC scaling converted the same raw values to `4.80-4.90 V`, falsely producing about `21.8-22.1 AFR`.

## V1.62 Wite Analog AFR Decoder Notes

The Digital/Analog mode selector and digital divisor path were removed. Current evidence from FCEdit, CoPilot, and Wite logs points to the Wite interface exposing the MTX-L wideband through the auxiliary analog packet, not as a direct serial AFR value in the app-facing stream.

`WitePacketDecoder` now owns Wite auxiliary packet handling. It finds length/checksum packets, validates checksums with `0xFF - sum(previous bytes)`, detects `00 06 AN1 AN2 AN3 AN4 checksum`, extracts AN1-AN4 raw bytes, and converts raw counts to voltage.

Input 2 is now the default AFR source using the Innovate MTX-L linear curve:

```text
0 V = 7.35 AFR
5 V = 22.39 AFR
AFR = 7.35 + volts * 3.008
```

Old saved settings that had an auxiliary input in Digital mode are migrated to Input 2 with the MTX-L preset. The live monitor shows the selected Aux source voltage and raw byte so FCEdit/CoPilot voltage readings can be compared directly.

## V1.61 Digital AFR Calibration Notes

Auxiliary Inputs 1 and 2 now expose a `Digital Divisor` setting in the Auxiliary Connections window. Digital AFR is calculated from the selected input's raw AN byte as `raw / Digital Divisor`. The default divisor is `14.3`, based on the latest comparison where an app reading around 15.0-15.5 needed to line up with a wideband gauge around 17.0-17.4.

The live monitor includes the selected divisor beside the raw byte and voltage view. This makes it possible to tune the decoder against the physical wideband gauge without changing code.

## V1.60 Aux Digital Diagnostics Notes

Historical note: this digital mode was removed in the current analog-only setup. In V1.60, Auxiliary Inputs 1 and 2 could be switched between Analog and Digital mode while Inputs 3-8 remained analog-only. Digital mode decoded the selected input's own AN byte with the current `raw / 16` AFR scale, so Input 1 used AN1 and Input 2 used AN2.

The live monitor now shows `O2 / Aux Data` instead of only voltage. For analog sources it displays the selected Aux voltage plus raw byte. For digital sources it displays the selected input name, decoded AFR, raw byte, and the same byte's 0-5 V interpretation. This makes it easier to compare what FCEdit/CoPilot are showing against the actual data coming back in the `00 06 AN1 AN2 AN3 AN4 checksum` frame.

## V1.59 Wite AN2 AFR Scale Notes

The Wite digital wideband AN2 decoder now uses `AFR = AN2 raw / 16`. In the supplied CoPilot capture, AN2 raw values of roughly `233-249` correspond to about `14.6-15.6 AFR`, matching the observed 14-16 AFR range during the log.

## V1.58 Wite Digital Wideband Notes

Wite confirmed that digital wideband data is exposed through AN2, overriding the sensor on that pin. Digital mode no longer treats the selected Aux input as analog voltage. Instead, when Aux1 is set to Digital, live monitoring decodes the AN2 raw byte from the `00 06 AN1 AN2 AN3 AN4 checksum` frame as AFR. V1.59 updated the scale to `AN2 / 16` based on observed logged AFR values.

The live monitor now labels this as `AN2 digital ... AFR` and includes the raw byte for troubleshooting. Analog Aux source conversion still uses the selected channel's 0-5 V scaled value.

## V1.57 Wite Aux1 AFR Notes

CoPilot monitoring with the wideband connected shows the Wite interface polling `00 02 FD` after each live `F0` packet and receiving `00 06 AN1 AN2 AN3 AN4 checksum`. In the supplied capture, AN1 is around raw `81-83` when the wideband is connected, drops to `0` while unplugged, and returns to roughly the same value when reconnected.

Live monitoring now polls the Aux data frame and stores AN1-AN4 raw bytes plus 0-5 V scaled values (`raw * 5 / 255`). AFR source conversion uses the selected auxiliary input voltage when available, including Aux1 when it is set to Digital mode. This matches the observed Wite behavior: the gauge side may be serial, but the PFC/CoPilot-visible data is still Aux voltage.

Aux calibration fields remain editable in Digital mode so users can map the received Aux1 voltage to AFR, lambda, or another configured unit.

## V1.56 Serial Read Reliability Notes

Map and live-data reads now ignore exact request echoes before accepting a response frame. Some USB/serial bridges echo the three-byte request, and treating that echo as the table response can make reads appear to fail or return empty payloads.

Read timeouts were increased to 1200 ms for live data and map reads to better tolerate the WiteDevices interface while preserving the same 57600 8N1, no-handshake, DTR/RTS-off serial settings.

Read/write operations now wait for live monitoring to fully stop before opening the COM port again. This matters most when Aux1 is set to digital AFR mode, because the monitor can otherwise still own the port briefly while a map read begins.

## V1.55 Auxiliary Mode Scope Notes

Historical note: this mode selector was removed in the current analog-only setup. In V1.55, only Auxiliary Input 1 showed the Analog/Digital mode selector while Inputs 2-8 remained analog-only.

## V1.54 Auxiliary Layout Notes

Auxiliary input cards now place Mode, Poly, and AFR source selection together at the top of each block. The Name/Unit and voltage/value calibration fields remain below. Selecting Digital mode also selects that input as the AFR source and clears the other AFR source selections.

## V1.53 Autotune Sample Gradient Notes

Fuel autotune sample requirements are now cell-based instead of fixed. Aggressive mode uses a load/RPM gradient from roughly 100 samples in low RPM/load cells down to 10 samples in high RPM/load cells. Safe and Conservative require double the Aggressive count for the active cell, so low cells can require around 200 samples and high cells around 20.

## V1.52 Digital AFR Input Notes

The Re-scale Maps dialog is narrower and wraps its explanation across multiple lines. Auxiliary Connections now gives Input 1 an Analog/Digital mode selector. Analog mode keeps the existing 0-5V calibration. Digital mode is intended for WiteDevices/gauge serial AFR sources, makes Input 1 the AFR source, disables analog calibration fields, and waits for a received digital AFR value instead of scaling the PFC O2 voltage. RealDash/Wite reference files identify AFR Serial as frame `0x01` with a `14.7*V/1000` style conversion; direct gauge serial may also arrive as plain ASCII like `14.7\r\n`, so the UI now has the configuration path for that source.

## V1.51 Rescale Axis Selection Notes

Advanced > Re-scale Maps now lets users choose whether to re-scale RPM, Load, or both. RPM and Load inputs are compact fixed-width fields with RPM limited to four digits and Load limited to five digits. Unselected axes keep their existing 20x20 axis values while selected axes are interpolated/extrapolated and written back to the map reference.

## V1.50 Advanced Rescale Notes

Auxiliary Connections now lives under the Settings menu. A new Advanced > Re-scale Maps action accepts new maximum RPM and Load values, creates new 20x20 axes, bilinearly interpolates or linearly extrapolates the working Injector, Base, Ignition, Ignition 2, VVTi, and AFR Target maps, updates the tuning document's 8A map-reference record, and clears logged samples because old sample cells no longer match the new axes. Write All Maps now includes the updated 8A map-reference payload when available.

## V1.49 Autotune Threshold Notes

Autotuning Options now displays sample requirements: Safe and Conservative require 10 samples per active cell, while Aggressive requires 5. Fuel autotuning now waits for the selected mode's sample requirement before applying a working base-map correction. Ignition autotuning guidance was moved above the enable checkboxes and now explains knock-only practice, low knock as noise/no-change, and that timing advance is only added when Ignition Advance is enabled.

## V1.48 TPS Calibration Safety Notes

TPS calibration now shows a warning popup when live PFC data indicates the engine is running. Calibration is blocked until RPM is 0, and the user is told to turn the car off before calibrating TPS.

## V1.47 Fresh Map Session Notes

Opening a new DAT or reading a fresh map set from the PFC now starts a clean tuning session. AFR target data, logged AFR averages, logged knock peaks, sample counts, active logging/autotuning state, and the per-session O2 feedback flag are reset. Write-and-reread paths preserve the current session so live tuning samples are not discarded by normal map writes.

## V1.46 Close Session Prompt Notes

Closing the app with loaded map/session data now prompts the user to save the session. The prompt warns that closing without saving removes unsaved changes, gathered samples, and unwritten map changes, and offers `Save Session`, `Close Without Saving`, or `Cancel`.

## V1.45 Ignition Autotune Safety Notes

The ignition autotune control is now labeled `Enable Ignition Autotuning`. Enabling it shows a warning that ignition autotuning only performs timing retard unless ignition advance is separately enabled. Ignition Advance is disabled until Ignition Autotuning is enabled, and enabling advance shows a catastrophic-damage warning reminding users to configure knock thresholds and monitor knock closely.

## V1.44 Tuning Button And Refresh Notes

Tuning map read buttons now identify the specific map being read from the PFC. When offline, the Tuning `Write All Maps` action is labeled `Save All Maps`, continues to save a user-selected DAT file, and `Reload All Maps` is disabled. Cell edits, paste, interpolation, and +/- changes now refresh the update indicator without rebuilding the visible working map grid, preserving the current selection and avoiding whole-grid flashing. Logged Data derived views also avoid full-grid refreshes during live samples.

## V1.43 Tuning Updates Notes

Tuning maps now include an `Updates` selector that can switch each map between the editable working map and a read-only `To Be Written` delta view compared with the current PFC-read map. AutoTuning base-map changes appear through the Base Map delta view, and the Tuning header shows `Map Updates Available` when any writable map has differences. AutoTuning now also requires valid TPS calibration, and TPS capture buttons require live RPM to be `0`.

## V1.42 Logged Data Notes

The Logged Data tab now includes a `Clear Samples` button that clears only the sample-count table.

## V1.41 Live Logging Notes

Live logging now updates the traced RPM/load cell while Logging or AutoTuning is active. Logged AFR is a running average for each cell, logged knock stores the highest observed knock value per cell, and Samples stores the count used for the average. PFC Maps are no longer included in the map tracer target list. The injector-pulse check has been removed from AutoTuning readiness, and live speed now shows both kph and mph.

## V1.40 Auxiliary Save Notes

The Auxiliary Connections popup now has an explicit `Save` button. Pressing it persists the auxiliary calibration/AFR source settings and closes the popup.

## V1.39 Auxiliary Calibration Layout Notes

Auxiliary calibration now reads as voltage-to-value pairs, with Voltage on the left and Value on the right, e.g. `0v - 8` and `5v - 20` for a wideband AFR input.

## V1.38 Auxiliary Layout Notes

Auxiliary input cards now separate identity fields from calibration fields. `Name` and `Unit` sit on the left, while voltage/value calibration is arranged as a compact matrix on the right.

## V1.37 Auxiliary AFR Source Notes

The `Logged Data` selector order is now Samples, Logged AFR, Logged Knock, AFR Difference, and Base Map Changes. Auxiliary Connections now renders each input as its own grouped editor and stores an explicit AFR source selection. Live AFR display and fuel autotuning use that selected input.

## V1.36 Logged Data And Map Trace Notes

The logging UI now uses one `Logged Data` tab with a view selector for true logged AFR, AFR difference, base map changes, logged knock, and samples. Live monitoring now resolves the current `F0` RPM/load values to the nearest map-axis cell and highlights that cell on the map grids as a first-pass map tracer.

## V1.35 Live Monitor Layout Notes

The Live Monitors tab now uses grouped dashboard panels instead of a source-oriented table. Monitoring is gated behind a successful PFC map read, so offline `.dat` viewing/editing cannot open the live polling loop by mistake.

## V1.34 Live Monitor Tab Notes

The AutoTuning & Logging area now includes a `Live Monitors` sub-tab. It displays every decoded value from the active `F0 02 0D` live monitor packet, plus calculated AFR from Auxiliary Connections and TPS percentage from the local TPS calibration.

## V1.33 Live Monitor Notes

The header `Start Monitoring` button now opens a continual serial poll using the CoPilot-observed advanced live-data command `F0 02 0D`. The app decodes RPM, load, TPS voltage, injector pulse, coolant temperature, intake temperature, knock, battery voltage, speed, O2 voltage, and both ignition values from the 33-byte response. Read/write operations pause monitoring before opening the COM port, then resume after successful PFC operations.

The AutoTuning Options page now reports which live checks are met and what it is waiting on. AFR display and AFR gating use the Auxiliary Connections calibration whose name or unit contains `AFR`; if no AFR input is configured, the live AFR value stays blank and logging/autotuning remain gated.

The Welcome support section now includes a PayPal support button and bundled QR code asset.

## V1.32 Map UI Notes

The Tuning tab now has a conditional `Ignition 2` page for ECUs/maps that expose both ignition packet families. The normal Ignition page uses the primary packet family, while `Ignition 2` uses the secondary `81-84` family only when both primary `76-79` and secondary `81-84` records are present. The tab remains disabled when the secondary family has not been read from the PFC or loaded from a `.dat` / session.

Rev/Idle settings now select a single available source from `B8`, `B9`, or `D4` instead of rendering duplicate rows when more than one alias/variant is present in the same map.

## V1.31 Compatibility Notes

The compatibility notes now explicitly separate "recognized for parsing" from "supported for editing/tuning." Rotary `13B` / `13B-REW` profiles are intentionally out of scope for tuning support because their map strategy and tuning requirements differ from piston-engine PowerFC applications. The decoder may identify rotary files defensively, but the UI should not treat them as supported tuning targets.

The 3S-GE sample exposes additional FCEdit map concepts named `VvinMap` and `VvexMap`. These appear as extra packets around `6C-6F`; they are documented as unsupported until scaling, axis pairing, and write behavior are confirmed. Honda-specific `60-6A` extras are documented the same way.

## V1.30 Decoder Notes

The decoder now carries a broader FCEdit-derived calibration list for Toyota, Mitsubishi, Nissan, Subaru, Honda, and rotary PowerFC files. The profile layer recognizes engine/version keys observed in the FCEdit decompile, including the sample families for `EJ20`, `RB20`, `RB25`, `RB26`, `SR20`, `CA18`, `1JZ`, `2JZ`, `3S-GE`, `3S-GTE`, `4G63`, `B16`, `B18`, `13B`, and the existing `1ZZ` / `2ZZ` Toyota maps.

Rev/Idle labels are now selected by ECU family:

- Toyota/Mitsubishi/default profiles keep the seven-label layout: `Rev Limit`, `F/C A.E`, `F/C E/L`, `F/C A/C`, `Idle A.E`, `Idle E/L`, and `Idle A/C`.
- `2ZZ-GE` and `2ZZ-GET` use the FCEdit VVTL-i labels: `Rev Limit`, `VTLI High`, `VTLI Low`, `F/C A/E`, `F/C A/C`, `Idle A/E`, and `Idle A/C`.
- Nissan/Subaru families seen with FCEdit's compact layout, including `CA18`, `SR20`, `RB20`, `RB25`, `RB26`, `VG30`, and `EJ20`, use `Rev Limit`, `F/C1`, `F/C2`, `Idle1`, and `Idle2`.

## V1.29 Decoder Notes

The FCEdit decompile confirms specific Toyota profile labels:

- `2ZZ-GE` / VVTL-i Rev/Idle captions are `Rev Limit`, `VTLI High`, `VTLI Low`, `F/C A/E`, `F/C A/C`, `Idle A/E`, and `Idle A/C`.
- FCEdit has explicit model/version branches for `1ZZ-FE3.14`, `1ZZ-FE3.20`, `1ZZ-FET4.12`, `2ZZ-GE2.50B`, `2ZZ-GE2.61`, `2ZZ-GE2.71A`, and `2ZZ-GET2.71`.

CoPilot extracted settings provide useful autotune defaults. The app now uses `1` as default minimum throttle, `3` as the minimum changes-to-write threshold, and ignition knock thresholds `10 / 19 / 30` for low / medium / high.

## V1.28 Decoder Notes

The serial reader now keeps direct FCEdit table IDs as the preferred source, but also probes known aliases from the PowerFC research notes:

- `C1-C4` can populate ignition records `81-84` when direct `81-84` reads do not respond.
- `C6-C9` can populate injector correction records `86-89` when direct `86-89` reads do not respond.
- `D1-D4` are included for older/alternate settings packets seen in emulator and bench notes.

Records read from direct table IDs win over alias records. Alias records only fill a missing table so a direct response is not overwritten by an alternate command response.

`PfcEcuProfile` classifies the `F3` model string using the PowerTune `Apexi.cpp` model groups. This is currently used for model-aware settings labels, including `2ZZ-GE` Rev/Idle lift labels such as `VTLI High` and `VTLI Low`.

## Build

```powershell
dotnet build PowerFCTuner\PowerFCTuner.csproj -o PowerFCTuner\bin\Verify
```

## Publish EXE

```powershell
dotnet publish PowerFCTuner\PowerFCTuner.csproj -c Release -r win-x64 -p:PublishSingleFile=true -p:SelfContained=true -p:IncludeNativeLibrariesForSelfExtract=true -o PowerFCTuner\bin\Package\win-x64-v2.13-self-contained
```

Published EXE:

```text
PowerFCTuner\bin\Package\FCTuner x64 V2.13\FCTuner x64 V2.13 Self Contained.exe
```

## Session Persistence

Session save uses:

- JSON `.pfcsession`
- Optional PFC sidecar `.dat`
- Optional working-map sidecar `.dat`

Session data includes:

- PFC map records
- Working map records
- Working table rows
- AFR target
- Logged AFR
- Logged knock
- Samples
- Auxiliary input definitions
- Autotuning checks
- Ignition autotuning options
- TPS calibration values

## Working Folder Structure

When a working folder is selected, the app creates:

```text
Backups\
Sessions\
Working\
Working\Maps\
Working\Logs\
Working\Settings\
```

## App Settings

Preferences are saved to:

```text
%APPDATA%\PowerFCTuner\settings.json
```

If this file does not exist, startup shows no selected working folder.

## Serial Communication

PowerFC serial access is implemented in `PfcSerialReader.cs`.

Current serial defaults:

```text
57600 baud
8 data bits
No parity
1 stop bit
No handshake
DTR false
RTS false
```

Read requests use PowerFC-style 3-byte commands:

```text
command length checksum
```

Writes build a frame with:

```text
tableId payloadLength payload checksum
```

## Map Handling

`PfcMapDecoder.cs` parses known map packets into 20x20 tables with RPM columns and load rows.

Main editable map groups:

- Injector Correction
- Base Fuel
- Ignition
- VVTi
- AFR Target

The PFC map tab intentionally shows only maps read from the PFC. Offline `.dat` files populate the tuning document only.

## Settings Handling

`PfcSettingsDecoder.cs` maps known raw payload offsets into editable setting rows.

Settings popups render parsed fields as compact grouped controls. Raw and unread rows are hidden from the popup UI.

Function Select currently exposes boolean checkbox fields for known FCEdit-style function selections. Because ECU variants may differ, these offsets should continue to be verified against additional `.dat` and live PFC reads.

## AFR And Auxiliary Inputs

Auxiliary inputs store linear `voltage low/high` to `value low/high` calibration.

The app has a helper to convert an auxiliary voltage into AFR when an input name or unit contains `AFR`.

Open work:

- Connect live serial auxiliary voltage sampling to the AFR conversion helper.
- Store polynomial coefficients if polynomial calibration should persist directly rather than just filling voltage/value pairs.

## Current Limitations

- Live logging ingestion is not fully wired.
- AFR conversion logic exists, but live aux voltage samples are not yet feeding it.
- AutoTuning buttons are gated by checks, but real-time sample capture and write decisions are not fully implemented.
- Ignition autotuning options are saved/restored, but live knock-based timing changes are not yet active.
- MSI packaging requires adding installer tooling such as WiX.
