"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.smmParameterStructureVersionToLaunchwaveVersion = exports.findBitsViewEntry = exports.parameterBitsViewEntries = exports.createSafetyStatuswordBitsViewEntries = exports.digitalOutputsBitNames = exports.digitalInputsBitNames = exports.safetyStatuswordBitsV2Array = exports.safetyStatuswordBitsV1Array = exports.circuloFeedbackEncoderStatusBitNames = exports.supportedDriveModesBitNames = exports.controlwordBitNames = exports.statuswordBitNames = void 0;
const encoder_1 = require("./encoder");
const smm_1 = require("./smm");
exports.statuswordBitNames = [
    'rtso = ready to switch on',
    'so = switched on',
    'oe = operation enabled',
    'f = fault',
    've = voltage enabled',
    'qs = quick stop',
    'sod = switch on disabled',
    'w = warning',
    'ms = manufacturer-specific',
    'rm = remote',
    'tr = target reached',
    'ila = internal limit active',
    'oms = operation-mode-specific',
    'oms = operation-mode-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
];
exports.controlwordBitNames = [
    'so = switch on',
    'ev = enable voltage',
    'qs = quick stop',
    'eo = enable operation',
    'oms = operation mode specific',
    'oms = operation mode specific',
    'oms = operation mode specific',
    'fr = fault reset',
    'h = halt',
    'oms = operation mode specific',
    'r = reserved',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
];
exports.supportedDriveModesBitNames = [
    'pp = profile position mode',
    'vl = velocity mode',
    'pv = profile velocity mode',
    'tq = torque mode',
    'r = reserved',
    'hm = homing mode',
    'ip = interpolated position mode',
    'csp = cyclic synchronous position mode',
    'csv = cyclic synchronous velocity mode',
    'cst = cyclic synchronous torque mode',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
    'ms = manufacturer-specific',
];
/**
 * An array of status bit names for the Circulo feedback encoder, ordered according to the specific
 * register sequence required by the firmware. Each entry corresponds to a bit in the encoder's status
 * registers, with the name and description of the error if available, or 'r = reserved' if not defined.
 * The array is padded with 'r = reserved' entries to ensure a total length of 32 bits.
 *
 * The bit names are constructed by iterating over the registers in the order specified by `registerOrder`
 * ([1, 2, 0]), and for each register, iterating through its bits. If a bit has an associated error with a
 * name and description in `circuloEncoderRegisterErrors`, it is included in the format `${error.name} = ${error.description}`.
 * Otherwise, 'r = reserved' is used.
 *
 * @remarks
 * - The ordering of registers and bits is critical to match the firmware's expected bit order.
 * - The source of error names and descriptions is the `circuloEncoderRegisterErrors` mapping.
 * - The final array always contains exactly 32 entries.
 */
