const {
  parseHexInteger
} = require('./base-utils')

const MODBUS_AREAS = {
  coil: {
    key: 'coil',
    label: '线圈',
    readFunction: '01',
    writeFunction: '05 / 0F',
    access: '读写'
  },
  input: {
    key: 'input',
    label: '输入寄存器',
    readFunction: '04',
    writeFunction: '--',
    access: '只读'
  },
  holding: {
    key: 'holding',
    label: '保持寄存器',
    readFunction: '03',
    writeFunction: '06 / 10',
    access: '读写'
  }
}

const BYTE_POSITIONS = {
  high: {
    label: '高8位',
    shift: 8
  },
  low: {
    label: '低8位',
    shift: 0
  }
}

function hex(address) {
  return `0x${address}`
}

function getRegisterCount(item) {
  return item.registerCount || (item.type === 'float' ? 2 : 1)
}

function getAddressDisplay(address, registerCount) {
  if (registerCount <= 1) return hex(address)

  const start = parseHexInteger(address)
  const end = start + registerCount - 1

  return `${hex(address)}-${hex(end.toString(16).toUpperCase())}`
}

function withArea(items, areaKey, category) {
  return items.map((item) => ({
    ...item,
    ...(() => {
      const byteMeta = item.bytePosition ? BYTE_POSITIONS[item.bytePosition] : null
      const byteLabel = item.byteLabel || (byteMeta ? byteMeta.label : '')
      const registerCount = getRegisterCount(item)
      const addressDisplay = byteLabel
        ? `${getAddressDisplay(item.address, registerCount)} ${byteLabel}`
        : getAddressDisplay(item.address, registerCount)

      return {
        byteLabel,
        byteShift: byteMeta ? byteMeta.shift : null,
        category,
        addressText: hex(item.address),
        addressDisplay,
        registerCount,
        area: MODBUS_AREAS[areaKey]
      }
    })()
  }))
}

const OBS_ADDRESSES = {
  EK1: '30',
  EK2: '31',
  EK3: '32',
  EK4: '33',
  FOC_KFG: '34',
  SPEED_KLPF: '35',
  OBS_FBASE: '36',
  OBS_EA_KS: '37',
  OBS_KP_START: '38',
  OBS_KI_START: '39',
  OBS_KP_RUN1: '3A',
  OBS_KI_RUN1: '3B',
  OBS_KP_RUN2: '3C',
  OBS_KI_RUN2: '3D',
  OBS_KP_RUN3: '3E',
  OBS_KI_RUN3: '3F',
  OBS_KP_RUN4: '40',
  OBS_KI_RUN4: '41',
  DQ_KP_START: '42',
  DQ_KI_START: '43',
  DQ_KP_RUN: '44',
  DQ_KI_RUN: '45',
  TAILWIND_SPEED_KLPF: '46',
  TAILWIND_OBS_EA_KS: '47',
  TAILWIND_OBS_KP: '48',
  TAILWIND_OBS_KI: '49',
  ALIGN_ANGLE: '4A'
}

const CONFIG_ADDRESSES = {
  LD: '60',
  LQ: '62',
  RS: '64',
  POLE_PAIRS: '66',
  SPEED_BASE: '67',
  SPEED_CTRL: '68',
  CURVE_MAX_SPEED: '69',
  CURVE_MIN_SPEED: '6A',
  SOUT_MAX: '6B',
  START_RAMP_INC: '6C',
  START_RAMP_DEC: '6E',
  RUN_RAMP_INC: '70',
  RUN_RAMP_DEC: '72',
  START_VOLT: '74',
  STOP_VOLT: '75',
  CURVE_MAX_VOLT: '76',
  CURVE_MIN_VOLT: '77',
  SPEED_CURVE_K: '78',
  OIL_SPEED: '7A',
  OIL_TIME: '7B'
}

const controlButtonRegisters = withArea([
  { key: 'protocol', address: '00', type: 'uint8_t', name: 'Modbus控制', writeValue: 1, nextName: 'VSP控制', nextWriteValue: 0 },
  { key: 'direction', address: '02', type: 'uint8_t', name: '正转', writeValue: 0, nextName: '反转', nextWriteValue: 1 },
  { key: 'power', address: '01', type: 'uint8_t', name: '开机', writeValue: 1, nextName: '关机', nextWriteValue: 0 },
  { key: 'save', address: '03', type: 'uint8_t', name: '固化', writeValue: 1, momentary: true },
  { key: 'reset', address: '04', type: 'uint8_t', name: '复位', writeValue: 1, momentary: true }
], 'coil', '控制类寄存器')

