An optional IF clause may be inserted in a FIELD statement following the Size Method. It consists of the keyword IF followed by a call to a Boolean Method. If the method returns FALSE then the FIELD is skipped. The effect of the test may be reversed by inserting the keyword NOT after the IF. Thus, the following are equivalent:
IF (FieldIs NotEqualTo 0 actuator_number)
IF NOT (FieldIs EqualTo 0 actuator_number)
IF clauses may also be put in GROUP statements following the name.
IF clauses depend on Boolean Methods that test for some condition and return True or False. The Boolean method FieldIs checks the value in a field we have already decoded.
FieldIs Method: FieldIs is a Boolean Method that compares the value of a previously decoded field with a constant. The first parameter is a relational operator (LessThan, LessThanOrEqualTo, EqualTo, NotEqualTo, GreaterThan, GreaterThanOrEqualTo). The second parameter is the number that the field value is to be compared to. The name of the field is supplied as the third parameter.
To distinguish between the Set Actuator and Read Sensor commands, we need to find out if the Command field is equal to 1 (Set Actuator) or 2 (Read Sensor). We add IF statements as follows (new items are in bold):
FIELD command_code (Fixed 1 Byte) (Table tableCommands) IN_SUMMARY "Command/Response" 150 "Command"
// if command_code = 1 execute the code in the Group, otherwise skip over Group
GROUP cmdSetActuator IF (FieldIs EqualTo 1 command_code) "Set Actuator"
{
FIELD actuator_number (Fixed 1 Byte) (Decimal) "Actuator Number" VERIFY (FieldIsBetween 1 32)
FIELD actuator_value (Fixed 2 Bytes) (Decimal) "Value to set"
}
// if command_code = 2 execute the code in the Group, otherwise skip over Group GROUP cmdReadSensor IF (FieldIs EqualTo 2 command_code) "Read Sensor"
{
FIELD sensor_number (Fixed 1 Byte) (Decimal) "Sensor Number" VERIFY (FieldIsBetween 1 32)
}
FIELD checksum (Fixed 1 Byte) (Hex) IN_SUMMARY "C'sum" 40 "Checksum" VERIFY (FPChecksum)
The checksum field has also been removed from both groups because it is identical for both commands. Since the Read Sensor group only has one field in it, we could also write the decoder without the Read Sensor group and put the IF clause on the sensor_number field, as shown below, but this makes the decoder more difficult to read.
FIELD command_code (Fixed 1 Byte) (Table tableCommands) IN_SUMMARY "Command/Response" 150 "Command"
GROUP cmdSetActuator IF (FieldIs EqualTo 1 command_code) "Set Actuator"
{
FIELD actuator_number (Fixed 1 Byte) (Decimal) "Actuator Number" VERIFY (FieldIsBetween 1 32)
FIELD actuator_value (Fixed 2 Bytes) (Decimal) "Value to set"
}
FIELD sensor_number (Fixed 1 Byte) IF (FieldIs EqualTo 2 command_code) (Decimal) "Sensor Number" VERIFY (FieldIsBetween 1 32)
FIELD checksum (Fixed 1 Byte) (Hex) IN_SUMMARY "C'sum" 40 "Checksum" VERIFY (FPChecksum)
When you need to handle both sides of a test, the IF and the IF NOT, it is necessary to explicitly test for one condition and then the reverse; there is no ELSE facility to create this effect.
Normally, the label on a GROUP statement is in quotes and cannot be changed. With the LABEL method type, a GROUP can be labeled dynamically.
For example:
FIELD myField (fixed 1 byte) (decimal) "My Field"
GROUP myGroup "My Group"
{
}
The content of the group is unimportant. The interesting thing here is "My Group". Normally that would be static text but if we use a LABEL method as below:
FIELD myField (fixed 1 byte) (decimal) "My Field"
GROUP myGroup LABEL (FromField myfield decimal)
{
}
If myfield has a value of 0x01, the label on myGroup will be '1'. This method works just like a FORMAT method except its output is a label. Let's make it more interesting:
TABLE myTable
{ 0 "zero" }
{ 1 "one" }
ENDTABLE
FIELD myField (fixed 1 byte) (decimal) "My Field"
GROUP myGroup LABEL (Table myTable myfield decimal)
{
}
Again, we have a method that works just like the FORMAT table method except it outputs to the LABEL.
LABEL methods only work for GROUPs, not FIELDs or GROUPFIELDs.