Math Input

Applies to: IOcan · Standalone controller. What this means

Overview

A Math Input combines two inputs with a single operation and reports the result as a new input. Use it to derive a value — a ratio, a sum, a difference — from two existing channels, or to combine two booleans.

Read the formulas before setting anything. Six of the seven operations divide by 1024, and on a divide the infinity value is also an upper clamp. Both catch people out, and both fail quietly.

And, Or and Xor work from firmware 2.1. Before that the firmware had no case for them and selecting one produced no input at all. From 2.1 they are implemented, and an operation the firmware does not recognise raises fault 0x00D1 rather than registering nothing.

Both operands usually originate off-device: a pin on the IOcan pinout or the standalone controller pinout, or a CAN signal from the ECU preset you are running.

Prerequisites

  • A first operand input (the dividend in a divide), referenced by name.
  • A second operand input (the divider in a divide), referenced by name.

Either can be a Constant Value Input where one side is a fixed number. Both must exist and be valid — an unassigned or invalid operand raises fault 0x00D0 and the input is not created.

Add it in the app

  1. Add a new input and choose Math / Divide Input as the type.
  2. Choose the two source inputs.
  3. Give it a clear name (e.g. Speed Ratio).
  4. Pick the operation, then set the multiplier to match — the right value depends on which operation you chose.
  5. On a divide, set the infinity value above the largest result you want to allow. Not to zero.

Settings reference

Setting Meaning Unit Range / values Notes
First operand Left-hand input; the dividend in a divide an existing input Must be assigned and valid.
Second operand Right-hand input; the divider in a divide an existing input Must be assigned and valid.
Operation What is applied Divide, Multiply, Add, Subtract, And, Or, Xor All seven implemented from firmware 2.1.
Multiplier Fixed-point scaling factor sint32 Its meaning differs per operation. On a divide it scales the dividend; on every other operation the result is divided by 1024 afterwards, so 1024 — not 1 — is the neutral value.
Infinity value Divide-by-zero substitute and result ceiling result's unit sint32 Used when the divider is 0, and applied as an upper clamp on every divide result. Divide only.

The formulas

Operation Result
Divide min( (multiplier × first) ÷ second , infinity ), or infinity when second is 0
Multiply first × second × multiplier ÷ 1024
Add (first + second) × multiplier ÷ 1024
Subtract (first − second) × multiplier ÷ 1024
And bitwise AND of the two, × multiplier ÷ 1024
Or bitwise OR of the two, × multiplier ÷ 1024
Xor bitwise XOR of the two, × multiplier ÷ 1024

Two consequences:

  • On everything except Divide, a multiplier of 1 gives you almost zero. The result is divided by 1024, so a plain sum needs a multiplier of 1024. Use 2048 to double the result, 512 to halve it.
  • On Divide the infinity value is a ceiling as well as a guard. Any result larger than it is clamped down to it. Setting it to 0 — which reads like a sensible "report zero when the divider is zero" — clamps every positive result to zero, and the input never does anything else again. Set it above the largest ratio you expect.

All of this is integer arithmetic, evaluated in the order shown. On a divide the multiplier is applied to the dividend before the division, which is what preserves precision — that is the whole reason it exists.

The bitwise operations on booleans

And, Or and Xor operate bit by bit, not on true and false. That distinction disappears for proper booleans and matters everywhere else.

A boolean here is 1024 or 0, and 1024 is a single bit, so bit-by-bit and true-or-false give the same answer: 1024 AND 1024 is 1024, 1024 AND 0 is 0, 1024 XOR 1024 is 0. With a multiplier of 1024, these are logical operators for any two Compare Inputs — two conditions that must both hold, either of which may hold, or exactly one of which holds.

Feed them anything else and you get a bit mask, not a test. 700 AND 300 is 260, which is a real answer to a question nobody asked. Put each side through a Compare Input first if what you mean is a condition.

Common settings

Math Input also uses the shared Name setting. See Common IO settings.

Example — engine-to-output speed ratio in hundredths

  1. Type Math / Divide Input, name Speed Ratio.
  2. First operand Engine Speed, second operand Output Speed.
  3. Operation Divide.
  4. Multiplier 100, so a true ratio of 2.50 reports as 250.
  5. Infinity value 2000 — above any real ratio (20.00), so it only substitutes when the output shaft is stopped and never clamps a live reading.

At standstill the divider is 0 and the input reports 2000. Gate that downstream with a Compare Input if it matters.

Example — two conditions that must both hold

Gate something on brake pressed and speed below a limit.

  1. Two Compare Inputs, Brake On and Below Limit, each reporting 1024 or 0.
  2. Type Math / Divide Input, name Ready To Engage.
  3. First operand Brake On, second operand Below Limit.
  4. Operation And, multiplier 1024.

The result is 1024 only when both are true, and can be used anywhere a boolean is expected. With Or it is true when either holds; with Xor, when exactly one does.

Example — difference between two temperatures

  1. First operand Trans Oil Temp, second operand Coolant Temp.
  2. Operation Subtract.
  3. Multiplier 1024 — the neutral value. With 1 the answer comes out as zero.

Troubleshooting

  • Every result is the infinity value: it is set too low and is clamping. Raise it above the largest result you expect; 0 clamps everything.
  • Result is always zero on anything but Divide: the multiplier is too small. The implicit ÷1024 needs 1024 for no scaling.
  • And or Or gives an odd number rather than 1024 or 0: one of the operands is not a boolean, so you are getting a bit mask. Put it through a Compare Input first.
  • Result looks rounded: integer arithmetic. On a divide, raise the multiplier to keep fractional precision — and raise the infinity value with it.
  • The input does not exist at all: an operand is unassigned or invalid (fault 0x00D0), or the operation is not one the firmware recognises (fault 0x00D1).