exports.circuloFeedbackEncoderStatusBitNames = (() => {
    const result = [];
    // Due to the specific ordering in the firmware,
    // the registers have to be ordered in a specific way
    // to get the correct bit order in the final array.
    const registerOrder = [1, 2, 0];
    for (const registerIndex of registerOrder) {
        const statusMap = encoder_1.circuloEncoderRegisterErrors[registerIndex];
        for (let bit = 1; bit <= 0x80; bit <<= 1) {
            const error = statusMap[bit];
            if (error && error.name) {
                result.push(`${error.name} = ${error.description}`);
            }
            else {
                result.push('r = reserved');
            }
        }
    }
    // Push 'r = reserved' until there are 32 bits in total
    while (result.length < 32) {
        result.push('r = reserved');
    }
    return result;
})();
exports.safetyStatuswordBitsV1Array = [
    'ain_valid = analog input valid',
    'ain_diag = analog input diagnostic',
    'safe_out2 = safe output 2',
    'safe_out1 = safe output 1',
    'safe_in4 = safe input 4',
    'safe_in3 = safe input 3',
    'safe_in2 = safe input 2',
    'safe_in1 = safe input 1',
    'u = unused',
    'u = unused',
    'u = unused',
    'safe_speed = Safe speed valid',
    'safe_pos = Safe position valid',
    'temp_warn = Temperature warning',
    'SBC = SBC command (state)',
    'restart_ack = Restart acknowledge required',
    'SLS4 = SLS Instance 4 state',
    'SLS3 = SLS Instance 3 state',
    'SLS2 = SLS Instance 2 state',
    'SLS1 = SLS Instance 1 state',
    'u = unused',
    'u = unused',
    'SS2 = SS2 state',
    'SS1 = SS1 state',
    'error = Error active',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'SOS = SOS state',
    'r = reserved',
    'r = reserved',
    'STO = STO state', // 0
];
exports.safetyStatuswordBitsV2Array = [
    'ain_valid = analog input valid',
    'ain_diag = analog input diagnostic',
    'safe_out2 = safe output 2',
    'safe_out1 = safe output 1',
    'safe_in4 = safe input 4',
    'safe_in3 = safe input 3',
    'safe_in2 = safe input 2',
    'safe_in1 = safe input 1',
    'SLT = SLT state',
    'safe_torque_sign = Safe torque sign valid',
    'safe_torque = Safe torque valid',
    'safe_speed = Safe speed valid',
    'safe_pos = Safe position valid',
    'temp_warn = Temperature warning',
    'SBC = SBC command (state)',
    'restart_ack = Restart acknowledge required',
    'SLS4 = SLS Instance 4 state',
    'SLS3 = SLS Instance 3 state',
    'SLS2 = SLS Instance 2 state',
    'SLS1 = SLS Instance 1 state',
    'u = unused',
    'u = unused',
    'SS2 = SS2 state',
    'SS1 = SS1 state',
    'error = Error active',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'SOS = SOS state',
    'r = reserved',
    'r = reserved',
    'STO = STO state', // 0
];
exports.digitalInputsBitNames = [
    'SNLSS = Shows Negative Limit Switch Status (1=Active, 0=Inactive)',
    'SPLSS = Shows Positive Limit Switch Status (1=Active, 0=Inactive)',
    'SHSS = Shows Home Switch Status (1=Active, 0=Inactive)',
    'SILS = Shows Interlock Status (1=Drive cannot be enabled, 0=Drive can be enabled)',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'DI1 = Digital input 1',
    'DI2 = Digital input 2',
    'DI3 = Digital input 3',
    'DI4 = Digital input 4',
    'DI5 = Digital input 5',
    'DI6 = Digital input 6',
    'DI7 = Digital input 7',
    'DI8 = Digital input 8',
    'DI9 = Digital input 9',
    'DI10 = Digital input 10',
    'DI11 = Digital input 11',
    'DI12 = Digital input 12',
    'DI13 = Digital input 13',
    'DI14 = Digital input 14',
    'DI15 = Digital input 15',
    'DI16 = Digital input 16',
];
exports.digitalOutputsBitNames = [
    'mo_brake = Manual Brake Operation (0=Engage, 1=Disengage)',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'r = reserved',
    'DO1 = Digital output 1',
    'DO2 = Digital output 2',
    'DO3 = Digital output 3',
    'DO4 = Digital output 4',
    'DO5 = Digital output 5',
    'DO6 = Digital output 6',
    'DO7 = Digital output 7',
    'DO8 = Digital output 8',
    'DO9 = Digital output 9',
    'DO10 = Digital output 10',
    'DO11 = Digital output 11',
    'DO12 = Digital output 12',
    'DO13 = Digital output 13',
    'DO14 = Digital output 14',
    'DO15 = Digital output 15',
    'DO16 = Digital output 16',
];
/**
 * Creates an array of {@link BitsViewEntry} objects describing the Safety Statusword
 * object (0x6621) byte-wise bit fields.
 *
 * Each entry represents one byte (8 bits) of the Safety Statusword and contains:
 * - CANopen object index (0x6621)
 * - Subindex corresponding to the byte position (1-based)
 * - Bit size (8)
 * - Bit names for that byte
 * - Optional SMM Launchwave version information
 * - A generated label in the format:
 *   "Safety Statusword Byte X" or
 *   "Safety Statusword V<version> Byte X"
 *
 * If `parameterStructureVersion` is provided, it is converted to the corresponding
 * Launchwave version using `smmParameterStructureVersionToLaunchwaveVersion()`.
 * The resulting version is included in the returned entries and in the generated labels.
 *
 * If `parameterStructureVersion` is not provided, the entries are generated
 * for non-SMM devices and no Launchwave version is associated with them.
 *
 * @param parameterStructureVersion - Optional SMM parameter structure version.
 * If provided, version-specific bit names and labels are generated.
 *
 * @returns Array of {@link BitsViewEntry} objects representing the Safety Statusword bytes.
 */
