-
-
September 18, 2024 at 12:42 pmSolutionParticipant
Introduction
In previous blogs, we have introduced Swan, the domain-specific language used for modeling in Scade One. We have already introduced the forward block, a loop-like construct for iterative algorithms, and variant types (aka. tagged unions), to define types with multiple possible representations. In this new blog, we want to put it all together and show the usage of these constructs to create and manipulate data structures. This will be illustrated by the decoding of messages for a simplified communication protocol.
Introducing the communication protocol
For this example, we will extend the QuadFlightControl example that is provided with Scade One. It is a flight controller for a quadcopter, taking as input the current and desired attitude (pitch, roll, yaw) and a desired vertical acceleration, and returning a command for the four electric motors. We want to add radio communication to remotely pilot the quadcopter.
The communication protocol consists in sending a list of messages representing commands for the quadcopter:
- Update the desired attitude
- Set the desired vertical acceleration
- Reset to the initial state
Each message starts with a header byte, then a byte identifying the message kind, the payload and finally a footer byte. The message list ends with a specific end byte. Here is the complete description of the protocol:
MessageList:
Type
Description
FullMessage*
List of 0 to 3 messages
uint8
End byte (=
0xff
)FullMessage:
Type
Description
uint8
Message header (=
0xf0
)Message
Message contents
uint8
Message footer (=
0xf1
)Message := UpdateAttitudeMessage | SetAccelMessage | ResetMessage
UpdateAttitudeMessage:
Type
Description
uint8
Message ID (=
0xf2
)int8
Pitch delta
int8
Roll delta
int8
Yaw delta
SetAccelMessage:
Type
Description
uint8
Message ID (=
0xf3
)int8
Acceleration
ResetMessage:
Type
Description
uint8
Message ID (=
0xf4
)A message can be represented using the following variant type in Swan:
type RadioInMsg = UpdateAttitude { pitch: int8, roll: int8, yaw: int8 } | SetVerticalAccel { int8 } | Reset {} | UnknownMsg {}
The definition lists all the possible representations of messages. Variant types are well suited to such use case, where each message has different contents. For instance, the
UpdateAttitude
message contains threeint8
fields, while theReset
message has no contents. We are also adding anUnknownMsg
variant, to represent invalid messages.Decoding messages
Our goal is to parse an input buffer (as an array of bytes) and turn it into the corresponding messages. Since each list contains a variable number of messages, we have to iterate byte by byte on the input buffer to discover messages.
The forward block offers a novel way to handle this. Remember that the
forward
block consists in viewing an input array as a finite flow, on which the sequential logic of Swan can be applied. Inside theforward
, thepre
operator refers to the value during the previous iteration, thusthe previous element when iterating on an array. Even more interestingly, state machines can also be used inside a forward. The current state can change for each element of the array.Here is how it looks for message decoding:
The state machine represents the way a message is read: first read the header, then the id, the payload and finally the footer. Transitions are triggered to change state depending on the value of the current byte.
The forward iterates on the input array
bytes
of sizeM::BUFFER_SIZE
. The forward outputs an array of messages and the number of read messages. They are updated in theFooter
state, when reading the footer byte. Don’t forget that the forward iterates on the input array in a single synchronous cycle/reaction: it will return the result instantaneously. At the bottom of the forward block, you can seeuntil done
part: it means that the forward block stops iterating whendone
is true, which is set when the end byte is read in theEnd
state.In the case of the payload (
Payload
state), a different operator is used depending on the kind of message. In particular, in the case of SetAccelMessage, a second nested automaton is used to read the three different fields:The output message is created using a variant constructor block, that takes as input the three fields that define the
UpdateAttitude
variant. In case of error, if an unexpected byte is read, thenUnknownMsg
is returned (it is the default value of the outputmsg
).We can see that the combination of forward and state machines offer a convenient way to read the input array. We could easily extend this example to handle more complex or variable-length messages.
Handling messages
Now that we have parsed the messages, we can apply the corresponding commands. This is done by iterating on the messages array, again with a forward:
The forward block outputs the new desired attitude and vertical acceleration. We use an
activate when
to update them depending on the current message. Each branch corresponds to one of the possible kind of messages. Typing checks ensure that all messages kinds are handled. Inside each branch, a local flow allows to access the contents of the selected variant (eg.att
in the first branch).Decoding messages with different rates
Let us now suppose that instead of receiving the message list as a whole, it is received in multiple chunks that we want to decode as they come. We can keep the same approach in that case:
We now use a
forward resume
block. It means that the body of the forward is no longer reset at each new activation. In our case, it means that the current state of the internal state machine is kept, so we can continue reading the rest of the message list. The state machine is basically the same, except that it now loops back to theInit
state when all messages have been read.Want to learn more?
You can download the examples from this blog here.
If you want to learn more about the forward block, you can look at the Forward Iteration (ansys.com) section of Scade One user documentation, that goes in more details. Scade One user documentation, like all other Ansys products, can now be accessed freely: Scade One Documentation (ansys.com).
Remember that if you are a SCADE user, you can access Scade One Essential with your existing licenses. Just go the Ansys Download Portal and start experimenting! Also, if you’d to schedule a live demo of Scade One, you may do so by following this link.
About the author
Cédric Pasteur (LinkedIn) is a Senior Product Manager at Ansys. He has been working on Scade One, Ansys’ latest-generation model-based embedded software development product, since its inception. He specializes in programming language theory and its application to safe embedded systems.
-
Introducing Ansys Electronics Desktop on Ansys Cloud
The Watch & Learn video article provides an overview of cloud computing from Electronics Desktop and details the product licenses and subscriptions to ANSYS Cloud Service that are...
How to Create a Reflector for a Center High-Mounted Stop Lamp (CHMSL)
This video article demonstrates how to create a reflector for a center high-mounted stop lamp. Optical Part design in Ansys SPEOS enables the design and validation of multiple...
Introducing the GEKO Turbulence Model in Ansys Fluent
The GEKO (GEneralized K-Omega) turbulence model offers a flexible, robust, general-purpose approach to RANS turbulence modeling. Introducing 2 videos: Part 1Â provides background information on the model and a...
Postprocessing on Ansys EnSight
This video demonstrates exporting data from Fluent in EnSight Case Gold format, and it reviews the basic postprocessing capabilities of EnSight.
- How to Verify a Model on Host with SCADE Test? (Part 4 of 6)
- Scade One – An Open Model-Based Ecosystem, Ready for MBSE
- Scade One – A Visual Coding Experience
- Scade One – Bridging the Gap between Model-Based Design and Traditional Programming
- Introduction to the SCADE Environment (Part 1 of 5)
- How to Generate Code with SCADE Display (Part 6 of 6)
- Using the SCADE Python APIs from your favorite IDE
- Scade One – Democratizing model-based development
- Interface Generic Types – Design a Median with ANSYS SCADE (Part 2 of 6)
- How to integrate multiple SCADE models into one executable
© 2024 Copyright ANSYS, Inc. All rights reserved.