Line data Source code
1 : /*
2 : * This file is free software: you can redistribute it and/or modify it
3 : * under the terms of the GNU General Public License as published by the
4 : * Free Software Foundation, either version 3 of the License, or
5 : * (at your option) any later version.
6 : *
7 : * This file is distributed in the hope that it will be useful, but
8 : * WITHOUT ANY WARRANTY; without even the implied warranty of
9 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 : * See the GNU General Public License for more details.
11 : *
12 : * You should have received a copy of the GNU General Public License along
13 : * with this program. If not, see <http://www.gnu.org/licenses/>.
14 : *
15 : * AP_OSD partially based on betaflight and inav osd.c implemention.
16 : * clarity.mcm font is taken from inav configurator.
17 : * Many thanks to their authors.
18 : */
19 :
20 : /*
21 : parameter object for one setting in AP_OSD
22 : */
23 :
24 : #include "AP_OSD.h"
25 : #include <AP_Vehicle/AP_Vehicle_Type.h>
26 : #include <GCS_MAVLink/GCS.h>
27 : #include <SRV_Channel/SRV_Channel.h>
28 : #include <AP_SerialManager/AP_SerialManager.h>
29 : #include <ctype.h>
30 :
31 : #if OSD_PARAM_ENABLED
32 :
33 : const AP_Param::GroupInfo AP_OSD_ParamSetting::var_info[] = {
34 : // @Param: _EN
35 : // @DisplayName: Enable
36 : // @Description: Enable setting
37 : // @Values: 0:Disabled,1:Enabled
38 : // @User: Standard
39 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_EN", 1, AP_OSD_ParamSetting, enabled, default_enabled),
40 :
41 : // @Param: _X
42 : // @DisplayName: X position
43 : // @Description: Horizontal position on screen
44 : // @Range: 0 29
45 : // @User: Standard
46 : AP_GROUPINFO("_X", 2, AP_OSD_ParamSetting, xpos, 2),
47 :
48 : // @Param: _Y
49 : // @DisplayName: Y position
50 : // @Description: Vertical position on screen
51 : // @Range: 0 15
52 : // @User: Standard
53 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_Y", 3, AP_OSD_ParamSetting, ypos, default_ypos),
54 :
55 : // Parameter access keys. These default to -1 too allow user overrides
56 : // to work properly
57 :
58 : // @Param: _KEY
59 : // @DisplayName: Parameter key
60 : // @Description: Key of the parameter to be displayed and modified
61 : // @User: Standard
62 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_KEY", 4, AP_OSD_ParamSetting, _param_key, default_param_key),
63 :
64 : // @Param: _IDX
65 : // @DisplayName: Parameter index
66 : // @Description: Index of the parameter to be displayed and modified
67 : // @User: Standard
68 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_IDX", 5, AP_OSD_ParamSetting, _param_idx, default_param_idx),
69 :
70 : // @Param: _GRP
71 : // @DisplayName: Parameter group
72 : // @Description: Group of the parameter to be displayed and modified
73 : // @User: Standard
74 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_GRP", 6, AP_OSD_ParamSetting, _param_group, default_param_group),
75 :
76 : // @Param: _MIN
77 : // @DisplayName: Parameter minimum
78 : // @Description: Minimum value of the parameter to be displayed and modified
79 : // @User: Standard
80 : AP_GROUPINFO("_MIN", 7, AP_OSD_ParamSetting, _param_min, 0.0f),
81 :
82 : // @Param: _MAX
83 : // @DisplayName: Parameter maximum
84 : // @Description: Maximum of the parameter to be displayed and modified
85 : // @User: Standard
86 : AP_GROUPINFO("_MAX", 8, AP_OSD_ParamSetting, _param_max, 1.0f),
87 :
88 : // @Param: _INCR
89 : // @DisplayName: Parameter increment
90 : // @Description: Increment of the parameter to be displayed and modified
91 : // @User: Standard
92 : AP_GROUPINFO("_INCR", 9, AP_OSD_ParamSetting, _param_incr, 0.001f),
93 :
94 : // @Param: _TYPE
95 : // @DisplayName: Parameter type
96 : // @Description: Type of the parameter to be displayed and modified
97 : // @User: Standard
98 : AP_GROUPINFO_FLAGS_DEFAULT_POINTER("_TYPE", 10, AP_OSD_ParamSetting, _type, default_type),
99 :
100 : AP_GROUPEND
101 : };
102 :
103 : #if HAL_GCS_ENABLED
104 : // ensure that our OSD_PARAM type enumeration is 1:1 with the mavlink
105 : // numbers. This allows us to do a simple cast from one to the other
106 : // when sending mavlink messages, rather than having some sort of
107 : // mapping function from our internal enumeration into the mavlink
108 : // enumeration. Doing things this way has two advantages - in the
109 : // future we could add that mapping function and change our
110 : // enumeration, and the other is that it allows us to build the GPS
111 : // library without having the mavlink headers built (for example, in
112 : // AP_Periph we shouldn't need mavlink headers).
113 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::NONE == (uint32_t)OSD_PARAM_NONE, "OSD_PARAM_NONE incorrect");
114 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::SERIAL_PROTOCOL == (uint32_t)OSD_PARAM_SERIAL_PROTOCOL, "OSD_PARAM_SERIAL_PROTOCOL incorrect");
115 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::SERVO_FUNCTION == (uint32_t)OSD_PARAM_SERVO_FUNCTION, "OSD_PARAM_SERVO_FUNCTION incorrect");
116 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::AUX_FUNCTION == (uint32_t)OSD_PARAM_AUX_FUNCTION, "OSD_PARAM_AUX_FUNCTION incorrect");
117 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::FLIGHT_MODE == (uint32_t)OSD_PARAM_FLIGHT_MODE, "OSD_PARAM_FLIGHT_MODE incorrect");
118 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::FAILSAFE_ACTION == (uint32_t)OSD_PARAM_FAILSAFE_ACTION, "OSD_PARAM_FAILSAFE_ACTION incorrect");
119 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::FAILSAFE_ACTION_1 == (uint32_t)OSD_PARAM_FAILSAFE_ACTION_1, "OSD_PARAM_FAILSAFE_ACTION_1 incorrect");
120 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::FAILSAFE_ACTION_2 == (uint32_t)OSD_PARAM_FAILSAFE_ACTION_2, "OSD_PARAM_FAILSAFE_ACTION_2 incorrect");
121 : static_assert((uint32_t)AP_OSD_ParamSetting::Type::NUM_TYPES == (uint32_t)AP_OSD_ParamSetting::Type::NUM_TYPES, "AP_OSD_ParamSetting::Type::NUM_TYPES incorrect");
122 : #endif // HAL_GCS_ENABLED
123 :
124 : #define PARAM_COMPOSITE_INDEX(key, idx, group) (uint32_t((uint32_t(key) << 23) | (uint32_t(idx) << 18) | uint32_t(group)))
125 :
126 : #define OSD_PARAM_DEBUG 0
127 : #if OSD_PARAM_DEBUG
128 : #define debug(fmt, args ...) do { hal.console->printf("OSD: " fmt, args); } while (0)
129 : #else
130 : #define debug(fmt, args ...)
131 : #endif
132 :
133 : // at the cost of a little flash, we can create much better ranges and values for certain important settings
134 : // common labels - all strings must be upper case
135 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_COPTER_OR_HELI
136 :
137 : static const char* SERIAL_PROTOCOL_VALUES[] = {
138 : "", "MAV", "MAV2", "FSKY_D", "FSKY_S", "GPS", "", "ALEX", "STORM", "RNG",
139 : "FSKY_TX", "LID360", "", "BEACN", "VOLZ", "SBUS", "ESC_TLM", "DEV_TLM", "OPTFLW", "RBTSRV",
140 : "NMEA", "WNDVNE", "SLCAN", "RCIN", "MGSQRT", "LTM", "RUNCAM", "HOT_TLM", "SCRIPT", "CRSF",
141 : "GEN", "WNCH", "MSP", "DJI", "AIRSPD", "ADSB", "AHRS", "AUDIO", "FETTEC", "TORQ",
142 : "AIS", "CD_ESC", "MSP_DP", "MAV_HL", "TRAMP", "DDS", "IMUOUT", "IQ", "PPP", "IBUS_TLM", "IOMCU"
143 : };
144 : static_assert(AP_SerialManager::SerialProtocol_NumProtocols == ARRAY_SIZE(SERIAL_PROTOCOL_VALUES), "Wrong size SerialProtocol_NumProtocols");
145 :
146 : static const char* SERVO_FUNCTIONS[] = {
147 : "NONE", "RCPASS", "FLAP", "FLAP_AUTO", "AIL", "", "MNT_PAN", "MNT_TLT", "MNT_RLL", "MNT_OPEN",
148 : "CAM_TRG", "", "MNT2_PAN", "MNT2_TLT", "MNT2_RLL", "MNT2_OPEN", "DIF_SPL_L1", "DIF_SPL_R1", "", "ELE",
149 : "", "RUD", "SPR_PMP", "SPR_SPIN", "FLPRON_L", "FLPRON_R", "GRND_STEER", "PARACHT", "GRIP", "GEAR",
150 : "ENG_RUN_EN", "HELI_RSC", "HELI_TAIL_RSC", "MOT_1", "MOT_2", "MOT_3", "MOT_4", "MOT_5", "MOT_6", "MOT_7",
151 : "MOT_8", "MOT_TLT", "", "", "", "", "", "", "", "",
152 : "", "RCIN_1", "RCIN_2", "RCIN_3", "RCIN_4", "RCIN_5", "RCIN_6", "RCIN_7", "RCIN_8", "RCIN_9",
153 : "RCIN_10", "RCIN_11", "RCIN_12", "RCIN_13", "RCIN_14", "RCIN_15", "RCIN_16", "IGN", "", "START",
154 : "THR", "TRCK_YAW", "TRCK_PIT", "THR_L", "THR_R", "TLTMOT_L", "TLTMOT_R", "ELEVN_L", "ELEVN_R", "VTAIL_L",
155 : "VTAIL_R", "BOOST_THR", "MOT_9", "MOT_10", "MOT_11", "MOT_12", "DIF_SPL_L2", "DIF_SPL_R2", "", "MAIN_SAIL",
156 : "CAM_ISO", "CAM_APTR", "CAM_FOC", "CAM_SH_SPD", "SCRPT_1", "SCRPT_2", "SCRPT_3", "SCRPT_4", "SCRPT_5", "SCRPT_6",
157 : "SCRPT_7", "SCRPT_8", "SCRPT_9", "SCRPT_10", "SCRPT_11", "SCRPT_12", "SCRPT_13", "SCRPT_14", "SCRPT_15", "SCRPT_16",
158 : "", "", "", "", "", "", "", "", "", "",
159 : "NEOPX_1", "NEOPX_2", "NEOPX_3", "NEOPX_4", "RAT_RLL", "RAT_PIT","RAT_THRST", "RAT_YAW", "WSAIL_EL", "PRLED_1",
160 : "PRLED_2", "PRLED_3", "PRLED_CLK", "WNCH_CL"
161 : };
162 :
163 : #endif
164 :
165 : #if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
166 :
167 : static const char* AUX_OPTIONS[] = {
168 : "NONE", "", "", "", "RTL", "", "", "", "", "CAM_TRG",
169 : "", "", "", "", "", "", "AUTO", "", "", "",
170 : "", "", "", "", "MIS_RST", "", "", "", "RLY", "LAND_GR",
171 : "LOST_SND", "M_ESTOP", "", "", "", "RLY3", "RLY4", "", "OA_ADSB", "",
172 : "", "ARM/DS", "", "INVERT", "", "", "RC_OVRD", "", "", "",
173 : "", "MANUAL", "", "", "", "GUIDE", "LOIT", "", "CLR_WP", "",
174 : "", "", "COMP_LRN", "", "REV_THR", "GPS_DIS", "RLY5", "RLY6", "", "",
175 : "", "", "CIRCLE", "", "", "", "", "TAKEOFF", "RCAM_CTL", "RCAM_OSD",
176 : "", "DSARM", "QASS3POS", "", "AIR", "GEN", "TER_AUTO", "CROW_SEL", "SOAR", "",
177 : "", "", "", "", "", "", "", "", "", "",
178 : "KILLIMU1", "KILLIMU2", "CAM_TOG", "", "", "GPSYAW_DIS"
179 : };
180 :
181 : static const char* FLTMODES[] = {
182 : "MAN", "CIRC", "STAB", "TRAIN", "ACRO", "FBWA", "FBWB", "CRUISE", "ATUNE", "", "AUTO",
183 : "RTL", "LOIT", "TKOF", "ADSB", "GUID", "", "QSTAB", "QHOV", "QLOIT", "QLAND",
184 : "QRTL", "QTUNE", "QACRO", "THRML", "L2QLND"
185 : };
186 :
187 : static const char* FS_ACT[] = {
188 : "NONE", "RTL", "LAND", "TERM", "QLAND", "PARA"
189 : };
190 :
191 : static const char* FS_SHRT_ACTNS[] = {
192 : "CRC_NOCHNGE", "CIRC", "FBWA", "DSABLE"
193 : };
194 :
195 : static const char* FS_LNG_ACTNS[] = {
196 : "CNTNUE", "RTL", "GLIDE", "PARACHT"
197 : };
198 :
199 : // plane parameters
200 : const AP_OSD_ParamSetting::ParamMetadata AP_OSD_ParamSetting::_param_metadata[unsigned(AP_OSD_ParamSetting::Type::NUM_TYPES)] = {
201 : { -1, AP_SerialManager::SerialProtocol_NumProtocols - 1, 1, ARRAY_SIZE(SERIAL_PROTOCOL_VALUES), SERIAL_PROTOCOL_VALUES }, // OSD_PARAM_SERIAL_PROTOCOL
202 : { 0, SRV_Channel::k_nr_aux_servo_functions - 1, 1, ARRAY_SIZE(SERVO_FUNCTIONS), SERVO_FUNCTIONS }, // OSD_PARAM_SERVO_FUNCTION
203 : { 0, 105, 1, ARRAY_SIZE(AUX_OPTIONS), AUX_OPTIONS }, // OSD_PARAM_AUX_FUNCTION
204 : { 0, 25, 1, ARRAY_SIZE(FLTMODES), FLTMODES }, // OSD_PARAM_FLIGHT_MODE
205 : { 0, 5, 1, ARRAY_SIZE(FS_ACT), FS_ACT }, // OSD_PARAM_FAILSAFE_ACTION
206 : { 0, 3, 1, ARRAY_SIZE(FS_SHRT_ACTNS), FS_SHRT_ACTNS }, // OSD_PARAM_FAILSAFE_ACTION_1
207 : { 0, 3, 1, ARRAY_SIZE(FS_LNG_ACTNS), FS_LNG_ACTNS }, // OSD_PARAM_FAILSAFE_ACTION_2
208 : };
209 :
210 : #elif APM_BUILD_COPTER_OR_HELI
211 :
212 : static const char* AUX_OPTIONS[] = {
213 : "NONE", "", "FLIP", "SIMP", "RTL", "SAV_TRM", "", "SAV_WP", "", "CAM_TRG",
214 : "RNG", "FENCE", "", "SSIMP", "ACRO_TRN", "SPRAY", "AUTO", "AUTOTN", "LAND", "GRIP",
215 : "", "CHUTE_EN", "CHUTE_RL", "CHUTE_3P", "MIS_RST", "ATT_FF", "ATT_ACC", "RET_MNT", "RLY", "LAND_GR",
216 : "LOST_SND", "M_ESTOP", "M_ILOCK", "BRAKE", "RLY2", "RLY3", "RLY4", "THROW", "OA_ADSB", "PR_LOIT",
217 : "OA_PROX", "ARM/DS", "SMRT_RTL", "INVERT", "", "", "RC_OVRD", "USR1", "USR2", "USR3",
218 : "", "", "ACRO", "", "", "GUIDE", "LOIT", "FOLLOW", "CLR_WP", "",
219 : "ZZAG", "ZZ_SVWP", "COMP_LRN", "", "", "GPS_DIS", "RLY5", "RLY6", "STAB", "PHOLD",
220 : "AHOLD", "FHOLD", "CIRCLE", "DRIFT", "", "", "STANDBY", "", "RCAM_CTL", "RCAM_OSD",
221 : "VISO_CAL", "DISARM", "", "ZZ_Auto", "AIR", "", "", "", "", "",
222 : "", "", "", "", "", "", "", "", "", "",
223 : "KILLIMU1", "KILLIMU2", "CAM_MOD_TOG", "", "", "GPSYAW_DIS"
224 : };
225 :
226 : static const char* FLTMODES[] = {
227 : "STAB", "ACRO", "ALTHOLD", "AUTO", "GUIDED", "LOIT", "RTL", "CIRC", "", "LAND",
228 : "", "DRFT", "", "SPORT", "FLIP", "ATUN", "POSHLD", "BRAKE", "THROW", "AVD_ADSB",
229 : "GUID_NOGPS", "SMRTRTL", "FLOHOLD", "FOLLOW", "ZIGZAG", "SYSID", "HELI_ARO", "AUTORTL",
230 : "TRTLE"
231 : };
232 :
233 : static const char* FS_OPTIONS[] = {
234 : "NONE", "CONT_RCFS", "CONT_GCSFS", "CONT_RC/GCSFS", "CONT_GUID_RC", "", "", "", "CONT_LAND", "",
235 : "", "", "", "", "", "CONT_CTRL_GCS", "", "", "CONTNUE"
236 : };
237 :
238 : static const char* THR_FS_ACT[] = {
239 : "NONE", "RTL", "CONT", "LAND", "SRTL_RTL", "SRTL_LAND"
240 : };
241 :
242 : static const char* FS_ACT[] = {
243 : "NONE", "LAND", "RTL", "SRTL_RTL", "SRTL_LAND", "TERM"
244 : };
245 :
246 : // copter parameters
247 : const AP_OSD_ParamSetting::ParamMetadata AP_OSD_ParamSetting::_param_metadata[unsigned(AP_OSD_ParamSetting::Type::NUM_TYPES)] = {
248 : { -1, AP_SerialManager::SerialProtocol_NumProtocols - 1, 1, ARRAY_SIZE(SERIAL_PROTOCOL_VALUES), SERIAL_PROTOCOL_VALUES }, // OSD_PARAM_SERIAL_PROTOCOL
249 : { 0, SRV_Channel::k_nr_aux_servo_functions - 1, 1, ARRAY_SIZE(SERVO_FUNCTIONS), SERVO_FUNCTIONS }, // OSD_PARAM_SERVO_FUNCTION
250 : { 0, 105, 1, ARRAY_SIZE(AUX_OPTIONS), AUX_OPTIONS }, // OSD_PARAM_AUX_FUNCTION
251 : { 0, 28, 1, ARRAY_SIZE(FLTMODES), FLTMODES }, // OSD_PARAM_FLIGHT_MODE
252 : { 0, 3, 1, ARRAY_SIZE(FS_OPTIONS), FS_OPTIONS }, // OSD_PARAM_FAILSAFE_ACTION
253 : { 0, 5, 1, ARRAY_SIZE(FS_ACT), FS_ACT }, // OSD_PARAM_FAILSAFE_ACTION_1
254 : { 0, 5, 1, ARRAY_SIZE(THR_FS_ACT), THR_FS_ACT }, // OSD_PARAM_FAILSAFE_ACTION_2
255 : };
256 :
257 : #else
258 : const AP_OSD_ParamSetting::ParamMetadata AP_OSD_ParamSetting::_param_metadata[unsigned(AP_OSD_ParamSetting::Type::NUM_TYPES)] = {};
259 : #endif
260 :
261 : extern const AP_HAL::HAL& hal;
262 :
263 : // default constructor that just sets some sensible defaults that exist on all platforms
264 0 : AP_OSD_ParamSetting::AP_OSD_ParamSetting(uint8_t param_number) :
265 0 : _param_number(param_number),
266 0 : default_ypos(param_number + 1),
267 0 : default_param_group(-1),
268 0 : default_param_idx(-1),
269 0 : default_param_key(-1)
270 : {
271 0 : AP_Param::setup_object_defaults(this, var_info);
272 0 : }
273 :
274 : // construct a setting from a compact static initializer structure
275 37098 : AP_OSD_ParamSetting::AP_OSD_ParamSetting(const Initializer& initializer) :
276 37098 : _param_number(initializer.index),
277 37098 : default_enabled(true),
278 37098 : default_ypos(initializer.index + 1),
279 37098 : default_param_group(initializer.token.group_element),
280 37098 : default_param_idx(initializer.token.idx),
281 37098 : default_param_key(initializer.token.key),
282 37098 : default_type(float(initializer.type))
283 : {
284 37098 : AP_Param::setup_object_defaults(this, var_info);
285 37098 : }
286 :
287 : // update the contained parameter
288 0 : void AP_OSD_ParamSetting::update()
289 : {
290 : // if the user has not made any changes then skip the update
291 0 : if (PARAM_TOKEN_INDEX(_current_token) == PARAM_COMPOSITE_INDEX(_param_key, _param_idx, _param_group) && _param_key >= 0) {
292 0 : return;
293 : }
294 : // if a parameter was configured then use that
295 0 : _current_token = AP_Param::ParamToken {};
296 : // surely there is a more efficient way than brute-force search
297 0 : for (_param = AP_Param::first(&_current_token, &_param_type);
298 0 : _param && (AP_Param::get_persistent_key(_current_token.key) != uint16_t(_param_key.get())
299 0 : || _current_token.idx != uint8_t(_param_idx.get())
300 0 : || _current_token.group_element != uint32_t(_param_group.get()));
301 0 : _param = AP_Param::next_scalar(&_current_token, &_param_type)) {
302 : }
303 :
304 0 : if (_param == nullptr) {
305 0 : enabled.set(false);
306 : } else {
307 0 : guess_ranges();
308 : }
309 : }
310 :
311 : // update parameter settings from the named parameter
312 0 : bool AP_OSD_ParamSetting::set_by_name(const char* name, uint8_t config_type, float pmin, float pmax, float pincr)
313 : {
314 0 : AP_Param::ParamToken token = AP_Param::ParamToken {};
315 : ap_var_type type;
316 0 : AP_Param* param = AP_Param::find_by_name(name, &type, &token);
317 :
318 0 : if (param == nullptr) {
319 : // leave unchanged
320 0 : return false;
321 : } else {
322 0 : _current_token = token;
323 0 : _param_type = type;
324 0 : _param = param;
325 0 : enabled.set_and_save_ifchanged(true);
326 : }
327 :
328 0 : _type.set_and_save_ifchanged(config_type);
329 :
330 0 : if (config_type == uint8_t(Type::NONE) && !is_zero(pincr)) {
331 : // ranges
332 0 : _param_min.set_and_save_ifchanged(pmin);
333 0 : _param_max.set_and_save_ifchanged(pmax);
334 0 : _param_incr.set_and_save_ifchanged(pincr);
335 : } else {
336 0 : guess_ranges(true);
337 : }
338 :
339 0 : _param_key.set_and_save_ifchanged(AP_Param::get_persistent_key(_current_token.key));
340 0 : _param_idx.set_and_save_ifchanged(_current_token.idx);
341 0 : _param_group.set_and_save_ifchanged(_current_token.group_element);
342 0 : return true;
343 : }
344 :
345 : // guess the ranges and increment for the selected parameter
346 : // only called when a change has been made
347 0 : void AP_OSD_ParamSetting::guess_ranges(bool force)
348 : {
349 0 : if (_param->is_read_only()) {
350 0 : return;
351 : }
352 :
353 : // check for statically configured setting metadata
354 0 : if (set_from_metadata()) {
355 0 : return;
356 : }
357 :
358 : // nothing statically configured so guess some appropriate values
359 0 : float min = -1, max = 127, incr = 1;
360 :
361 0 : if (_param != nullptr) {
362 0 : switch (_param_type) {
363 0 : case AP_PARAM_INT8:
364 0 : break;
365 0 : case AP_PARAM_INT16: {
366 0 : AP_Int16* p = (AP_Int16*)_param;
367 0 : min = -1;
368 0 : uint8_t digits = 0;
369 0 : for (int16_t int16p = p->get(); int16p > 0; int16p /= 10) {
370 0 : digits++;
371 : }
372 0 : incr = MAX(1, powf(10, digits - 2));
373 0 : max = powf(10, digits + 1);
374 : debug("Guessing range for value %d as %f -> %f, %f\n", p->get(), min, max, incr);
375 0 : break;
376 : }
377 0 : case AP_PARAM_INT32: {
378 0 : AP_Int32* p = (AP_Int32*)_param;
379 0 : min = -1;
380 0 : uint8_t digits = 0;
381 0 : for (int32_t int32p = p->get(); int32p > 0; int32p /= 10) {
382 0 : digits++;
383 : }
384 0 : incr = MAX(1, powf(10, digits - 2));
385 0 : max = powf(10, digits + 1);
386 : debug("Guessing range for value %d as %f -> %f, %f\n", int(p->get()), min, max, incr);
387 0 : break;
388 : }
389 0 : case AP_PARAM_FLOAT: {
390 0 : AP_Float* p = (AP_Float*)_param;
391 :
392 0 : uint8_t digits = 0;
393 0 : for (float floatp = p->get(); floatp > 1.0f; floatp /= 10) {
394 0 : digits++;
395 : }
396 0 : float floatp = p->get();
397 0 : if (digits < 1) {
398 0 : if (!is_zero(floatp)) {
399 0 : incr = floatp * 0.01f; // move in 1% increments
400 : } else {
401 0 : incr = 0.01f; // move in absolute 1% increments
402 : }
403 0 : max = 1.0;
404 0 : min = 0.0f;
405 : } else {
406 0 : if (!is_zero(floatp)) {
407 0 : incr = floatp * 0.01f; // move in 1% increments
408 : } else {
409 0 : incr = MAX(1, powf(10, digits - 2));
410 : }
411 0 : max = powf(10, digits + 1);
412 0 : min = 0.0f;
413 : }
414 : debug("Guessing range for value %f as %f -> %f, %f\n", p->get(), min, max, incr);
415 0 : break;
416 : }
417 0 : case AP_PARAM_VECTOR3F:
418 : case AP_PARAM_NONE:
419 : case AP_PARAM_GROUP:
420 0 : break;
421 : }
422 :
423 0 : if (force || !_param_min.configured()) {
424 0 : _param_min.set(min);
425 : }
426 0 : if (force || !_param_max.configured()) {
427 0 : _param_max.set(max);
428 : }
429 0 : if (force || !_param_incr.configured()) {
430 0 : _param_incr.set(incr);
431 : }
432 : }
433 : }
434 :
435 : // copy the name converting FOO_BAR_BAZ to FooBarBaz
436 0 : void AP_OSD_ParamSetting::copy_name_camel_case(char* name, size_t len) const
437 : {
438 : char buf[17];
439 0 : _param->copy_name_token(_current_token, buf, 17);
440 0 : buf[16] = 0;
441 0 : name[0] = buf[0];
442 0 : for (uint8_t i = 1, n = 1; i < len; i++, n++) {
443 0 : if (buf[i] == '_') {
444 0 : name[n] = buf[i+1];
445 0 : i++;
446 : } else {
447 0 : name[n] = tolower(buf[i]);
448 : }
449 : }
450 0 : }
451 :
452 0 : bool AP_OSD_ParamSetting::set_from_metadata()
453 : {
454 : // check for statically configured setting metadata
455 0 : if (_type > 0 && _type < uint8_t(Type::NUM_TYPES) && _param_metadata[_type - 1].values_max > 0) {
456 0 : _param_incr.set(_param_metadata[_type - 1].increment);
457 0 : _param_min.set(_param_metadata[_type - 1].min_value);
458 0 : _param_max.set(_param_metadata[_type - 1].max_value);
459 0 : return true;
460 : }
461 0 : return false;
462 : }
463 :
464 : // modify the selected parameter values
465 0 : void AP_OSD_ParamSetting::save_as_new()
466 : {
467 0 : _param_group.save();
468 0 : _param_key.save();
469 0 : _param_idx.save();
470 : // the user has configured the range and increment, but the parameter
471 : // is no longer valid so reset these to guessed values
472 0 : guess_ranges(true);
473 0 : if (_param_min.configured()) {
474 0 : _param_min.save();
475 : }
476 0 : if (_param_max.configured()) {
477 0 : _param_max.save();
478 : }
479 0 : if (_param_incr.configured()) {
480 0 : _param_incr.save();
481 : }
482 0 : }
483 :
484 : #endif // OSD_PARAM_ENABLED
485 :
|