const speedCommandRegister = withArea([
  { address: CONFIG_ADDRESSES.SPEED_CTRL, type: 'uint16_t', name: '转速命令', unit: 'RPM', inputValue: '', writeValue: '--' }
], 'holding', '参数配置')[0]

const tailwindSwitchRegisters = withArea([
  { address: '05', type: 'uint8_t', name: '顺逆风启用', value: false, writeValue: 0 },
  { address: '06', type: 'uint8_t', name: '预定位启用', value: false, writeValue: 0 }
], 'coil', '顺逆风控制')

const protectionSwitchRegisters = withArea([
  { address: '07', type: 'uint8_t', name: '保护使能', value: false, writeValue: 0 },
  { address: '08', type: 'uint8_t', name: '恢复使能', value: false, writeValue: 0 },
  { address: '09', type: 'uint8_t', name: '电压保护使能', value: false, writeValue: 0 },
  { address: '0A', type: 'uint8_t', name: '电流保护使能', value: false, writeValue: 0 },
  { address: '0B', type: 'uint8_t', name: '堵转保护使能', value: false, writeValue: 0 },
  { address: '0C', type: 'uint8_t', name: '功率保护使能', value: false, writeValue: 0 },
  { address: '0D', type: 'uint8_t', name: '温度保护使能', value: false, writeValue: 0 },
  { address: '0E', type: 'uint8_t', name: '缺相保护使能', value: false, writeValue: 0 },
  { address: '0F', type: 'uint8_t', name: 'PWM丢失保护使能', value: false, writeValue: 0 },
  { address: '10', type: 'uint8_t', name: '串口保护使能', value: false, writeValue: 0 }
], 'coil', '保护')

const estimatorRegisters = withArea([
  { address: OBS_ADDRESSES.EK1, type: 'uint16_t', name: 'OBS_E1K', conversion: '2047 * 3.0 / 125.0 * LQ / TPWM_VALUE * 电流基准 / 电压基准' },
  { address: OBS_ADDRESSES.EK2, type: 'uint16_t', name: 'OBS_E2K', conversion: '2047 * 0.8 * RS * 电流基准 / 电压基准' },
  { address: OBS_ADDRESSES.EK3, type: 'uint16_t', name: 'OBS_E3K', conversion: '255 * 2.5' },
  { address: OBS_ADDRESSES.EK4, type: 'uint16_t', name: 'OBS_E4K', conversion: '((LD - LQ) * TPWM_VALUE * MAX_OMEGA_RAD_SEC) / (LD + RS * TPWM_VALUE)' },
  { address: OBS_ADDRESSES.FOC_KFG, type: 'uint16_t', name: 'FOC_KFG', conversion: 'TIM4频率 / BASE_FREQ / FG_K * 极对数' },
  { address: OBS_ADDRESSES.SPEED_KLPF, type: 'uint16_t', name: 'SPEED_KLPF', conversion: '32767 * 2PI * SPD_BW * TPWM_VALUE' },
  { address: OBS_ADDRESSES.OBS_FBASE, type: 'uint16_t', name: 'OBS_FBASE', conversion: '32767 * TPWM_VALUE' },
  { address: OBS_ADDRESSES.OBS_EA_KS, type: 'uint16_t', name: 'OBS_EA_KS', conversion: '32767 * 2 * SMOMIN * 2PI * BASE_FREQ * TPWM_VALUE / 速度基准' },
  { address: OBS_ADDRESSES.OBS_KP_START, type: 'uint16_t', name: 'OBS_KP_START', conversion: '4095 * 2PI * ATT_COEF * ATO_BW / BASE_FREQ' },
  { address: OBS_ADDRESSES.OBS_KI_START, type: 'uint16_t', name: 'OBS_KI_START', conversion: '32767 * 2PI * ATO_BW * ATO_BW * TPWM_VALUE / BASE_FREQ' },
  { address: OBS_ADDRESSES.OBS_KP_RUN1, type: 'uint16_t', name: 'OBS_KP_RUN1' },
  { address: OBS_ADDRESSES.OBS_KI_RUN1, type: 'uint16_t', name: 'OBS_KI_RUN1' },
  { address: OBS_ADDRESSES.OBS_KP_RUN2, type: 'uint16_t', name: 'OBS_KP_RUN2' },
  { address: OBS_ADDRESSES.OBS_KI_RUN2, type: 'uint16_t', name: 'OBS_KI_RUN2' },
  { address: OBS_ADDRESSES.OBS_KP_RUN3, type: 'uint16_t', name: 'OBS_KP_RUN3' },
  { address: OBS_ADDRESSES.OBS_KI_RUN3, type: 'uint16_t', name: 'OBS_KI_RUN3' },
  { address: OBS_ADDRESSES.OBS_KP_RUN4, type: 'uint16_t', name: 'OBS_KP_RUN4' },
  { address: OBS_ADDRESSES.OBS_KI_RUN4, type: 'uint16_t', name: 'OBS_KI_RUN4' },
  { address: OBS_ADDRESSES.DQ_KP_START, type: 'uint16_t', name: 'DQ_KP_START' },
  { address: OBS_ADDRESSES.DQ_KI_START, type: 'uint16_t', name: 'DQ_KI_START' },
  { address: OBS_ADDRESSES.DQ_KP_RUN, type: 'uint16_t', name: 'DQ_KP_RUN' },
  { address: OBS_ADDRESSES.DQ_KI_RUN, type: 'uint16_t', name: 'DQ_KI_RUN' },
  { address: OBS_ADDRESSES.TAILWIND_SPEED_KLPF, type: 'uint16_t', name: 'SPEED_KLPF_TAILWIND' },
  { address: OBS_ADDRESSES.TAILWIND_OBS_EA_KS, type: 'uint16_t', name: 'OBS_EA_KS_TAILWIND' },
  { address: OBS_ADDRESSES.TAILWIND_OBS_KP, type: 'uint16_t', name: 'OBS_KP_TAILWIND' },
  { address: OBS_ADDRESSES.TAILWIND_OBS_KI, type: 'uint16_t', name: 'OBS_KI_TAILWIND' },
  { address: OBS_ADDRESSES.ALIGN_ANGLE, type: 'uint16_t', name: '预定位角度' }
], 'holding', '估算器配置参数')

