Auto: focas-f2b — multi-path/multi-channel CNC

Adds optional `@N` path suffix to FocasAddress (PARAM:1815@2, R100@3.0,
MACRO:500@2, DIAG:280@2/1) with PathId defaulting to 1 for back-compat.
Per-device PathCount is discovered via cnc_rdpathnum at first connect and
cached on DeviceState; reads with PathId>PathCount return BadOutOfRange.
The driver issues cnc_setpath before each non-default-path read and
tracks LastSetPath so repeat reads on the same path skip the wire call.

Closes #264
This commit is contained in:
Joseph Doherty
2026-04-25 19:42:58 -04:00
parent 3b82f4f5fb
commit 2f3eeecd17
7 changed files with 478 additions and 17 deletions

View File

@@ -195,6 +195,27 @@ internal static class FwlibNative
short length,
ref IODBPSD buffer);
// ---- Multi-path / multi-channel ----
/// <summary>
/// <c>cnc_rdpathnum</c> — read the number of CNC paths (channels) the controller
/// exposes + the currently-active path. Multi-path CNCs (lathe + sub-spindle,
/// dual-turret) return 2..N; single-path CNCs return 1. The driver caches
/// <see cref="ODBPATH.MaxPath"/> at connect and uses it to validate per-tag
/// <c>PathId</c> values (issue #264).
/// </summary>
[DllImport(Library, EntryPoint = "cnc_rdpathnum", ExactSpelling = true)]
public static extern short RdPathNum(ushort handle, ref ODBPATH buffer);
/// <summary>
/// <c>cnc_setpath</c> — switch the active CNC path (channel) for subsequent
/// calls. <paramref name="path"/> is 1-based. The driver issues this before
/// every read whose path differs from the last one set on the session;
/// single-path tags (PathId=1 only) skip the call entirely (issue #264).
/// </summary>
[DllImport(Library, EntryPoint = "cnc_setpath", ExactSpelling = true)]
public static extern short SetPath(ushort handle, short path);
// ---- Currently-executing block ----
/// <summary>
@@ -361,6 +382,19 @@ internal static class FwlibNative
public byte[] Data;
}
/// <summary>
/// ODBPATH — <c>cnc_rdpathnum</c> reply. <see cref="PathNo"/> is the currently-active
/// path (1-based); <see cref="MaxPath"/> is the controller's path count. We consume
/// <see cref="MaxPath"/> at bootstrap to validate per-tag PathId; runtime path
/// selection happens via <see cref="SetPath"/> (issue #264).
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ODBPATH
{
public short PathNo;
public short MaxPath;
}
/// <summary>ODBST — CNC status info. Machine state, alarm flags, automatic / edit mode.</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ODBST