#### Basics

RaceChrono Pro (v6.0 and later) allows users to enter freely typed equations for custom OBD-II channels and CAN-Bus channels.

**Case insensitive:**Variables and functions in equations are case insensitive. It doesn’t matter if you write*POW(2) , Pow(2) or pow(2)*.**Decimal floating point values:**64-bit floating point value. A dot ( . ) is used as decimal separator. Comma ( , ) is reserved as function parameter separator. Constants are interpreted as floating point values only when decimal separator is included ( . ). Example:*12494.0***Decimal integer values:**64-bit integer value. Example:*12494***Hexadecimal integer values:**64-bit integer value. Denoted by 0x at start. Example:*0x30CE = 12494***Spaces:**Spaces can be used to make equations more readable, but they are not required anywhere.**Brackets:**Brackets can be used to mark precedence. For example:*(4 + 2) * 10 = 60*

4 + (2 * 10) = 24**Definition of true and false:**In logical operations and functions, zero is always considered as false. Anything else is considered as true.

#### Operators

Normal C / C++ / Java style operators work, and the operator precedence is same as in these languages.

**Add***5 + 2 = 7***Subtract***5 – 2 = 3***Multiplication***5 * 2 = 10***Division***5 / 2 = 2*

5.0 / 2 = 2.5

5 / 2.0 = 2.5

Notice when dividing two integers, an integer rounded down will be returned.**Modulo***10 % 3 = 1*

-10 % 3 = -1

10 % 3.5 = 3.0**Equal to***11 == 12 = 0 (false)*

11 == 11 = 1 (true)**Not equal to***11 != 12 = 1 (true)*

11 != 11 = 0 (false)**Less than***11 < 12 = 1 (true)*

11 < 11 = 0 (false)**Greater than***12 > 11 = 1 (true)*

11 > 11 = 0 (false)**Less or equal to***11 <= 11 = 1 (true)*

11 <= 10 = 0 (false)**Greater or equal to***11 >= 11 = 1 (true)*

11 >= 12 = 0 (false)**Logical or***0 || 100 = 1 (true)*

0 || 0 = 0 (false)**Logical and***10 && 100 = 1 (true)*

10 && 0 = 0 (false)**Bitwise shift left***1 << 3 = 8***Bitwise shift right***8 >> 3 = 1***Bitwise and***15 & 8 = 8***Bitwise or***8 | 4 = 12***Bitwise xor***15 ^ 8 = 7*

#### Variables and constants

**NaN**

Not-a-number. Floating point value that will not be displayed in gauges and graphs. Can be used in place of an invalid value.**raw**

Raw data output by the OBD-II PID or CAN-Bus PID. Usually you’ll extract bytes (or bits) from the raw variable to an integer, and then apply some maths over it. The following will extract first two bytes to an unsigned integer, and divides that by 100:*bytesToUint(raw, 0, 2) / 100.0*

bytesToUint(0x0101FFFFFFFFFFFF, 0, 2) / 100.0

257 / 100.0 = 2.57**A**and**R2**

1st byte of variable*raw*. Same as*bytesToUInt(raw, 0, 1)***B**and**R3**

2nd byte of variable*raw*. Same as*bytesToUInt(raw, 1, 1)***C**and**R4**

3rd byte of variable*raw*. Same as*bytesToUInt(raw, 2, 1)***D**and**R5**

4th byte of variable*raw*. Same as*bytesToUInt(raw, 3, 1)***E**and**R6**

5th byte of variable*raw*. Same as*bytesToUInt(raw, 4, 1)***F**and**R7**

6th byte of variable*raw*. Same as*bytesToUInt(raw, 5, 1)***G**and**R8**

7th byte of variable*raw*. Same as*bytesToUInt(raw, 6, 1)***H**and**R9**

8th byte of variable*raw*. Same as*bytesToUInt(raw, 7, 1)*

#### Basic functions

These basic functions can be used everywhere equations can be written.

**bitsToUint(source, bitOffset, bitLength)**

Returns unsigned integer value, extracted from the source value. Bit offset 0 is the bit with most significance (msb-0 and big-endian).*raw = 0x 00 11 22 33 44 55 66 77*

raw = 00000000 00010001 00100010 00110011 01000100 01010101 01100110 0111 0111 (binary)

bitsToUint(raw, 24, 16) = 0011 0011 0100 0100 (binary) = 0x3344 = 13124**bitsToInt(source, bitOffset, bitLength)**

Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Bit offset 0 is the bit with most significance (msb-0 and big-endian).*raw = 0x00 11 22 33 44 55 66 77*and

bitsToInt(raw, 24, 16) = 0x3344 = 13124

raw = 0x001122B344556677

bitsToInt(raw, 24, 16) = 0x3344 – 0x8000 = -19644

**bitsToUintLe(source, bitOffset, bitLength)**

Little-endian version of**bitsToUInt**. Returns unsigned integer value, extracted from the source value. Bit offset 0 is the bit with least significance (lsb-0 and little-endian).*r**aw = 0x01 23 45 67 89 AB CD EF*

bitsToUintLe(raw, 28, 16) = 0xB896 = 47254**bitsToIntLe(source, bitOffset, bitLength)**

Little-endian version of**bytesToInt**. Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Bit offset 0 is the bit with least significance (lsb-0 and little-endian).*raw = 0x01 23 45 67 89 AB CD EF*and*bitsToIntLe(raw, 28, 16) = 0xB896 = 47254*– 0x8000 =*raw = 0x01 23 45 67 89 AB CD EF*

