
How do you specify an Altia library for Stateflow code to use Altia API calls?

To specify an Altia API library for Stateflow code to use Altia API calls, begin by opening the
Model Explorer in Simulink (it is a tool bar icon in the Simulink window).
Select the
sfun icon in the middle
Contents of: <MODEL_NAME> pane (it is usually at the bottom of the pane). Press the
Target Options button in the right pane now labeled
Stateflow Target Builder. Go to the
Libraries tab in the new
Stateflow sfun Target Options window.
Necessary custom libraries are an Altia API library and a Windows user32 library as in:
C:\usr\altia806mr9b3\lib\ms32\libddeMDoption.lib
user32.lib
Get the
user32.lib library from the computer's installation of Microsoft Visual Studio or if this is too difficult to do, use the
<MATLAB_ROOT>/toolbox/altia/bin/user32.lib copy. To make it easy, put the copy of
user32.lib in the current working directory (which is how it is shown in the above example because no path is given for
user32.lib).
If the compiler is Visual Studio 6, the Altia API library can be
<ALTIAHOME>/lib/ms32/libdde.lib or
liblan.lib and make sure there is a path in the
Include Paths tab of the Stateflow sfun Target Options window referencing the same directory. Note, however, the example uses
libddeMDoption.lib. Continue to the next paragraph to learn why.
If the compiler is Visual Studio 2005 or newer, the Altia API library must be
<ALTIAHOME>/lib/ms32/libddeMDoption.lib or
liblanMDoption.lib and make sure there is a path in the
Include Paths tab referencing the same directory. Note that integer (i.e.,
lib/ms32) versions of these libraries are only available in Altia Design 8.06 DeepScreen MR9 Beta 3 or newer. If the Altia Design software is older than this release, no
lib/ms32 versions exist, only
libfloat/ms32 versions. Use the
libfloat/ms32 versions in these cases, but only pass whole number event values to/from the Altia API functions if the plan is to migrate the model to an RTW executable. For portable results, declare values passed to/from the Altia API functions as type
AltiaEventType or cast values to
AltiaEventType.
The
lib[dde|lan]MDoption.lib library is necessary with VS 2005 otherwise there are
libc.lib errors because this version of the libc library is referenced in
libdde.lib and
liblan.lib. Or, there are
libcmt.lib errors if there is an attempt to use
liblanMT.lib. These errors occur when the Stateflow coder attempts to link the compiled Stateflow code into a DLL. Only
lib[dde|lan]MDoption.lib works because it is built with the
/MD option. This is necessary with Stateflow because the Stateflow code gets built as a DLL (the
/MD option means
Multi-threaded
Dll target). Long-time users might try to specify
libsdde.lib because it resides in the local
<model_name>_grt_rtw folder after running the Altia connection
altiartwsetup Matlab script for a RTW build. Unfortunately,
libsdde.lib also causes link errors when the Stateflow DLL builds with Visual Studio 2005 or newer.
Let's move on to the Stateflow code itself. It must open a connection to Altia somewhere in the Stateflow code using a specific port string as the first argument. If linking with a DDE version of the Altia API library (e.g.,
libddeMDoption.lib), use a logical name for the port (but not the name of the Altia block in Simulink, it is a bad choice, sorry). The code should look like:
Code:
AtSuppressErrors(1);
altia_id = AtOpenConnection("MyAltia1", NULL, 0, NULL);
AtRetryCount(altia_id, 0);
AtCacheOutput(altia_id, 0);
If linking with a LAN version of the Altia API library (e.g.,
liblanMDoption.lib), try using the default Altia socket for the local machine unless there is a good reason to use a different socket (you are in somewhat uncharted territory using a LAN library so there should be a very good reason for using it). In this case, the code might look like:
Code:
AtSuppressErrors(1);
altia_id = AtOpenConnection("127.0.0.1:5100", NULL, 0, NULL);
AtRetryCount(altia_id, 0);
AtCacheOutput(altia_id, 0);
Whether using a DDE or LAN Altia API library, this example code should not go into the default state of a Stateflow chart because it might get initialized before the Simulink Altia block gets initialized. It can go into a state that has a transition directly from the default state. The Simulink Altia block must get initialized first so that it can start the Altia Runtime before the Stateflow call to
AtOpenConnection().
In Stateflow termination code (open the
Termination Code tab in the
Stateflow sfun Target Options window), there should be a call to:
Code:
AtCloseConnection(altia_id);
The include for
altia.h and the definition of
altia_id can go in the Stateflow include code (open the
Include Code tab in the
Stateflow sfun Target Options window). For example:
Code:
#include <altia>
AtConnectId altia_id;
NOTE:When it comes time to do an RTW build, the contents of the sfun
Include Code should go into the RTW Custom Code
Source file: section. Sfun
Source files should go into RTW
Source files. Sfun
Initialize Code shoud go into to RTW
Initialize function. Sfun
Terminate Code to RTW
Terminate function.
Aside from adding actual Altia API calls into states of the Stateflow model, these are the basics that have to happen within Simulink and Stateflow.
Now also edit the
altia_block_name.xmc file with Notepad and change the
start line to include a
port argument with the same content as the string passed to
AtOpenConnection() except do not include the double-quotes. For example:
Code:
start altia_block_name.dsn port MyAltia1
Or if using a LAN version of the Altia API:
Code:
start altia_block_name.dsn port 127.0.0.1:5100
It is actually possible to have a separate line for the
port designation, but the .mxc file comment header says to add it to the
start line if a
start line already exists.
Save modifications to the .mxc file before starting a simulation.
If these steps are not taken, the DLL created for the Stateflow charts will have problems when it executes for one or more of the following reasons:
1. If it cannot connect to Altia because
AtOpenConnection() is missing or fails (i.e., returns a value less than 0 because no Altia Runtime with the given port is available), this can cause big problems.
2. If retry count is not set to 0 with a call to
AtRetryCount(altia_id,0), the Altia API library tries to do an exit when it looses contact with Altia. This is very bad when running from a DLL (which is how the Stateflow charts execute in simulation mode).
3. If caching is not turned off with
AtCacheOutput(altia_id, 0), the events sent from Stateflow with
AtSendEvent() or
AtSendText() calls might not be seen immediately in Altia because they get buffered in the Altia API.
4. If the Stateflow code is not disconnected from the Altia Runtime with
AtCloseConnection(altia_id) when the simulation finishes, the Stateflow code may continue to talk to the wrong Altia Runtime the next time the simulation executes.
Note that once a port name is specified in the .mxc file, the ability to connect to the Altia editor during a simulation is lost. The Altia block always opens an Altia Runtime with the given port when it sees a
start line with a
port option or even a
start line with a separate
port line.
Be careful assigning a port name that is the same as the base name of the design file. Take the example where the design file name is
AltiaDesign.dsn and the
AtOpenConnection() call in Stateflow looks like:
Code:
altia_id = AtOpenConnection("AltiaDesign", NULL, 0, NULL);
and the
start line in the .mxc file looks like:
Code:
start AltiaDesign.dsn port AltiaDesign
This setup works fine as long as the Altia editor is not open for the Altia block. If the Altia editor is open, the Stateflow
AtOpenConnection() call connects to the Altia editor, but the Altia block in Simulink still starts an Altia Runtime and communicates with it rather than the Altia editor. To use the Altia editor in this type of configuration, temporarily suppress the starting of Altia Runtime by commenting out the
start line in the .mxc file. This is done by placing a
# character at the beginning of the line.
To just use Altia API calls in Stateflow and not an Altia Simulink block simultaneously, the Stateflow code should do
AtStartInterface() instead of
AtOpenConnection() and use
AtStopInterface(altia_id) in the termination code instead of
AtCloseConnection(altia_id). A call to AtStartInterface would look like:
Code:
altia_id = AtStartInterface("altia_design.dsn", NULL, 0, 0, NULL);