%% Decode J1939 Data from MDF-Files
% This example shows you how to import and decode J1939 data from MDF-files in MATLAB for analysis. The MDF-file used in this example was generated from Vector CANoe using the "System Configuration (J1939)" sample. This example also uses the CAN database file, Powertrain_J1939_MDF.dbc, provided with the Vector sample configuration.
%
%% Open the MDF-File
% Open access to the MDF-file using the mdf function.

m = mdf("LoggingMDF_J1939.mf4")

%
%% Identify J1939 CAN Data Frames
% According to the ASAM MDF associated standard for bus logging, the event types defined for a CAN bus system can be "CAN_DataFrame", "CAN_RemoteFrame", "CAN_ErrorFrame", or "CAN_OverloadFrame". J1939 is a protocol built on top of the CAN protocol. A J1939 parameter group (PG) is a set of parameters belonging to the same topic and sharing the same transmission rate. For example, the Electronic Engine Controller 1 (EEC1) PG contains engine speed, engine torque demand percent, actual engine torque percent, etc. Each parameter group is addressed via a unique number called the parameter group number (PGN). J1939 PGs are transmitted as CAN frames, and the MDF-file reflects that a J1939 PG is logged as a "CAN_DataFrame".
% The standard specifies that the channel names of the event structure should be prefixed by the event type name, for instance, "CAN_DataFrame". Typically a dot is used as a separator character to specify the member channels, for instance, "CAN_DataFrame.ID" or "CAN_DataFrame.DataLength".
% Use the channelList function to filter on channel names exactly matching "CAN_DataFrame". A table with information on matched channels is returned.

channelList(m, "CAN_DataFrame", "ExactMatch", true)

% The J1939 powertrain data of interest was logged from the CAN 2 network. The channelList output above shows that the data from CAN 2 network has been stored in channel group 13 of the MDF-file. View the channel group details using the ChannelGroup property.

m.ChannelGroup(13)

%
%% Read J1939 CAN Data Frames From the MDF-File
% Read all data from all channels in channel group 13 into a timetable using the read function. The timetable is structured to follow the ASAM MDF standard logging format. Each row represents one raw CAN frame from the bus, while each column represents a channel within the specified channel group. The channels, such as "CAN_DataFrame.Dir", are named to follow the bus logging standard. However, because timetable column names must be valid MATLAB variable names, they might not be identical to the channel names. Most unsupported characters are converted to underscores. Because "." is not supported in a MATLAB variable name, "CAN_DataFrame.Dir" is altered to "CAN_DataFrame_Dir" in the table.

canData = read(m, 13, m.ChannelNames{13})

%
%% Decode J1939 Parameter Groups Using the DBC-File
% Open the database file using the canDatabase function.

canDB = canDatabase("Powertrain_J1939_MDF.dbc")

% The j1939ParameterGroupTimetable function uses the database to decode the raw CAN Data into PGs, PGNs and signals. The timetable of ASAM standard logging format data is converted into a Vehicle Network Toolbox J1939 parameter group timetable.

j1939PGTimetable = j1939ParameterGroupTimetable(canData, canDB)

% View the signal data stored in the third PG of the timetable, which is one instance of the "EEC1_EMS" PG.

signalData = j1939PGTimetable.Signals{3}

%
%% Repackage and Visualize Signal Values of Interest
% Use the j1939SignalTimetable function to repackage signal data from each unique PGN on the bus into a signal timetable. This example creates two individual signal timetables for the two PGs of interest, "EEC1_EMS" and "TCO1_TCO", from the J1939 PG timetable.

signalTimetable1 = j1939SignalTimetable(j1939PGTimetable, "ParameterGroups", "EEC1_EMS")
signalTimetable2 = j1939SignalTimetable(j1939PGTimetable, "ParameterGroups", "TCO1_TCO")

% You can alternatively choose to convert the whole J1939 PG timetable into a struct containing multiple J1939 signal timetables for each individual PG, and index into it to get data for a particular PG.

signalTimetables = j1939SignalTimetable(j1939PGTimetable)
signalTimetables.EEC1_EMS

% To visualize a signal of interest, variables from the signal timetables can be plotted over time for further analysis. For this example, look at the "EngineSpeed" signal from the "EEC1_EMS" PG.

plot(signalTimetable1.Time, signalTimetable1.EngSpeed, "r")
title("{\itEngineSpeed} signal from {\itEEC1\_EMS} PG", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Engine Speed")

%
%% Close the Files
% Close access to the MDF-file and the DBC-file by clearing their variables from the workspace.

clear m
clear canDB

%
% Copyright 2021 The MathWorks, Inc.