Message Encoding and Decoding
Encoding and decoding a message to be transmitted, using Scade One variant types
Why encoding a message ?
To be transferred through a given channel, a message must often be converted into a given format. The operation which consists in converting a message given in a high-level format into a message in another format, suitable for transmission, is called coding. Decoding is the reverse operation.


To be able to decode the message, the receiver must know the rules applied to transform the initial message into a code.
In the above example, the rule is: replace each letter by its position in alphabet.
H=8, e=5, l=12, o=15
A message with different kinds of information
-
let us consider a more complex message: the information to transfer indicates either a position or an alarm.
- The position message is represented by two integers coordinates: two 16 bits integers.
- The alarm message is represented by a system identifier and an error level. The system identifier is an integer on 16 bits and the error level is an integer on 8 bits
Example of a position message: Position [563, 425]
Example of an alarm message: Alarm {systemID: 825, level:5}
-
To be transferred, this message must be encoded into an array of 5 bytes.
Consequently, the position and the system identifier must be encoded on 2 bytes.
The rules to encode and decode the message are:
- The first cell of the array contains the message kind: 1 for a position, 2 for an alarm
- Each 16 bits integer is converted into two bytes where the result of the integer
division by 256 is the Most Significant Byte (MSB) and its remainder is
the Least Significant Byte (LSB).
Example: v= 563
is written in the encoded message [2, 51]
- For a position, in the encoded message, the first coordinate is encoded in cells 2 and 3, the second coordinate is encoded in cells 4 and 5.
- For an alarm, in the encoded message, the system identifier is encoded in cells 2 and 3, the level is in cell 4 and the last cell corresponds to nothing. Let us fill it with 0
Applying these rules, on Position and Alarm examples we obtain:
- Example of a position message
- Example of an alarm message
Scade One data structures types
The message is represented by a variant type with two constructors: one for the position and one for the alarm.
The position is composed of 2 coordinates represented by an array of two int16.
The alarm is a structure with two fields. The system identifier is stored in the systemID field which is an int16 and the alarm level is stored in level field which is an int8.
- The message variant type:
type message = Position {coord2D} | Alarm {alarm}
- the coord2D array type:
type coord2D = int16^2
- the alarm structure type:
type alarm = {systemID:int16, level:int8}
The encoded message is represented by an array of five cells.
type encodedMessage = uint8^5
Encoding function
According to the kind of the message given by the constructor, the appropriate encoding function is applied.
This can be done thanks to the activate ... when construct, which
applies a pattern matching on the constructor (Position or
Alarm). In order to access the element inside the
constructor, a local variable x is introduced through the
construct {x}
in the pattern matching condition. The variable
x has automatically the appropriate type (resp.
coord2D or alarm).
In each branch, the PositionEncoding transforms a coord2D value into an encoded message and AlarmEncoding transforms an alarm value into an encoded message.

For the position encoding, the first cell of the array is filled with 1. The four integers coming from the translation of the coordinates into uint8 and the 1 integer are given as inputs to an array constructor which creates the whole encoded message.

And the conversion of an int16 into two uint8 is done by the Int16to2uint8 operator:

For the alarm encoding, the first cell of the array is filled with 2. The SystemID field is accessed in the structure and transformed into two uint8. The level is only casted into uint8 and then an array constructor is used to build an encoded message with all of these elements: the message kind, the systemID converted into two uint8, and the system level. A NC constant (NC for Non Coding) is used for the last cell. It is set to 0.
const NC: uint8 = 0

Reverse operation: decoding function
The decoding function to apply differs according to the type of the message.
To decode a Position, the operations described in the following drawing are done:
In Scade one: the two uint8 for each coordinate must be converted into an int16.
And from these two integers, we must create an array and then a Position constructor.
To decode an alarm, the operations described in the following drawing are done:
In Scade One: the two uint8 representing the system identifier must be converted into an int16. And the cell containing the level must be converted into an int8.
Then we construct the alarm directly with the Alarm constructor.
-
The decoding function
The decoding function to apply is given by the first cell content of the encoded message. To apply the dedicated function, an activate ... if is used
How to make the Decoding function more robust
If the first cell is different from 1 or 2, the code given as input to the decoding function is not a message. In this case, the decoding function returns something indicating that the input was not a message. This lead to modify the example in two steps:
Optional message type definition
A new type is defined: optionalMessage with two constructors to represent the two cases: None and Some message
type optionalMessage = None {} | Some {message}
Note: This new type shows that Scade One allows to define a variant type with constructors containing other variant types.Decoding optional message function definition
A new decoding function is defined. It returns either
Some{message}
, if the first cell of the code contains an expected value (i.e. 1 or 2), orNone
in all other cases.The message value is the result of the Decoding function.