function createSafetyStatuswordBitsViewEntries(parameterStructureVersion) {
    const bytes = (0, smm_1.getSafetyStatuswordBitNames)(parameterStructureVersion);
    let smmLwVersion = undefined;
    let labelPrefix = 'Safety Statusword';
    if (parameterStructureVersion) {
        smmLwVersion = smmParameterStructureVersionToLaunchwaveVersion(parameterStructureVersion);
        labelPrefix = `Safety Statusword V${smmLwVersion}`;
    }
    return bytes.map((names, i) => ({
        index: 0x6621,
        subindex: i + 1,
        size: 8,
        names,
        smmLwVersion,
        label: labelPrefix + ` Byte ${i + 1}`,
    }));
}
exports.createSafetyStatuswordBitsViewEntries = createSafetyStatuswordBitsViewEntries;
/**
 * Collection of {@link BitsViewEntry} definitions describing commonly used
 * parameter bit fields for the motion master client.
 *
 * Each entry specifies:
 * - CANopen object index and subindex
 * - Bit size (in bits)
 * - Associated bit name array
 * - Human-readable label used in the UI
 *
 * The collection includes:
 * - Encoder feedback status objects
 * - Safety module input diagnostics
 * - CiA 402 Controlword (0x6040) and Statusword (0x6041)
 * - Digital inputs and outputs (0x60FD, 0x60FE)
 * - Supported drive modes (0x6502)
 * - Safety Statusword (0x6621) entries
 *
 * Safety Statusword entries are generated dynamically using
 * {@link createSafetyStatuswordBitsViewEntries}:
 * - `undefined` → Non-SMM devices
 * - `0x0041` → SMM Launchwave V1
 * - `0x0203` → SMM Launchwave V2
 *
 * This array is intended to serve as the central registry of bit-field
 * definitions used for parameter bit visualization.
 */