const atoBandwidthInputRegisters = [
  { suffix: 'START', name: 'ATO_BW_START', kpAddress: OBS_ADDRESSES.OBS_KP_START, kiAddress: OBS_ADDRESSES.OBS_KI_START, kpName: 'OBS_KP_START', kiName: 'OBS_KI_START' },
  { suffix: 'RUN1', name: 'ATO_BW_RUN1', kpAddress: OBS_ADDRESSES.OBS_KP_RUN1, kiAddress: OBS_ADDRESSES.OBS_KI_RUN1, kpName: 'OBS_KP_RUN1', kiName: 'OBS_KI_RUN1' },
  { suffix: 'RUN2', name: 'ATO_BW_RUN2', kpAddress: OBS_ADDRESSES.OBS_KP_RUN2, kiAddress: OBS_ADDRESSES.OBS_KI_RUN2, kpName: 'OBS_KP_RUN2', kiName: 'OBS_KI_RUN2' },
  { suffix: 'RUN3', name: 'ATO_BW_RUN3', kpAddress: OBS_ADDRESSES.OBS_KP_RUN3, kiAddress: OBS_ADDRESSES.OBS_KI_RUN3, kpName: 'OBS_KP_RUN3', kiName: 'OBS_KI_RUN3' },
  { suffix: 'RUN4', name: 'ATO_BW_RUN4', kpAddress: OBS_ADDRESSES.OBS_KP_RUN4, kiAddress: OBS_ADDRESSES.OBS_KI_RUN4, kpName: 'OBS_KP_RUN4', kiName: 'OBS_KI_RUN4' },
  { suffix: 'TAILWIND', name: 'ATO_BW_TAILWIND', kpAddress: OBS_ADDRESSES.TAILWIND_OBS_KP, kiAddress: OBS_ADDRESSES.TAILWIND_OBS_KI, kpName: 'OBS_KP_TAILWIND', kiName: 'OBS_KI_TAILWIND' }
].map((item) => ({
  ...item,
  type: 'float',
  inputValue: '',
  writeValue: '--',
  kpWriteValue: '--',
  kiWriteValue: '--',
  category: '估算器配置参数',
  addressDisplay: `${hex(item.kpAddress)}/${hex(item.kiAddress)}`,
  area: MODBUS_AREAS.holding
}))

