fix(focas): decode cnc_rdmacro dec_val at offset 6; vacant/fractional macros go Bad
The ODBM wire payload is [i32 mantissa][i16 length, a constant 10][i16 dec_val]. ReadMacroAsync read the decimal at offset 4, so every macro decoded without failing but wrongly: the captured #500 = 1.0 (05 f5 e1 00 00 0a 00 08) published 0.01. FANUC normalises macros to a 9-significant-digit mantissa, so the error was never small. - dec_val is read at [6..7]; a payload < 8 bytes is refused, not guessed at. - A vacant variable (dec_val 0xFFFF) publishes BadNoData, never a Good 0. - Integer-typed tags get the exact whole value (integer arithmetic); a fractional macro on an integer tag is BadTypeMismatch, a whole value that does not fit the type BadOutOfRange. Float tags get mantissa / 10^dec. Ported from the sister ignitionoee FOCAS driver v0.15.0 (Focas.Wire-013, Focas-017/018); live vectors from Makino Z-34184 (31i-B, G431). Adds a WireFixtures helper that loads the raw 31i-B captures in Fixtures/v3.
This commit is contained in:
@@ -86,13 +86,31 @@ public sealed record WireParameter(
|
||||
int Value);
|
||||
|
||||
/// <summary>
|
||||
/// Macro variable from <c>cnc_rdmacro</c>. Scaled decimal: the callable value is
|
||||
/// <c>Value / 10^Decimal</c>.
|
||||
/// Macro variable from <c>cnc_rdmacro</c>. Scaled decimal: the real value is
|
||||
/// <c>Value / 10^Decimal</c> (<see cref="Scaled"/>). FANUC normalises every macro to a
|
||||
/// 9-significant-digit mantissa, so <see cref="Value"/> alone is never a value to publish
|
||||
/// (live: <c>#502 = 270</c> arrives as <c>270000000 / 10^6</c>).
|
||||
/// </summary>
|
||||
/// <param name="Number">Macro variable number (the request argument; not carried in the payload).</param>
|
||||
/// <param name="Value">The 9-significant-digit mantissa.</param>
|
||||
/// <param name="Decimal">Implied decimal places; negative (<c>0xFFFF</c> on the wire) = vacant.</param>
|
||||
public sealed record WireMacro(
|
||||
short Number,
|
||||
int Value,
|
||||
short Decimal);
|
||||
short Decimal)
|
||||
{
|
||||
/// <summary>
|
||||
/// True when the CNC reported the variable as vacant (undefined / never set):
|
||||
/// <c>dec_val == 0xFFFF</c>. A vacant macro's mantissa is 0, indistinguishable from a
|
||||
/// genuine 0, so this must be tested before <see cref="Value"/> means anything. Any
|
||||
/// negative decimal is treated as vacant — no other negative has ever been observed and
|
||||
/// failing closed is the safe reading.
|
||||
/// </summary>
|
||||
public bool IsVacant => Decimal < 0;
|
||||
|
||||
/// <summary>The real value, <c>Value / 10^Decimal</c>; null when <see cref="IsVacant"/>.</summary>
|
||||
public double? Scaled => IsVacant ? null : Decimal == 0 ? Value : Value / Math.Pow(10.0, Decimal);
|
||||
}
|
||||
|
||||
/// <summary>PMC range read-back from <c>pmc_rdpmcrng</c>: one or more values of the requested width.</summary>
|
||||
public sealed record WirePmcRange(
|
||||
|
||||
Reference in New Issue
Block a user