12#define ADSBLIB_STR(x) ADSBLIB_STR_(x)
13#define ADSBLIB_STR_(x) #x
15const char *adsb_version_string(
void)
17 return ADSBLIB_STR(ADSBLIB_VERSION_MAJOR)
"."
18 ADSBLIB_STR(ADSBLIB_VERSION_MINOR)
"."
19 ADSBLIB_STR(ADSBLIB_VERSION_PATCH);
29#define ADSB_CPR_BITS 17U
30#define ADSB_CPR_MOD (1U << ADSB_CPR_BITS)
38static double adsb_pi(
void)
43static bool is_valid_icao(uint32_t icao)
45 return (icao <= ADSB_ICAO_MAX);
48static bool is_valid_latitude(
double latitude_deg)
50 return isfinite(latitude_deg) && (latitude_deg >= -90.0) && (latitude_deg <= 90.0);
53static bool is_valid_longitude(
double longitude_deg)
55 return isfinite(longitude_deg) && (longitude_deg >= -180.0) && (longitude_deg <= 180.0);
58static bool is_valid_altitude(int32_t altitude_ft)
60 return (altitude_ft >= -1000) && (altitude_ft <= 60000);
63static bool is_valid_speed(
double speed_kt)
65 return isfinite(speed_kt) && (speed_kt >= 0.0);
68static bool is_valid_track(
double track_deg)
70 return isfinite(track_deg) && (track_deg >= 0.0) && (track_deg < 360.0);
73static bool is_valid_vertical_rate(int32_t vr_fpm)
75 return (vr_fpm >= -32640) && (vr_fpm <= 32640);
78static bool is_valid_emergency_state(adsb_emergency_state_t state)
80 return (state >= ADSB_EMERGENCY_NONE) &&
81 (state <= ADSB_EMERGENCY_DOWNED_AIRCRAFT);
84static bool is_valid_mode_a_code(uint16_t mode_a_code)
86 return mode_a_code <= 07777U;
89static bool is_valid_altitude_source(adsb_altitude_source_t source)
91 return (source == ADSB_ALTITUDE_SOURCE_MCP) ||
92 (source == ADSB_ALTITUDE_SOURCE_FMS);
95static enc_status_t encode_target_altitude(int32_t altitude_ft, uint32_t *altitude_field)
99 if (altitude_field == NULL)
101 return ENC_INVALID_SELECTED_ALTITUDE;
103 if (altitude_ft == -1)
105 *altitude_field = 0U;
108 if ((altitude_ft < 0) || (altitude_ft > 65472))
110 return ENC_INVALID_SELECTED_ALTITUDE;
113 raw = lround((
double)altitude_ft / 32.0) + 1L;
114 if ((raw < 1L) || (raw > 2047L))
116 return ENC_INVALID_SELECTED_ALTITUDE;
119 *altitude_field = (uint32_t)raw;
123static enc_status_t encode_barometric_pressure(
double pressure_mbar, uint32_t *pressure_field)
127 if (pressure_field == NULL)
129 return ENC_INVALID_BARO_PRESSURE;
131 if (pressure_mbar == -1.0)
133 *pressure_field = 0U;
136 if (!isfinite(pressure_mbar) || (pressure_mbar < 800.0) || (pressure_mbar > 1208.0))
138 return ENC_INVALID_BARO_PRESSURE;
141 raw = lround((pressure_mbar - 800.0) / 0.8) + 1L;
142 if ((raw < 1L) || (raw > 511L))
144 return ENC_INVALID_BARO_PRESSURE;
147 *pressure_field = (uint32_t)raw;
151static uint32_t encode_mode_a_code(uint16_t mode_a_code)
153 uint32_t a = (mode_a_code >> 9U) & 0x7U;
154 uint32_t b = (mode_a_code >> 6U) & 0x7U;
155 uint32_t c = (mode_a_code >> 3U) & 0x7U;
156 uint32_t d = mode_a_code & 0x7U;
159 return ((a & 4U) << 5U) |
179static uint32_t encode_movement(
double speed_kt)
181 static const uint32_t bin_lb_code[6] = { 2U, 9U, 13U, 39U, 94U, 109U };
182 static const double bin_lb_kt[6] = { 0.125, 1.0, 2.0, 15.0, 70.0, 100.0 };
183 static const double bin_step_kt[6] = { 0.125, 0.25, 0.5, 1.0, 2.0, 5.0 };
184 if (speed_kt < 0.125)
189 if (speed_kt >= 175.0)
194 for (
int i = 5; i >= 0; --i)
196 if (speed_kt >= bin_lb_kt[i])
198 return bin_lb_code[i] + (uint32_t)floor((speed_kt - bin_lb_kt[i]) / bin_step_kt[i]);
205static double pos_mod(
double value,
double modulus)
214 r = fmod(value, modulus);
223static void frame_set_bits(uint8_t frame[ADSB_FRAME_BYTES], uint32_t start_bit, uint32_t num_bits, uint32_t value)
227 for (i = 0U; i < num_bits; ++i)
229 uint32_t dst_bit = start_bit + i;
230 uint32_t dst_byte = dst_bit / 8U;
231 uint32_t dst_bit_in_byte = 7U - (dst_bit % 8U);
232 uint32_t src_bit = num_bits - 1U - i;
233 uint8_t bit_value = (uint8_t)((value >> src_bit) & 0x1U);
237 frame[dst_byte] = (uint8_t)(frame[dst_byte] | (uint8_t)(1U << dst_bit_in_byte));
241 frame[dst_byte] = (uint8_t)(frame[dst_byte] & (uint8_t)~(uint8_t)(1U << dst_bit_in_byte));
246static size_t callsign_len8(
const char callsign[ADSB_CALLSIGN_LEN + 1])
250 for (i = 0U; i < (ADSB_CALLSIGN_LEN + 1U); ++i)
252 if (callsign[i] ==
'\0')
258 return ADSB_CALLSIGN_LEN + 1U;
261static int callsign_char_to_6bit(
char c)
263 if ((c >=
'A') && (c <=
'Z'))
265 return (
int)(c -
'A') + 1;
268 if ((c >=
'0') && (c <=
'9'))
270 return (
int)(c -
'0') + 48;
281static enc_status_t encode_callsign(
const char in_callsign[ADSB_CALLSIGN_LEN + 1], uint8_t out_codes[ADSB_CALLSIGN_LEN])
286 if (in_callsign == NULL)
288 return ENC_INVALID_ARGUMENT;
291 len = callsign_len8(in_callsign);
292 if (len > ADSB_CALLSIGN_LEN)
294 return ENC_INVALID_CALLSIGN;
297 for (i = 0U; i < ADSB_CALLSIGN_LEN; ++i)
299 char c = (i < len) ? in_callsign[i] :
' ';
300 int code = callsign_char_to_6bit(c);
304 return ENC_INVALID_CALLSIGN;
307 out_codes[i] = (uint8_t)code;
313static enc_status_t encode_altitude_12bit(int32_t altitude_ft, uint32_t *alt_code)
319 if ((alt_code == NULL) || !is_valid_altitude(altitude_ft))
321 return ENC_INVALID_ALTITUDE;
328 if (altitude_ft > 50175)
330 return ENC_INVALID_ALTITUDE;
333 n = (altitude_ft + 1000) / 25;
334 if ((n < 0) || (n > 2047))
336 return ENC_INVALID_ALTITUDE;
339 high = (uint32_t)((n >> 4) & 0x7FU);
340 low = (uint32_t)(n & 0x0FU);
342 *alt_code = (high << 5) | (1U << 4) | low;
350void adsb_frame_clear(uint8_t frame[ADSB_FRAME_BYTES])
354 (void)memset(frame, 0, ADSB_FRAME_BYTES);
358void adsb_frame_to_hex(
const uint8_t frame[ADSB_FRAME_BYTES],
char hex_string[29])
360 static const char hex_lut[] =
"0123456789ABCDEF";
363 if ((frame == NULL) || (hex_string == NULL))
368 for (i = 0U; i < ADSB_FRAME_BYTES; ++i)
370 hex_string[(2U * i)] = hex_lut[(frame[i] >> 4) & 0x0FU];
371 hex_string[(2U * i) + 1U] = hex_lut[frame[i] & 0x0FU];
374 hex_string[28] =
'\0';
377uint32_t adsb_crc24(
const uint8_t *data, uint32_t num_bits)
381 const uint32_t poly = 0xFFF409U;
388 for (i = 0U; i < num_bits; ++i)
390 uint32_t byte_idx = i / 8U;
391 uint32_t bit_idx = 7U - (i % 8U);
392 uint32_t bit = (data[byte_idx] >> bit_idx) & 0x1U;
393 uint32_t top = (crc >> 23U) & 0x1U;
395 crc = (crc << 1U) & 0xFFFFFFU;
396 if ((top ^ bit) != 0U)
402 return crc & 0xFFFFFFU;
405void adsb_apply_crc(uint8_t frame[ADSB_FRAME_BYTES])
414 crc = adsb_crc24(frame, 88U);
416 frame[11] = (uint8_t)((crc >> 16U) & 0xFFU);
417 frame[12] = (uint8_t)((crc >> 8U) & 0xFFU);
418 frame[13] = (uint8_t)(crc & 0xFFU);
421bool adsb_verify_crc(
const uint8_t frame[ADSB_FRAME_BYTES])
423 uint32_t expected_crc;
431 expected_crc = adsb_crc24(frame, 88U);
432 frame_crc = ((uint32_t)frame[11] << 16U) |
433 ((uint32_t)frame[12] << 8U) |
436 return (expected_crc == frame_crc);
443int adsb_cpr_nl(
double latitude_deg)
452 if (!isfinite(latitude_deg))
457 lat = fabs(latitude_deg);
469 a = 1.0 - cos(adsb_pi() / (2.0 * ADSB_NZ));
470 b = cos((adsb_pi() / 180.0) * lat);
478 angle = 1.0 - (a / b);
488 num = 2.0 * adsb_pi();
496 return (
int)floor(num / den);
499uint32_t adsb_cpr_encode_latitude(
double latitude_deg, cpr_format_t format)
504 if (!is_valid_latitude(latitude_deg))
509 if (format == CPR_EVEN)
511 dlat = 360.0 / (4.0 * ADSB_NZ);
515 dlat = 360.0 / (4.0 * ADSB_NZ - 1.0);
518 yz = floor(((
double)ADSB_CPR_MOD * pos_mod(latitude_deg, dlat) / dlat) + 0.5);
520 return ((uint32_t)yz) & 0x1FFFFU;
523uint32_t adsb_cpr_encode_longitude(
double latitude_deg,
double longitude_deg, cpr_format_t format)
530 if (!is_valid_latitude(latitude_deg) || !is_valid_longitude(longitude_deg))
535 nl = adsb_cpr_nl(latitude_deg);
536 if (format == CPR_EVEN)
550 dlon = 360.0 / (double)ni;
551 xz = floor(((
double)ADSB_CPR_MOD * pos_mod(longitude_deg, dlon) / dlon) + 0.5);
553 return ((uint32_t)xz) & 0x1FFFFU;
560enc_status_t adsb_encode_identification(
const adsb_identification_t *msg, uint8_t frame[ADSB_FRAME_BYTES])
562 uint8_t callsign_codes[ADSB_CALLSIGN_LEN];
566 if ((msg == NULL) || (frame == NULL))
568 return ENC_INVALID_ARGUMENT;
571 if (!is_valid_icao(msg->icao))
573 return ENC_INVALID_ICAO;
576 st = encode_callsign(msg->callsign, callsign_codes);
582 adsb_frame_clear(frame);
584 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
585 frame_set_bits(frame, 5U, 3U, ADSB_CA);
586 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
588 frame_set_bits(frame, 32U, 5U, 4U);
589 frame_set_bits(frame, 37U, 3U, 0U);
591 for (i = 0U; i < ADSB_CALLSIGN_LEN; ++i)
593 frame_set_bits(frame, 40U + (6U * i), 6U, callsign_codes[i]);
596 adsb_apply_crc(frame);
601enc_status_t adsb_encode_position(
const adsb_position_t *msg, uint8_t frame[ADSB_FRAME_BYTES])
608 if ((msg == NULL) || (frame == NULL))
610 return ENC_INVALID_ARGUMENT;
613 if (!is_valid_icao(msg->icao))
615 return ENC_INVALID_ICAO;
617 if (!is_valid_latitude(msg->latitude_deg))
619 return ENC_INVALID_LATITUDE;
621 if (!is_valid_longitude(msg->longitude_deg))
623 return ENC_INVALID_LONGITUDE;
625 if (!is_valid_altitude(msg->altitude_ft))
627 return ENC_INVALID_ALTITUDE;
629 if ((msg->cpr_format != CPR_EVEN) && (msg->cpr_format != CPR_ODD))
631 return ENC_INVALID_ARGUMENT;
634 st = encode_altitude_12bit(msg->altitude_ft, &alt_code);
640 cpr_lat = adsb_cpr_encode_latitude(msg->latitude_deg, msg->cpr_format);
641 cpr_lon = adsb_cpr_encode_longitude(msg->latitude_deg, msg->longitude_deg, msg->cpr_format);
643 adsb_frame_clear(frame);
645 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
646 frame_set_bits(frame, 5U, 3U, ADSB_CA);
647 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
649 frame_set_bits(frame, 32U, 5U, 11U);
650 frame_set_bits(frame, 37U, 2U, 0U);
651 frame_set_bits(frame, 39U, 1U, 0U);
652 frame_set_bits(frame, 40U, 12U, alt_code & 0x0FFFU);
653 frame_set_bits(frame, 52U, 1U, 0U);
654 frame_set_bits(frame, 53U, 1U, (uint32_t)msg->cpr_format & 0x01U);
655 frame_set_bits(frame, 54U, 17U, cpr_lat & 0x1FFFFU);
656 frame_set_bits(frame, 71U, 17U, cpr_lon & 0x1FFFFU);
658 adsb_apply_crc(frame);
670 if ((msg == NULL) || (frame == NULL))
672 return ENC_INVALID_ARGUMENT;
675 if (!is_valid_icao(msg->icao))
677 return ENC_INVALID_ICAO;
679 if (!is_valid_latitude(msg->latitude_deg))
681 return ENC_INVALID_LATITUDE;
683 if (!is_valid_longitude(msg->longitude_deg))
685 return ENC_INVALID_LONGITUDE;
687 if (!is_valid_speed(msg->ground_speed_kt))
689 return ENC_INVALID_SPEED;
691 if (!is_valid_track(msg->ground_track_deg))
693 return ENC_INVALID_TRACK;
695 if ((msg->cpr_format != CPR_EVEN) && (msg->cpr_format != CPR_ODD))
697 return ENC_INVALID_ARGUMENT;
700 movement = encode_movement(msg->ground_speed_kt);
701 track_code = ((uint32_t)lround(msg->ground_track_deg / (360.0 / 128.0))) & 0x7FU;
703 cpr_lat = adsb_cpr_encode_latitude(msg->latitude_deg, msg->cpr_format);
704 cpr_lon = adsb_cpr_encode_longitude(msg->latitude_deg, msg->longitude_deg, msg->cpr_format);
706 adsb_frame_clear(frame);
708 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
709 frame_set_bits(frame, 5U, 3U, ADSB_CA);
710 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
718 frame_set_bits(frame, 32U, 5U, 8U);
719 frame_set_bits(frame, 37U, 7U, movement & 0x7FU);
720 frame_set_bits(frame, 44U, 1U, 1U);
721 frame_set_bits(frame, 45U, 7U, track_code);
722 frame_set_bits(frame, 52U, 1U, 0U);
723 frame_set_bits(frame, 53U, 1U, (uint32_t)msg->cpr_format & 0x01U);
724 frame_set_bits(frame, 54U, 17U, cpr_lat & 0x1FFFFU);
725 frame_set_bits(frame, 71U, 17U, cpr_lon & 0x1FFFFU);
727 adsb_apply_crc(frame);
732enc_status_t adsb_encode_velocity(
const adsb_velocity_t *msg, uint8_t frame[ADSB_FRAME_BYTES])
748 if ((msg == NULL) || (frame == NULL))
750 return ENC_INVALID_ARGUMENT;
753 if (!is_valid_icao(msg->icao))
755 return ENC_INVALID_ICAO;
757 if (!is_valid_speed(msg->ground_speed_kt))
759 return ENC_INVALID_SPEED;
761 if (!is_valid_track(msg->track_deg))
763 return ENC_INVALID_TRACK;
765 if (!is_valid_vertical_rate(msg->vertical_rate_fpm))
767 return ENC_INVALID_VERTICAL_RATE;
770 track_rad = msg->track_deg * (adsb_pi() / 180.0);
771 v_east = msg->ground_speed_kt * sin(track_rad);
772 v_north = msg->ground_speed_kt * cos(track_rad);
779 ew_speed = (int32_t)lround(fabs(v_east));
780 ns_speed = (int32_t)lround(fabs(v_north));
782 if ((ew_speed <= 1022) && (ns_speed <= 1022))
789 ew_speed = (int32_t)lround(fabs(v_east) / 4.0);
790 ns_speed = (int32_t)lround(fabs(v_north) / 4.0);
793 if ((ew_speed > 1022) || (ns_speed > 1022))
795 return ENC_INVALID_SPEED;
798 ew_dir = (v_east < 0.0) ? 1U : 0U;
799 ns_dir = (v_north < 0.0) ? 1U : 0U;
801 ew_field = (uint32_t)(ew_speed + 1);
802 ns_field = (uint32_t)(ns_speed + 1);
804 vr_q = (int32_t)lround((
double)abs(msg->vertical_rate_fpm) / 64.0);
807 return ENC_INVALID_VERTICAL_RATE;
810 vr_sign = (msg->vertical_rate_fpm < 0) ? 1U : 0U;
811 vr_field = (uint32_t)(vr_q + 1);
813 adsb_frame_clear(frame);
815 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
816 frame_set_bits(frame, 5U, 3U, ADSB_CA);
817 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
819 frame_set_bits(frame, 32U, 5U, 19U);
820 frame_set_bits(frame, 37U, 3U, subtype);
821 frame_set_bits(frame, 40U, 1U, 0U);
822 frame_set_bits(frame, 41U, 1U, 0U);
823 frame_set_bits(frame, 42U, 3U, 0U);
824 frame_set_bits(frame, 45U, 1U, ew_dir);
825 frame_set_bits(frame, 46U, 10U, ew_field & 0x03FFU);
826 frame_set_bits(frame, 56U, 1U, ns_dir);
827 frame_set_bits(frame, 57U, 10U, ns_field & 0x03FFU);
828 frame_set_bits(frame, 67U, 1U, 1U);
829 frame_set_bits(frame, 68U, 1U, vr_sign);
830 frame_set_bits(frame, 69U, 9U, vr_field & 0x01FFU);
831 frame_set_bits(frame, 78U, 2U, 0U);
832 frame_set_bits(frame, 80U, 1U, 0U);
833 frame_set_bits(frame, 81U, 7U, 0U);
835 adsb_apply_crc(frame);
840enc_status_t adsb_encode_emergency(
const adsb_emergency_t *msg, uint8_t frame[ADSB_FRAME_BYTES])
842 uint32_t mode_a_field;
844 if ((msg == NULL) || (frame == NULL))
846 return ENC_INVALID_ARGUMENT;
849 if (!is_valid_icao(msg->icao))
851 return ENC_INVALID_ICAO;
853 if (!is_valid_emergency_state(msg->emergency_state))
855 return ENC_INVALID_EMERGENCY_STATE;
857 if (!is_valid_mode_a_code(msg->mode_a_code))
859 return ENC_INVALID_MODE_A_CODE;
862 mode_a_field = encode_mode_a_code(msg->mode_a_code);
864 adsb_frame_clear(frame);
866 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
867 frame_set_bits(frame, 5U, 3U, ADSB_CA);
868 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
870 frame_set_bits(frame, 32U, 5U, 28U);
871 frame_set_bits(frame, 37U, 3U, 1U);
872 frame_set_bits(frame, 40U, 3U, (uint32_t)msg->emergency_state);
873 frame_set_bits(frame, 43U, 13U, mode_a_field & 0x1FFFU);
874 frame_set_bits(frame, 56U, 32U, 0U);
876 adsb_apply_crc(frame);
881enc_status_t adsb_encode_target_state(
const adsb_target_state_t *msg, uint8_t frame[ADSB_FRAME_BYTES])
883 uint32_t altitude_field;
884 uint32_t pressure_field;
885 uint32_t heading_field = 0U;
888 if ((msg == NULL) || (frame == NULL))
890 return ENC_INVALID_ARGUMENT;
892 if (!is_valid_icao(msg->icao))
894 return ENC_INVALID_ICAO;
896 if (!is_valid_altitude_source(msg->selected_altitude_source))
898 return ENC_INVALID_ARGUMENT;
900 st = encode_target_altitude(msg->selected_altitude_ft, &altitude_field);
905 st = encode_barometric_pressure(msg->barometric_pressure_mbar, &pressure_field);
910 if (msg->nac_p > 15U)
912 return ENC_INVALID_NAC_P;
916 return ENC_INVALID_SIL;
918 if (msg->selected_heading_valid)
920 if (!is_valid_track(msg->selected_heading_deg))
922 return ENC_INVALID_HEADING;
924 heading_field = (uint32_t)lround(msg->selected_heading_deg * (512.0 / 360.0)) & 0x1FFU;
927 adsb_frame_clear(frame);
929 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
930 frame_set_bits(frame, 5U, 3U, ADSB_CA);
931 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
933 frame_set_bits(frame, 32U, 5U, 29U);
934 frame_set_bits(frame, 37U, 2U, 1U);
935 frame_set_bits(frame, 39U, 1U, 0U);
936 frame_set_bits(frame, 40U, 1U, (uint32_t)msg->selected_altitude_source);
937 frame_set_bits(frame, 41U, 11U, altitude_field);
938 frame_set_bits(frame, 52U, 9U, pressure_field);
939 frame_set_bits(frame, 61U, 1U, msg->selected_heading_valid ? 1U : 0U);
940 frame_set_bits(frame, 62U, 9U, heading_field);
941 frame_set_bits(frame, 71U, 4U, msg->nac_p);
942 frame_set_bits(frame, 75U, 1U, msg->nic_baro ? 1U : 0U);
943 frame_set_bits(frame, 76U, 2U, msg->sil);
944 frame_set_bits(frame, 78U, 1U, msg->mode_status ? 1U : 0U);
945 frame_set_bits(frame, 79U, 1U, msg->mode_status && msg->autopilot_engaged ? 1U : 0U);
946 frame_set_bits(frame, 80U, 1U, msg->mode_status && msg->vnav_mode ? 1U : 0U);
947 frame_set_bits(frame, 81U, 1U, msg->mode_status && msg->altitude_hold_mode ? 1U : 0U);
948 frame_set_bits(frame, 82U, 1U, 0U);
949 frame_set_bits(frame, 83U, 1U, msg->mode_status && msg->approach_mode ? 1U : 0U);
950 frame_set_bits(frame, 84U, 1U, msg->tcas_operational ? 1U : 0U);
951 frame_set_bits(frame, 85U, 1U, msg->mode_status && msg->lnav_mode ? 1U : 0U);
952 frame_set_bits(frame, 86U, 2U, 0U);
954 adsb_apply_crc(frame);
961 if ((msg == NULL) || (frame == NULL))
963 return ENC_INVALID_ARGUMENT;
965 if (!is_valid_icao(msg->icao))
967 return ENC_INVALID_ICAO;
969 if (msg->subtype > 1U)
971 return ENC_INVALID_OPERATIONAL_SUBTYPE;
973 if (msg->adsb_version > 7U)
975 return ENC_INVALID_ADSB_VERSION;
977 if (msg->nac_p > 15U)
979 return ENC_INVALID_NAC_P;
983 return ENC_INVALID_SIL;
986 adsb_frame_clear(frame);
988 frame_set_bits(frame, 0U, 5U, ADSB_DF17);
989 frame_set_bits(frame, 5U, 3U, ADSB_CA);
990 frame_set_bits(frame, 8U, 24U, msg->icao & ADSB_ICAO_MAX);
992 frame_set_bits(frame, 32U, 5U, 31U);
993 frame_set_bits(frame, 37U, 3U, msg->subtype);
994 frame_set_bits(frame, 40U, 16U, msg->capability_class);
995 frame_set_bits(frame, 56U, 16U, msg->operational_mode);
996 frame_set_bits(frame, 72U, 3U, msg->adsb_version);
997 frame_set_bits(frame, 75U, 1U, msg->nic_supplement_a ? 1U : 0U);
998 frame_set_bits(frame, 76U, 4U, msg->nac_p);
999 frame_set_bits(frame, 80U, 2U, 0U);
1000 frame_set_bits(frame, 82U, 2U, msg->sil);
1001 frame_set_bits(frame, 84U, 1U, msg->nic_baro ? 1U : 0U);
1002 frame_set_bits(frame, 85U, 1U, msg->heading_reference_magnetic ? 1U : 0U);
1003 frame_set_bits(frame, 86U, 1U, msg->sil_supplement ? 1U : 0U);
1004 frame_set_bits(frame, 87U, 1U, 0U);
1006 adsb_apply_crc(frame);