MarioM - 20 January 2016 11:55 AM
Hi 234k5hjg,
The definition in fit_profile.cpp is correct. Components act somewhat backwards of what would be expected at first. That definition describes the avg_speed field which expands into the enhanced_avg_speed field and not the enhanced_avg_speed field itself.
The 16 will tell logic within the ExpandComponents function of the Decoder class (in fit_decode.cpp) that it should take 16 bits of data from the avg_speed field when performing the expansion into the enhanced_avg_speed field.
Mario,
big thanks for the explanation. Let's see if I got it right...
Expanding component field:
Message type: 0x37 (55) Monitoring
Field number: 0x18 (24) current_activity_type_intensity
From the profile definition we can see that current_activity_type_intensity expands
to components "activity_type" and "intensity".
In the profile, their definitions are following:
activity_type: type = ENUM, field number = 5, scale = 1.0, offset = 0.0
intensity: type = UINT8,field number = 28, scale = 10.0, offset = 0.0
Let's assume we have field data:
0xa8 (0b00100110)
Expand:
1) Take the current_activity_type_intensity raw value 0xa8 (0b00100110)
2) Read the current_activity_type_intensity component definitions from the profile
3) From the component definitions we can see that
- There are 2 component field destinations 5 (activity_type) and 28 (intensity)
- For activity_type, we have to read first 5 bits of the data (0xa8)
- For intensity, we have to read remaining 3 bits of the data (0xa8)
4) Read the bits as defined in step 3 and "cast" them to value types defind by destination field definition
- activity_type, first 5 bits (0bxxx01000) -> ENUM(8-bits) -> 0x8 -> scale+offset -> (8 / 1.0) - 0.0 = 8.0
- intensity, remaining 3 bits (0b101xxxxx) -> UINT8(8-bits) -> 0x5 -> scale+offset -> (5 / 10.0) - 0.0 = 0.5
So in human readable form - from...
current_activity_type_intensity = 168
...we get two additional fields...
activity_type = 8.0
intensity = 0.5
Another example:
Message type: 0x12 (18) Session
Field number: 0x0e (14) avg_speed
From the profile definition we can see that avg_speed expands
to only one component "enhanced_avg_speed".
In the profile, the definition is following:
enhanced_avg_speed: type = UINT32, field number = 124, scale = 1000.0, offset = 0.0
Let's assume our field data is:
0x0ab6 (0b00001010:10110110)
Expand:
1) Take the avg_speed raw value 0x0ab6 (0b00001010:10110110)
2) Read the avg_speed component definitions from the profile
3) From the component definitions we can see that
- There is 1 component field destination 124 (enhanced_avg_speed)
- For enhanced_avg_speed, we have to read 16 bits of the data (0x0ab6)
4) Read the bits as defined in step 3 and "cast" them to value types defind by destination field definition
- enhanced_avg_speed, 16 bits (0b00001010:10110110) -> UINT32(32-bits) -> 0x00000ab6 -> scale+offset -> (2742 / 1000.0) - 0.0 = 2.742
Again in human readable form - from...
avg_speed = 2.742
...we get an additional field...
enhanced_avg_speed = 2.742
Which leads to the question of what is the point of enhanced_avg_speed?
The only visible differences to avg_speed are
- "name" [avg_speed -> enhanced_avg_speed]
- "type" [UINT16 -> UINT32]
At least to my understanding (if the above decoding/expansion logic is correct) the components
can not "bring more bits" to the original data and therefore the expanded field can not represent
a wider range of values. Which was the original "assumption" made in this thread.
With different scale, let's say 10.0 (in the above avg_speed example) enhanced_avg_speed could be representing a wider range of values? Is that the purpose? Even though the current profile has 1000 and 1000.
Are there any rules for scaling and offsetting (I can see some hints of this in the fit_decode.cpp)? Scale and offset are present in multiple definitions and one should know which to apply and when.
Thanks again.