const dqGainInputRegisters = withArea([
  { address: OBS_ADDRESSES.DQ_KP_START, type: 'uint16_t', name: 'DQ_KP_START', protocolName: 'DQ_KP_START', gainType: 'kp' },
  { address: OBS_ADDRESSES.DQ_KI_START, type: 'uint16_t', name: 'DQ_KI_START', protocolName: 'DQ_KI_START', gainType: 'ki' },
  { address: OBS_ADDRESSES.DQ_KP_RUN, type: 'uint16_t', name: 'DQ_KP_RUN', protocolName: 'DQ_KP_RUN', gainType: 'kp' },
  { address: OBS_ADDRESSES.DQ_KI_RUN, type: 'uint16_t', name: 'DQ_KI_RUN', protocolName: 'DQ_KI_RUN', gainType: 'ki' }
], 'holding', '估算器配置参数').map((item) => ({
  ...item,
  inputValue: '',
  writeValue: '--'
}))

const parameterRegisters = withArea([
  { address: CONFIG_ADDRESSES.LD, type: 'float', name: 'LD', unit: 'H', step: '0.000001' },
  { address: CONFIG_ADDRESSES.LQ, type: 'float', name: 'LQ', unit: 'H', step: '0.000001' },
  { address: CONFIG_ADDRESSES.RS, type: 'float', name: 'RS', unit: 'Ω', step: '0.0001' },
  { address: CONFIG_ADDRESSES.POLE_PAIRS, type: 'uint16_t', name: '极对数' },
  { address: CONFIG_ADDRESSES.SPEED_BASE, type: 'uint16_t', name: '速度基准', unit: 'RPM' },
  { address: CONFIG_ADDRESSES.CURVE_MAX_SPEED, type: 'uint16_t', name: '速度最大值', unit: 'RPM' },
  { address: CONFIG_ADDRESSES.CURVE_MIN_SPEED, type: 'uint16_t', name: '速度最小值', unit: 'RPM' },
  { address: CONFIG_ADDRESSES.SOUT_MAX, type: 'uint16_t', name: 'SOUT_MAX', unit: 'A' },
  { address: CONFIG_ADDRESSES.START_RAMP_INC, type: 'float', name: '启动加速加速度', unit: 'RPM/S' },
  { address: CONFIG_ADDRESSES.START_RAMP_DEC, type: 'float', name: '启动减速加速度', unit: 'RPM/S' },
  { address: CONFIG_ADDRESSES.RUN_RAMP_INC, type: 'float', name: '运行加速加速度', unit: 'RPM/S' },
  { address: CONFIG_ADDRESSES.RUN_RAMP_DEC, type: 'float', name: '运行减速加速度', unit: 'RPM/S' },
  { address: CONFIG_ADDRESSES.START_VOLT, type: 'uint16_t', name: '开机电压', unit: 'V' },
  { address: CONFIG_ADDRESSES.STOP_VOLT, type: 'uint16_t', name: '关机电压', unit: 'V' },
  { address: CONFIG_ADDRESSES.CURVE_MAX_VOLT, type: 'uint16_t', name: '调速最高电压', unit: 'V' },
  { address: CONFIG_ADDRESSES.CURVE_MIN_VOLT, type: 'uint16_t', name: '调速最低电压', unit: 'V' },
  { address: CONFIG_ADDRESSES.SPEED_CURVE_K, type: 'float', name: '调速曲线斜率' },
  { address: CONFIG_ADDRESSES.OIL_SPEED, type: 'uint16_t', name: '上油转速', unit: 'RPM' },
  { address: CONFIG_ADDRESSES.OIL_TIME, type: 'uint16_t', name: '上油时间', unit: 's' }
], 'holding', '参数配置')

const parameterInputNames = [
  'LD',
  'LQ',
  'RS',
  '极对数',
  '速度基准'
]

const configParameterInputNames = [
  '开机电压',
  '关机电压',
  '速度最小值',
  '速度最大值',
  'SOUT_MAX',
  '调速最低电压',
  '调速最高电压'
]

const speedLoopExtraInputNames = [
  '启动加速加速度',
  '启动减速加速度',
  '运行加速加速度',
  '运行减速加速度'
]

