dji_log_parser/record/
rc.rs

1use binrw::binread;
2use serde::Serialize;
3#[cfg(target_arch = "wasm32")]
4use tsify_next::Tsify;
5
6use crate::layout::details::ProductType;
7use crate::utils::sub_byte_field;
8
9#[binread]
10#[derive(Serialize, Debug)]
11#[serde(rename_all = "camelCase")]
12#[br(little, import { version: u8, product_type: ProductType = ProductType::None })]
13#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
14pub struct RC {
15    /// right stick - horizontal
16    pub aileron: u16,
17    /// right stick - vertical
18    pub elevator: u16,
19    /// left stick - vertical
20    pub throttle: u16,
21    /// left stick - horizontal
22    pub rudder: u16,
23    pub gimbal: u16,
24
25    #[br(temp)]
26    _bitpack1: u8,
27    #[br(calc(sub_byte_field(_bitpack1, 0x01) == 1))]
28    pub wheel_btn_down: bool,
29    #[br(calc(sub_byte_field(_bitpack1, 0x3E)))]
30    pub wheel_offset: u8,
31    #[br(calc(sub_byte_field(_bitpack1, 0x40)))]
32    pub wheel_polarity: u8,
33    #[br(calc(sub_byte_field(_bitpack1, 0x80)))]
34    pub wheel_change: u8,
35
36    #[br(temp)]
37    _bitpack2: u8,
38    #[br(calc(sub_byte_field(_bitpack2, 0x07)))]
39    pub transform_btn_reserve: u8,
40    #[br(calc(sub_byte_field(_bitpack2, 0x08) == 1))]
41    pub return_btn: bool,
42    #[br(calc(FlightModeSwitch::from(sub_byte_field(_bitpack2, 0x30), product_type)))]
43    pub flight_mode_switch: FlightModeSwitch,
44    #[br(calc(sub_byte_field(_bitpack2, 0xC0)))]
45    pub transform_switch: u8,
46
47    #[br(temp)]
48    _bitpack3: u8,
49    #[br(calc(sub_byte_field(_bitpack3, 0x02) == 1))]
50    pub custom_function_btn4_down: bool,
51    #[br(calc(sub_byte_field(_bitpack3, 0x04) == 1))]
52    pub custom_function_btn3_down: bool,
53    #[br(calc(sub_byte_field(_bitpack3, 0x08) == 1))]
54    pub custom_function_btn2_down: bool,
55    #[br(calc(sub_byte_field(_bitpack3, 0x10) == 1))]
56    pub custom_function_btn1_down: bool,
57    #[br(calc(sub_byte_field(_bitpack3, 0x20) == 1))]
58    pub playback_btn_down: bool,
59    #[br(calc(sub_byte_field(_bitpack3, 0x40) == 1))]
60    pub shutter_btn_down: bool,
61    #[br(calc(sub_byte_field(_bitpack3, 0x80) == 1))]
62    pub record_btn_down: bool,
63
64    #[br(if(version >= 6))]
65    pub bandwidth: u8,
66    #[br(if(version >= 7))]
67    pub gimbal_control_enable: u8,
68}
69
70#[derive(Serialize, Debug, Clone, Copy)]
71#[cfg_attr(target_arch = "wasm32", derive(Tsify))]
72pub enum FlightModeSwitch {
73    /// Position One. For all products except Mavic Pro, this is the left most position
74    /// of the flight mode switch on a remote controller from the perspective of the
75    /// pilot. For example, on a Phantom 4 remote controller,  Position One is labeled
76    /// "A". For Mavic Pro, Spark and Mavic Air, this is  the position that is furthest
77    /// away from the pilot and labeled "Sport".
78    One,
79    /// Position Two. For all products except Mavic Pro, this is the middle position of
80    /// the flight mode switch on a remote controller from the perspective of the pilot.
81    /// For example, on a Phantom 4 remote controller, Position Two is labeled "S". For
82    /// Mavic Pro, Spark and Mavic Air, this is the position that is closest  to the
83    /// pilot [the P position].
84    Two,
85    /// Position Three. For all products except Mavic Pro, this is the right most
86    /// position of the flight mode switch on a remote controller from the perspective
87    /// of the pilot. For example, on a Phantom 4 remote controller, Position Two is
88    /// labeled "P". Mavic Pro, Spark or Mavic Air does not have  a third position for
89    /// the flight mode switch.
90    Three,
91    #[serde(untagged)]
92    Unknown(u8),
93}
94
95impl FlightModeSwitch {
96    pub fn from(value: u8, product_type: ProductType) -> Self {
97        let mapped_value = match product_type {
98            // Remap values for Mavic Pro
99            ProductType::MavicPro => match value {
100                0 => 2,
101                1 => 3,
102                2 => 1,
103                _ => value,
104            },
105            _ => value,
106        };
107
108        match mapped_value {
109            0 => FlightModeSwitch::One,
110            1 => FlightModeSwitch::Two,
111            2 => FlightModeSwitch::Three,
112            _ => FlightModeSwitch::Unknown(mapped_value),
113        }
114    }
115}