This article describes how the Front Lights System (FLS) and the Rear Lights System (RLS) applications work internally, by walking through the Simulink models and describing how signals travel from the CAN bus all the way to the LED strip on the evaluation board. The goal is to give a practical understanding of what each model does, from the moment a command is received up to the moment the corresponding lamp is turned on.
Both nodes are described together because they share the same overall architecture, the same execution pattern, and almost the same set of subsystems. The differences between them are limited to the lighting functions that only make sense on one side of the vehicle (Daytime Running Lights on the front, Stop Lights on the rear) and to a few CAN identifiers. Presenting them side by side keeps the article shorter and highlights how the same design pattern is reused across projects.
Earlier articles in this series introduced the boards, the toolchain, and the general project layout. This article focuses on the application logic.
Each application is implemented as an individual Simulink model, one for the Front Node and one for the Rear Node, structured into communication, control, and output subsystems. From a model perspective, the application can be divided into four logical areas:
Figure 1 - Front Lights main Simulink application
Figure 2 - Rear Lights main Simulink application
The reception area receives CAN frames from the Central Controller and makes the extracted signals available to the rest of the model through shared Data Store Memory blocks. The control area contains one Stateflow chart per lighting function and decides which lamps should be on or off. The output area builds the color pattern from the lamp requests. This separation keeps the model modular and makes it easier to add new lighting functions without changing the reception or the actuation logic.
Each node receives information from three main categories of inputs.
CAN communication is the main source of information for both applications. All messages come from the Central Controller and are defined in the DBC file that ships with each project.
On the Front Lights node the application consumes:
On the Rear Lights node the set is almost the same, with Gear Mode replaced by Press Brake - an 8-bit signal that carries the brake pedal position. The other three messages are shared with the front node.
On top of the CAN traffic, each node reads a digital fault input through a DIO block. The value of this pin is stored in a shared Data Store (FLS_Fault or RLS_Fault) and is consumed by every logic-control chart. When the fault is asserted, the charts switch to a dedicated fault branch and the LEDs display a blink pattern to signal the condition visually.
Before normal operation begins, each model runs an Initialize Function that sets up the peripherals used by the application.
Figure 3 - Initialize Function
This subsystem enables the CAN controller interrupts and moves the controller into the started mode.
Internally, each node performs four main processing activities.
The first step consists of collecting the incoming CAN traffic. Reception is interrupt-driven: a Can_RxIndication handler is registered at the top level of the model and fires a function-call trigger every time a new frame arrives. The trigger runs the CAN Unpack subsystem exactly once and captures the frame identifier, the payload, and the length.
Inside the CAN Unpack subsystem there is one CAN Unpack block per DBC message. Each block decodes the incoming frame and extracts the signals declared in the DBC file.
Figure 4 - Front Lights CAN reception subsystem
Figure 5 - Rear Lights CAN reception subsystem
Overall, the reception subsystem receives the CAN frames, decodes the payload into named signals, and places them into the shared Data Stores.
Every lighting function is implemented as a dedicated Stateflow chart. All charts follow the same skeleton: an Idle state where the lamp is OFF, one or more active states covering the operating modes, and a small fault branch (Fault_Detected and Fault_Detected_Off) that toggles a per-function fault flag whenever the shared fault input is asserted.
The head lights chart reads CCS_ActivateHeadLights and moves from Idle to Head_Lights_LowBeam when the command equals 1, and to Head_Lights_HighBeam when it equals 2. Direct crossovers between the two beams are allowed without going through Idle. When the fault input is asserted, the chart enters the fault branch and toggles Low_Beam and High_Beam to create a blink pattern.
Figure 6 - Head Lights logic control chart
The fog lights chart moves from Idle to Fog_Lights_Active when CCS_ActivateFogLights is 1 and returns to Idle when the command drops back to 0. The fault branch is identical to the one used by the head lights chart.
Figure 7 - Fog Lights logic control chart
The DRL chart only exists on the front node. It keeps the daytime running lights on whenever the vehicle is in a drive gear: Idle moves to DRL_Active when CCS_GearMode is between 1 and 4, and drops back to Idle when the gear returns to 0. Fault handling is identical to the other charts.
Figure 8 - DRL logic control chart (Front Lights only)
The stop lights chart keeps the stop lights on as long as the brake pedal is pressed: Idle transitions to Brake_Active when CCS_PressBrake is different from 0, and returns to Idle when the pedal is released. The fault branch is identical to the other charts.
Figure 9 - Stop Lights logic control chart (Rear Lights only)
The turn lights chart handles both the direction indicators and the hazard lights, and also generates the blinking pattern. It uses parallel states: an outer super-state selects between Idle, Turn_Left_Active, Turn_Right_Active and Hazard_Active, while inside each active super-state a pair of On and Off states swaps every 500 ms using after(0.5, sec) transitions.
From Idle, the chart enters Turn_Left_Active when CCS_TurnLeft is asserted, Turn_Right_Active when CCS_TurnRight is asserted, and Hazard_Active when CCS_ActivateHazardLights is asserted. Direct crossovers between left and right are allowed. When the fault input is asserted, the chart moves into the fault branch.
Figure 10 - Turn Lights logic control chart
The per-function charts do not drive the LED strip directly. They only produce simple lamp requests, and a central Stateflow chart is in charge of turning those requests into a color pattern that the LED strip can display.
Each lighting mode has its own state inside this chart, and every state sets the colors that represent that mode on the strip. For example, the head lights use white, the fog lights light up a few dedicated pixels, and the turn signals move step by step across one side of the strip. The hazard mode reuses the same effect on both sides at the same time. On the front node the chart also includes a state for the daytime running lights, and on the rear node it includes a state for the stop lights.
Once the color pattern is ready, it is passed to a Function-Call Subsystem that sends it to the physical LED strip. This subsystem takes care of the low-level details, so the rest of the model only deals with lighting behavior.
Figure 11 - LED output chart
Alongside the normal lighting behavior, each node also reports its own health to the rest of the system. A local fault input is read at runtime and made available to every logic chart, so the lamps can switch to a fault indication whenever a problem is detected on the board.
The same fault information is also sent back to the Central Controller over CAN, using a short dedicated message. This way, the rest of the vehicle can react to a lighting-node fault without having to check anything manually.
In addition, the model exposes its internal signals to FreeMASTER, which allows the developer to observe the CAN commands, the lamp requests, and the fault flags live during development and troubleshooting.
This article described the internal behavior of the Front Lights and Rear Lights nodes by looking at how information flows through the models. It explained how CAN commands are received, interpreted by dedicated Stateflow charts, and finally turned into the corresponding lighting behavior on the LED strip, while the local fault status is reported back to the Central Controller.
Because both applications share the same architecture, they were presented together. The only real differences are the set of lighting functions specific to each side of the vehicle (DRL on the front, Stop Lights on the rear) and the identifiers used for the fault message.
The next articles in the series will take a closer look at specific parts of these applications, such as the CAN communication, the LED driving, and the tools used to validate and troubleshoot the lighting behavior.