const oilParameterInputNames = [
  '上油转速',
  '上油时间'
]

const prepositionParameterInputNames = [
  '预定位角度'
]

const parameterByName = parameterRegisters.reduce((result, item) => {
  result[item.name] = item
  return result
}, {})
const motorParameterInputRegisters = parameterInputNames
  .map((name) => parameterByName[name])
  .filter(Boolean)
  .map((item) => ({
    ...item,
    inputValue: item.inputValue || '',
    writeValue: item.writeValue || '--'
  }))

const parameterInputRegisters = configParameterInputNames
  .map((name) => parameterByName[name])
  .filter(Boolean)
  .map((item) => ({
    ...item,
    inputValue: item.inputValue || '',
    writeValue: item.writeValue || '--'
  }))

const speedSlopeRegister = {
  ...parameterByName['调速曲线斜率'],
  inputValue: '',
  writeValue: '--'
}

const speedLoopExtraRegisters = speedLoopExtraInputNames
  .map((name) => parameterByName[name])
  .filter(Boolean)
  .map((item) => ({
    ...item,
    inputValue: '',
    writeValue: '--'
  }))

const oilParameterInputRegisters = oilParameterInputNames
  .map((name) => parameterByName[name])
  .filter(Boolean)
  .map((item) => ({
    ...item,
    inputValue: '',
    writeValue: '--'
  }))

const prepositionParameterInputRegisters = prepositionParameterInputNames
  .map((name) => estimatorRegisters.find((item) => item.name === name))
  .filter(Boolean)
  .map((item) => ({
    ...item,
    inputValue: '',
    writeValue: '--'
  }))

function isAtoGainRegister(item) {
  return item.name.startsWith('OBS_KP_') || item.name.startsWith('OBS_KI_')
}

function isDqGainRegister(item) {
  return item.name.startsWith('DQ_KP_') || item.name.startsWith('DQ_KI_')
}

const calculatedParameterRegisters = [
  ...estimatorRegisters.filter((item) => !isAtoGainRegister(item) && !isDqGainRegister(item) && !prepositionParameterInputNames.includes(item.name)),
  ...parameterRegisters.filter((item) => !parameterInputNames.includes(item.name)
    && !configParameterInputNames.includes(item.name)
    && !speedLoopExtraInputNames.includes(item.name)
    && !oilParameterInputNames.includes(item.name)
    && !prepositionParameterInputNames.includes(item.name)
    && item.name !== '调速曲线斜率')
].map((item) => ({
  ...item,
  inputValue: '',
  writeValue: '--'
}))

const protectionRegisters = withArea([
  { address: '7C', type: 'uint16_t', name: '硬件过流值', unit: 'A' },
  { address: '7D', type: 'uint16_t', name: '软件过流值', unit: 'A', conversion: '32767 * 限制值 / 电流基准' },
  { address: '7E', type: 'uint16_t', name: '过压保护值', unit: 'V', conversion: '32767 * 限制值 / 电压采样最大值' },
  { address: '7F', type: 'uint16_t', name: '欠压保护值', unit: 'V' },
  { address: '80', type: 'uint16_t', name: '过压恢复值', unit: 'V' },
  { address: '81', type: 'uint16_t', name: '欠压恢复值', unit: 'V' },
  { address: '82', type: 'uint16_t', name: '速度限制最大值', unit: 'RPM', conversion: '32767 * 限制值 / 速度基准' },
  { address: '83', type: 'uint16_t', name: '速度限制最小值', unit: 'RPM' },
  { address: '84', type: 'uint16_t', name: '反电动势低阈值' },
  { address: '85', type: 'uint16_t', name: '反电动势高阈值' },
  { address: '86', type: 'uint16_t', name: '速度中间值', unit: 'RPM' },
  { address: '87', type: 'uint16_t', name: '功率保护值', unit: 'W', conversion: '32767 * 保护值 / 电流采样最大值 / 电压采样最大值' },
  { address: '88', type: 'uint16_t', name: '功率保护时间', unit: 'ms' },
  { address: '89', type: 'uint16_t', name: '温度保护值', unit: '℃' },
  { address: '8A', type: 'uint16_t', name: '温度恢复值', unit: '℃' },
  { address: '8B', type: 'uint16_t', name: '温度保护时间', unit: 'ms' },
  { address: '8C', type: 'uint16_t', name: '故障恢复时间', unit: 's' },
  { address: '8D', type: 'uint16_t', name: '串口丢失检测时间', unit: 'ms' }
], 'holding', '保护配置')