bitsToIntLe(raw, 28, 16) =*0x3896**-18282*

**bytesToUint(source, byteOffset, byteLength)**

Returns unsigned integer value, extracted from the source value. Byte offset 0 is the byte with most significance (big-endian).*raw = 0x0011223344556677*

bytesToUint(raw, 3, 2) = 0x3344 = 13124**bytesToInt(source, byteOffset, byteLength)**

Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Byte offset 0 is the byte with most significance (big-endian).*raw = 0x0011223344556677*and

bytesToInt(raw, 3, 2) =*0x3344*= 13124

raw = 0x001122B344556677

bytesToInt(raw, 3, 2) = 0x3344 – 0x8000 = -19644**bytesToUintLe(source, byteOffset, byteLength)**

Little-endian version of**bytesToUint**. Returns unsigned integer value, extracted from the source value. Byte offset 0 is the byte with least significance (little-endian).*raw = 0x0011223344556677*

bytesToUintLe(raw, 3, 2) = 0x4433 = 17459**bytesToIntLe(source, byteOffset, byteLength)**

Little-endian version of**bytesToInt**. Returns signed integer value, extracted from the source value. Negative values are determined by the most significant bit (two’s complement). Byte offset 0 is the byte with least significance (little-endian).*raw = 0x0011223344556677*and

bytesToIntLe(raw, 3, 2) = 0x4433 = 17459

raw = 0x00112233C4556677

bytesToIntLe(raw, 3, 2) = 0x4433 – 0x8000 = -15309**bytesToFloat(source, byteOffset, byteLength)**

Returns a floating point value, extracted from the source value. The source value is encoded in IEEE 754 format using the standard byte order. Only 32-bit and 64-bit values are supported, so the**byteLength**parameter is either 4 or 8.**bytesToFloatLe(source, byteOffset, byteLength)**

Little-endian version of. Returns a floating point value, extracted from the source value. The source value is encoded in IEEE 754 format using the**bytesToFloat***reverse*byte order. Only 32-bit and 64-bit values are supported, so the**byteLength**parameter is either 4 or 8.**float(arg)**

Converts the argument to floating point. Examples:*float(4) = 4.0, float(5) / 2 = 2.5***int(arg)**

Converts the argument to integer. Examples:*int(4.0) = 4, int(5.0) / 2 = 2***pow(base, power)**

The first argument is a base value and second argument is a power raised to the base value. Examples:*pow(x, y) = x*^{y}, pow(3, 2) = 3^{2}= 9**pow2(base)**

The base argument is raised to power of 2. Examples:*pow2(x) = x*^{2}, pow2(3) = 3^{2}= 9**sqrt(arg)**

Returns the square root of the argument. Examples:*sqrt(x) = √x, sqrt(4) = 2***lowPass(source, limit)**

Returns source when source <= limit, otherwise NaN.

*lowPass(100.0, 99.9) = NaN*8

lowPass(99.9, 99.9) = 99.9

lowPass(99.8, 99.9) = 99.**highPass(source, limit)**

Returns source when source >= limit, otherwise NaN.

*highPass(100.0, 99.9) = 100.0*

highPass(99.9, 99.9) = 99.9

highPass(99.8, 99.9) = NaN**min(a, b)**

Returns minimum value of the two arguments.

*max(100.0, 99.9) = 99.9***max(a, b)**

Returns maximum value of the two arguments.

*max(100.0, 99.9) = 100.0*

**if(a, b, c)**

Returns argument c if argument a is 0 (false), otherwise returns argument b.*if(1, 100, 101) = 100*

if(0, 100, 101) = 101

**abs(source)**

Returns absolute value of source.*abs(-10) = 10*

abs(10) = 10

**scale(source, oldA, oldB, newA, newB)**

Scales source value from range [oldA, oldB] to [newA, newB].*scale(50, 0, 100, 0, 200) = 100*

scale(50, 0, 100, 1000, 2000) = 1500

scale(source, oldA, oldB, newA, newB) = ((value – oldA) / (oldB – oldA)) * (newB – newA) + newA

**isNaN(source)**

Returns 1 (true) if the argument is not a number (NaN), otherwise returns 0 (false)*isNaN(100) = 0*

isNaN(NaN) = 1

#### Extended functions

These extended functions can be used with features where channel data is available, such as the DIY Monitor API.

**device(deviceTypeIdentifier)**

Selects a device with device type identifier. List of available device type identifiers can be found here.*device(gps)*selects the GPS deviceselects the OBD-II device

device(obd)**channel(device, channelIdentifier)**

Selects a channel from a device with a channel identifier, and returns the current value of the selected channel. List of available channel identifiers can be found here.*channel(device(gps), speed)*selects the speed from a GPS deviceselects the accelerator position from OBD-II device

channel(device(obd), accelerator_pos)

#### Examples

**2009 BMW 320d oil temperature**

OBD-II PID: 0x2C100458

Source data: 0x49D4

Equation: bytesToUInt(raw, 0, 2) * 0.01 – 100.0

= bytesToUInt(0x49D4, 0, 2) * 0.01 – 100.0

= 18900 * 0.01 – 100.0

= 189.0 – 100.0

= 89.0 celsius**2018 KTM 790 Duke engine RPM**

CAN-Bus PID: 288

Source data: 0x23A0223344556677

Equation: bitsToUInt(raw, 0, 16)

= 9120 RPM