Auto: focas-f2a — DIAG: address scheme
New FocasAreaKind.Diagnostic parsed from DIAG:nnn (whole-CNC) and DIAG:nnn/axis (per-axis), validated against a per-series FocasCapabilityMatrix.DiagnosticRange table (16i: 0-499; 0i-F family: 0-999; 30i/31i/32i: 0-1023; Power Motion i: 0-255; Unknown: permissive per existing matrix convention). IFocasClient gains ReadDiagnosticAsync(diagNumber, axisOrZero, type, ct) with a default returning BadNotSupported so older transport variants degrade gracefully. FwlibFocasClient implements it via a new cnc_rddiag P/Invoke that reuses the IODBPSD struct (same shape as cnc_rdparam). FocasDriver.ReadAsync dispatches Diagnostic addresses through the new path; non-Diagnostic kinds keep the existing ReadAsync route unchanged. Tests: parser positives (DIAG:1031, DIAG:280/2, case-insensitive, zero, axis-8) + negatives (malformed, axis>31), capability matrix boundaries per series, driver-level dispatch verifying axis index threads through, init-time rejection on out-of-range, and BadNotSupported fallback when the wire client doesn't override the default. 266/266 pass in Driver.FOCAS.Tests. Closes #263 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,9 +32,10 @@ public static class FocasCapabilityMatrix
|
||||
|
||||
return address.Kind switch
|
||||
{
|
||||
FocasAreaKind.Macro => ValidateMacro(series, address.Number),
|
||||
FocasAreaKind.Parameter => ValidateParameter(series, address.Number),
|
||||
FocasAreaKind.Pmc => ValidatePmc(series, address.PmcLetter, address.Number),
|
||||
FocasAreaKind.Macro => ValidateMacro(series, address.Number),
|
||||
FocasAreaKind.Parameter => ValidateParameter(series, address.Number),
|
||||
FocasAreaKind.Pmc => ValidatePmc(series, address.PmcLetter, address.Number),
|
||||
FocasAreaKind.Diagnostic => ValidateDiagnostic(series, address.Number),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
@@ -73,6 +74,29 @@ public static class FocasCapabilityMatrix
|
||||
_ => (0, int.MaxValue),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// CNC diagnostic number range accepted by a series; from <c>cnc_rddiag</c>
|
||||
/// (and <c>cnc_rddiagdgn</c> for axis-scoped reads). Returning <c>null</c>
|
||||
/// means the series doesn't support <c>cnc_rddiag</c> at all — the driver
|
||||
/// rejects every <c>DIAG:</c> address on that series. Conservative ceilings
|
||||
/// per the FOCAS Developer Kit: legacy 16i-family caps at 499; modern 0i-F
|
||||
/// family at 999; 30i / 31i / 32i extend to 1023. Power Motion i has a
|
||||
/// narrow diagnostic surface (0..255).
|
||||
/// </summary>
|
||||
internal static (int min, int max)? DiagnosticRange(FocasCncSeries series) => series switch
|
||||
{
|
||||
FocasCncSeries.Sixteen_i => (0, 499),
|
||||
FocasCncSeries.Zero_i_D => (0, 499),
|
||||
FocasCncSeries.Zero_i_F or
|
||||
FocasCncSeries.Zero_i_MF or
|
||||
FocasCncSeries.Zero_i_TF => (0, 999),
|
||||
FocasCncSeries.Thirty_i or
|
||||
FocasCncSeries.ThirtyOne_i or
|
||||
FocasCncSeries.ThirtyTwo_i => (0, 1023),
|
||||
FocasCncSeries.PowerMotion_i => (0, 255),
|
||||
_ => (0, int.MaxValue),
|
||||
};
|
||||
|
||||
/// <summary>PMC letters accepted per series. Legacy controllers omit F/M/C
|
||||
/// signal groups that 30i-family ladder programs use.</summary>
|
||||
internal static IReadOnlySet<string> PmcLetters(FocasCncSeries series) => series switch
|
||||
@@ -143,6 +167,16 @@ public static class FocasCapabilityMatrix
|
||||
: null;
|
||||
}
|
||||
|
||||
private static string? ValidateDiagnostic(FocasCncSeries series, int number)
|
||||
{
|
||||
if (DiagnosticRange(series) is not { } range)
|
||||
return $"Diagnostic addresses are not supported on {series} (no documented cnc_rddiag range).";
|
||||
var (min, max) = range;
|
||||
return (number < min || number > max)
|
||||
? $"Diagnostic #{number} is outside the documented range [{min}, {max}] for {series}."
|
||||
: null;
|
||||
}
|
||||
|
||||
private static string? ValidatePmc(FocasCncSeries series, string? letter, int number)
|
||||
{
|
||||
if (string.IsNullOrEmpty(letter)) return "PMC address is missing its letter prefix.";
|
||||
|
||||
Reference in New Issue
Block a user