const readonlyParamRegisters = withArea([
  { address: 'A8', type: 'ascii', name: '芯片型号', displayValue: '--', registerCount: 4, hideMeta: true },
  { address: 'AC', type: 'ascii', name: '型号', displayValue: '--', registerCount: 8, hideMeta: true },
  { address: 'A0', type: 'uint8_t', name: '载波频率', unit: 'KHz', displayValue: '--', bytePosition: 'high' },
  { address: 'A0', type: 'uint8_t', name: '基准电压', unit: 'V', displayValue: '--', bytePosition: 'low' },
  { address: 'A1', type: 'uint16_t', name: '运放倍数', displayValue: '--' },
  { address: 'A2', type: 'uint16_t', name: '采样电阻', unit: 'mΩ', displayValue: '--' },
  { address: 'A3', type: 'uint16_t', name: '全区 Flash 校验码', displayValue: '--' },
  { address: 'A4', type: 'float', name: '母线电压分压比', displayValue: '--' },
  { address: 'A6', type: 'float', name: '模拟输入电压分压比', displayValue: '--' }
], 'input', '只读参数寄存器')

const userStatusRegisters = Array.from({ length: 10 }, (_, index) => ({
  address: (0xD3 + index).toString(16).toUpperCase(),
  type: 'uint16_t',
  name: `用户状态字 ${index + 1}`
}))

const statusRegisters = withArea([
  { address: 'C0', type: 'uint8_t', name: '状态机', bytePosition: 'high' },
  { address: 'C0', type: 'uint8_t', name: '故障码', bytePosition: 'low' },
  { address: 'C1', type: 'int16_t', name: 'UQ' },
  { address: 'C2', type: 'int16_t', name: 'UD' },
  { address: 'C3', type: 'int16_t', name: 'IQ' },
  { address: 'C4', type: 'int16_t', name: 'ID' },
  { address: 'C5', type: 'int16_t', name: 'A 相电流' },
  { address: 'C6', type: 'int16_t', name: 'B 相电流' },
  { address: 'C7', type: 'int16_t', name: 'C 相电流' },
  { address: 'C8', type: 'uint16_t', name: '相电流最大值' },
  { address: 'C9', type: 'uint16_t', name: '相电流最小值' },
  { address: 'CA', type: 'int16_t', name: '估算速度', unit: 'RPM' },
  { address: 'CB', type: 'uint16_t', name: '估算反电动势' },
  { address: 'CC', type: 'uint16_t', name: '母线电压', unit: '0.1V', displayUnit: 'V' },
  { address: 'CD', type: 'uint16_t', name: '母线电流', unit: '0.01A', displayUnit: 'A' },
  { address: 'CE', type: 'uint16_t', name: '估算功率', unit: 'W' },
  { address: 'CF', type: 'uint16_t', name: 'NTC 温度', unit: '℃', displayUnit: '℃' },
  { address: 'D0', type: 'uint16_t', name: '模拟输入电压', unit: 'V', displayUnit: 'V' },
  { address: 'D1', type: 'uint16_t', name: '频率', unit: 'Hz', displayUnit: 'Hz' },
  { address: 'D2', type: 'uint16_t', name: '占空比', unit: '%', displayUnit: '%' },
  ...userStatusRegisters
], 'input', '状态类寄存器')

function getByteRegisterValue(item, wordValue) {
  if (!item || item.type !== 'uint8_t' || !item.bytePosition) return wordValue

  return (Number(wordValue) >> item.byteShift) & 0xFF
}

module.exports = {
  controlButtonRegisters,
  speedCommandRegister,
  atoBandwidthInputRegisters,
  dqGainInputRegisters,
  oilParameterInputRegisters,
  prepositionParameterInputRegisters,
  motorParameterInputRegisters,
  parameterInputRegisters,
  calculatedParameterRegisters,
  protectionSwitchRegisters,
  protectionRegisters,
  readonlyParamRegisters,
  speedLoopExtraRegisters,
  speedSlopeRegister,
  statusRegisters,
  tailwindSwitchRegisters,
  getByteRegisterValue,
  getRegisterCount
}