exports.parameterBitsViewEntries = [
    {
        index: 0x2111,
        subindex: 0x04,
        size: 32,
        names: exports.circuloFeedbackEncoderStatusBitNames,
        label: 'Encoder 1 feedback - Encoder status',
    },
    {
        index: 0x2113,
        subindex: 0x04,
        size: 32,
        names: exports.circuloFeedbackEncoderStatusBitNames,
        label: 'Encoder 2 feedback - Encoder status',
    },
    {
        index: 0x2611,
        subindex: 0x01,
        size: 1,
        names: ['I1 - Input 1'],
        label: 'Safety Module input diagnostics: Input 1',
    },
    {
        index: 0x2611,
        subindex: 0x02,
        size: 1,
        names: ['I2 - Input 2'],
        label: 'Safety Module input diagnostics: Input 2',
    },
    {
        index: 0x6040,
        subindex: 0x00,
        size: 16,
        names: exports.controlwordBitNames,
        label: 'Controlword',
    },
    {
        index: 0x6041,
        subindex: 0x00,
        size: 16,
        names: exports.statuswordBitNames,
        label: 'Statusword',
    },
    {
        index: 0x60fd,
        subindex: 0x00,
        size: 32,
        names: exports.digitalInputsBitNames,
        label: 'Digital Inputs',
    },
    {
        index: 0x60fe,
        subindex: 0x01,
        size: 32,
        names: exports.digitalOutputsBitNames,
        label: 'Digital Outputs - Physical outputs',
    },
    {
        index: 0x60fe,
        subindex: 0x02,
        size: 32,
        names: exports.digitalOutputsBitNames,
        label: 'Digital Outputs - Bit mask',
    },
    {
        index: 0x6502,
        subindex: 0x00,
        size: 32,
        names: exports.supportedDriveModesBitNames,
        label: 'Supported drive modes',
    },
    // Safety statusword entries, generated from the bit name arrays
    ...createSafetyStatuswordBitsViewEntries(0x0041),
    ...createSafetyStatuswordBitsViewEntries(0x0203),
    // NOTE: The non-SMM version of the safety statusword entries is intentionally added at the end of the array to
    // ensure that when looking up entries with a specific SMM version, the versioned entries are found first.
    // This allows for correct fallback behavior where if a version-specific entry is not found,
    // the non-versioned entry can still be returned.
    // This is useful fo UI where parameter structure version is always provided,
    // even for non-SMM devices but can be any value.
    ...createSafetyStatuswordBitsViewEntries(undefined),
];
/**
 * Finds a `BitsViewEntry` from the parameter bits view registry based on
 * a given CANopen object index and subindex, optionally filtering by
 * a specific parameter structure version.
 *
 * This function supports both standard (non-SMM) and SMM parameters:
 * - For non-SMM lookups (no `parameterStructureVersion` provided), it returns
 *   entries without a SMM LW version.
 * - For SMM lookups (`parameterStructureVersion` provided), it maps the
 *   structure version to a SMM LW version and returns the entry matching
 *   that version.
 *
 * @param index - The CANopen object index of the parameter.
 * @param subindex - The CANopen object subindex of the parameter.
 * @param parameterStructureVersion - Optional version of the parameter structure
 *                                    used to select the correct SMM LW entry.
 *
 * @returns The matching `BitsViewEntry` if found; otherwise, `undefined`.
 */
function findBitsViewEntry(index, subindex, parameterStructureVersion) {
    const requestedSmmLwVersion = parameterStructureVersion !== undefined
        ? smmParameterStructureVersionToLaunchwaveVersion(parameterStructureVersion)
        : undefined;
    return exports.parameterBitsViewEntries.find((entry) => {
        // Must match index and subindex
        if (entry.index !== index || entry.subindex !== subindex) {
            return false;
        }
        // Non-SMM: match only non-SMM entries
        if (requestedSmmLwVersion === undefined) {
            return entry.smmLwVersion === undefined;
        }
        // special case when parameter structure version is provided but the entry does not have SMM LW version defined
        if (entry.smmLwVersion === undefined && requestedSmmLwVersion !== undefined) {
            return true;
        }
        // SMM: match only entries with the same Launchwave version
        return entry.smmLwVersion === requestedSmmLwVersion;
    });
}
exports.findBitsViewEntry = findBitsViewEntry;
/**
 * Converts a SMM parameter structure version to the corresponding Launchwave version.
 *
 * @param version - The SMM parameter structure version as a number.
 * @returns The Launchwave version: returns 1 if the version is less than 0x0203, otherwise returns 2.
 */
function smmParameterStructureVersionToLaunchwaveVersion(version) {
    return version < 0x0203 ? 1 : 2;
}
exports.smmParameterStructureVersionToLaunchwaveVersion = smmParameterStructureVersionToLaunchwaveVersion;
//# sourceMappingURL=bits.js.map