The 0x09 frame provides bit-efficient altitude and vertical speed data.
Altitude Packing
Altitude is packed into a uint16_t. The Most Significant Bit (MSB, bit 15) determines the precision:
- MSB = 0: Altitude is in decimeters with a -10000dm offset (0 represents -1000m; 10000 represents 0m; 0x7fff represents 2276.7m).
- MSB = 1: Altitude is in meters with no offset.
Vertical Speed Packing
Vertical speed is represented in cm/s using a logarithmic scale. This provides $\pm$2500cm/s range with 3cm/s precision at low speeds, and 70cm/s precision at speeds around 25m/s.
// Altitude unpack example
int32_t get_altitude_dm(uint16_t packed){
return (packed & 0x8000) ? (packed & 0x7fff) * 10 : (packed - 10000);
}
// Altitude pack example
uint16_t get_altitude_packed (int32_t altitude_dm){
enum {
ALT_MIN_DM = 10000,
ALT_THRESHOLD_DM = 0x8000 - ALT_MIN_DM,
ALT_MAX_DM = 0x7ffe * 10 - 5,
}
if(altitude_dm < -ALT_MIN_DM) return 0;
if(altitude_dm > ALT_MAX_DM) return 0xfffe;
if(altitude_dm < ALT_THRESHOLD_DM) return altitude_dm + ALT_MIN_DM;
return ((altitude_dm + 5) / 10) | 0x8000;
}
// Vertical speed pack/unpack examples
const int Kl = 100;
const float Kr = .026;
int8_t get_vertical_speed_packed (int16_t vertical_speed_cm_s){
return (int8_t)(log(abs(vertical_speed_cm_s)/Kl + 1)/Kr) * sign(vertical_speed_cm_s);
}
int16_t get_vertical_speed_cm_s (int8_t vertical_speed_packed){
return (exp(abs(vertical_speed_packed * Kr)) - 1) * Kl * sign(vertical_speed_packed);
}