Introduction
Welcome to the TSharkRex programming language reference. This guide will take you from your first program to advanced vehicle integration, covering everything you need to build real-world automotive automation recipes.
What is TSharkRex?
TSharkRex is a PLC-style programming language based on the IEC 61131-3 Structured Text standard. It is purpose-built for XBB automotive diagnostic dongles - small devices that plug into (or are permanently mounted on) a vehicle’s CAN bus and can read signals, make diagnostic requests, and control external outputs such as lights or accessories.
If you have ever worked with industrial automation or PLC programming, TSharkRex will feel familiar. If your background is in general-purpose languages like C, Python, or JavaScript, think of TSharkRex as a real-time control language where your code runs in a continuous loop, reading inputs and writing outputs on every cycle.
What Does It Do?
A TSharkRex program - called a recipe - typically performs two jobs:
- Read vehicle data - listen to CAN bus frames or send UDS (Unified Diagnostic Services) requests to ECUs to obtain signal values such as speed, gear position, high-beam status, ambient light level, and more.
- Control outputs - based on the signal values, drive physical outputs (LEDs, relays, accessories) connected through the dongle or an external PowerUnit module.
Here is a minimal example that turns on an output whenever the vehicle’s high-beam signal is active:
VAR
CANRECV : CAN_RX;
DATA : ARRAY[0..7] OF BYTE;
END_VAR;
VAR_SIGNAL
SIGNAL_HELLJUS : BOOL;
END_VAR;
VAR_OUTPUT
EXTRALJUS : OUTPUT;
END_VAR;
// Read CAN message from vehicle
CANRECV(ENABLE := TRUE, ID := 0x381, EXT := FALSE, DATA := DATA);
// Extract high-beam signal from byte 1, bit 3
SIGNAL_HELLJUS := DATA[1].3;
// Drive auxiliary light output based on high-beam
EXTRALJUS(VALUE := SIGNAL_HELLJUS * 1000, PERIOD := 1000);
Don’t worry about the syntax details yet - we will cover every construct in the chapters ahead. The key takeaway is that TSharkRex lets you express “read a vehicle signal, then control an output” in a compact, readable way.
Target Hardware
TSharkRex programs compile to native machine code for the ARM Cortex-M4 processor found inside all XBB hardware products:
- XBB Dongle - the original OBD-II plug-in dongle.
- XBB Dongle-2 - second-generation dongle with CAN-FD support.
- PP-CAN-FD - a permanently mounted variant for internal CAN bus installations, with full CAN and CAN-FD send/receive support.
The compiler takes care of targeting the correct hardware. You write the same TSharkRex code regardless of device; hardware-specific differences (CAN mode, wake-up method) are handled by the platform and standard libraries.
Language Characteristics
Case Sensitivity
TSharkRex is case-sensitive. Keywords must be written in their canonical form (usually uppercase), and identifiers are distinguished by case:
// These are three DIFFERENT variables:
VAR
speed : INT;
Speed : INT;
SPEED : INT;
END_VAR;
VAR, IF, END_IF, etc.).
Strongly Typed
Every variable must be declared with an explicit type before use. There is no dynamic typing or implicit type coercion. This catches many bugs at compile time rather than at runtime on the vehicle.
No Dynamic Memory
TSharkRex does not have heap allocation, garbage collection, or dynamic data structures. All memory is statically allocated at compile time. This is a deliberate design choice for safety and determinism - in an automotive environment, you need predictable timing and zero risk of memory leaks.
Development Workflow
TSharkRex programs are created and compiled on the TSharkRex Platform at xbb-code.com. The typical workflow looks like this:
- Write your recipe in the online code editor.
- Compile the recipe using the built-in compiler. The compiler runs server-side and produces an ARM binary.
- Install the compiled recipe onto your XBB device via the XBB mobile app over Bluetooth LE.
- Test the recipe on the vehicle. Monitor signals and outputs in real time using the app.
- Iterate - go back to step 1 and refine your logic.
You do not need to install any local toolchain. Everything from editing to compilation happens in the browser or through the platform API.
Execution Model
TSharkRex programs run in a continuous scan cycle, just like a traditional PLC:
// Conceptual execution model (you do NOT write this loop yourself):
//
// 1. Read all inputs (CAN signals, button state, etc.)
// 2. Execute your program code from top to bottom
// 3. Write all outputs (LEDs, relays, etc.)
// 4. Go back to step 1
//
// This cycle repeats as long as the device is powered.
Your code is the body of this loop. You never write an explicit while(true) or main() function - the runtime does that for you. Variable declarations in VAR blocks are initialized once when the program starts; the rest of the code executes on every scan.
This means you should think about your program as a set of rules that are continuously evaluated, rather than a sequence of steps that runs once. For example:
VAR_SIGNAL
SIGNAL_HASTIGHET : INT; // Vehicle speed (km/h)
END_VAR;
VAR
varning_aktiv : INT; // Intermediate variable for output value
END_VAR;
VAR_OUTPUT
VARNINGSLAMPA : OUTPUT; // Warning light
END_VAR;
// Logic: set intermediate variable based on condition
IF SIGNAL_HASTIGHET > 120 THEN
varning_aktiv := 1000; // Full brightness
ELSE
varning_aktiv := 0; // Off
END_IF;
// IMPORTANT: Output must be called EVERY scan cycle!
// Never put the output call inside an IF - it must always run.
VARNINGSLAMPA(VALUE := varning_aktiv, PERIOD := 1000);
A common mistake is to call OUTPUT() only inside an IF block.
This means the output is not updated when the condition is false, which can
cause the output to get stuck in its last state. Always calculate the value first (using an
intermediate variable or an inline expression), then call the output unconditionally
at the end of your code.
WHILE loops
for draining CAN_RX.AVAILABLE run at sub-millisecond speed on the ARM Cortex-M4,
so you can process multiple CAN messages per cycle without any issue.
Recipes and Libraries
In TSharkRex terminology:
- A recipe is a complete program that can be compiled and installed on a device.
- A library is a reusable code module that can be attached to multiple recipes. A library can contain functions, function blocks, and/or plain code snippets. Libraries are added to a recipe before compilation and provide common functionality such as CAN signal reading, wake-up handling, and settings UI.
A set of standard libraries are provided by XBB for common tasks (wake-up, settings, flashers). You add these manually to your recipe’s library list - they are not added automatically. You can also create your own libraries to share code between recipes. See Chapter 24 for the full library structure.
What You Will Learn
This reference guide is organized as a progressive tutorial. Here is what the upcoming chapters cover:
- Hardware Overview - detailed comparison of XBB devices and their capabilities.
- Getting Started - program anatomy, comments, reserved keywords, and your first recipe.
- Data Types - integers, floats, booleans, time, strings, arrays, and pointers.
- Literals & Constants - how to write numbers, hex values, time durations, and more.
Later chapters will cover variables, operators, control flow, functions, function blocks, CAN communication, UDS requests, output control, and advanced topics. By the end, you will be able to write production-quality recipes for any XBB-supported vehicle.