1 /* This file is part of Cleanflight.
3 * Cleanflight is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * Cleanflight is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 // Mixer and servo menu
30 #include "common/utils.h"
32 #include "build/version.h"
34 #include "flight/mixer_profile.h"
35 #include "flight/mixer.h"
36 #include "flight/servos.h"
39 #include "cms/cms_types.h"
40 #include "cms_menu_mixer_servo.h"
42 #include "fc/runtime_config.h"
43 #include "fc/settings.h"
44 #include "fc/config.h"
46 static uint8_t currentMotorMixerIndex
= 0;
47 static uint8_t tmpcurrentMotorMixerIndex
= 1;
48 static uint16_t tmpMotorMixerThrottle
;
49 static int16_t tmpMotorMixerRoll
;
50 static int16_t tmpMotorMixerYaw
;
51 static int16_t tmpMotorMixerPitch
;
52 static uint8_t currentServoMixerIndex
= 0;
53 static uint8_t tmpcurrentServoMixerIndex
= 1;
54 static servoMixer_t tmpServoMixer
;
55 static uint8_t currentServoIndex
= 0;
56 static uint8_t oldServoIndex
= 0;
57 static servoParam_t tmpServoParam
;
59 static void loadServoSettings(void)
61 tmpServoParam
.middle
= servoParams(currentServoIndex
)->middle
;
62 tmpServoParam
.min
= servoParams(currentServoIndex
)->min
;
63 tmpServoParam
.max
= servoParams(currentServoIndex
)->max
;
64 tmpServoParam
.rate
= servoParams(currentServoIndex
)->rate
;
67 static void saveServoSettings(uint8_t idx
)
69 servoParamsMutable(idx
)->middle
= tmpServoParam
.middle
;
70 servoParamsMutable(idx
)->min
= tmpServoParam
.min
;
71 servoParamsMutable(idx
)->max
= tmpServoParam
.max
;
72 servoParamsMutable(idx
)->rate
= tmpServoParam
.rate
;
75 static long cmsx_menuServo_onEnter(const OSD_Entry
*from
)
84 static long cmsx_menuServo_onExit(const OSD_Entry
*from
)
88 saveServoSettings(currentServoIndex
);
93 static long cmsx_menuServoIndexOnChange(displayPort_t
*displayPort
, const void *ptr
)
98 saveServoSettings(oldServoIndex
);
100 oldServoIndex
= currentServoIndex
;
105 static const OSD_Entry cmsx_menuServoEntries
[] =
107 OSD_LABEL_ENTRY("-- SERVOS --"),
108 OSD_UINT8_CALLBACK_ENTRY("SERVO", cmsx_menuServoIndexOnChange
, (&(const OSD_UINT8_t
){ ¤tServoIndex
, 0, MAX_SUPPORTED_SERVOS
- 1, 1})),
109 OSD_INT16_DYN_ENTRY("MID", (&(const OSD_INT16_t
){&tmpServoParam
.middle
, 500, 2500, 1})),
110 OSD_INT16_DYN_ENTRY("MIN", (&(const OSD_INT16_t
){&tmpServoParam
.min
, 500, 2500, 1})),
111 OSD_INT16_DYN_ENTRY("MAX", (&(const OSD_INT16_t
){&tmpServoParam
.max
, 500, 2500, 1})),
112 OSD_INT8_DYN_ENTRY("RATE", (&(const OSD_INT8_t
){&tmpServoParam
.rate
, -125, 125, 1})),
113 OSD_BACK_AND_END_ENTRY
116 const CMS_Menu cmsx_menuServo
= {
117 #ifdef CMS_MENU_DEBUG
118 .GUARD_text
= "MENUSERVO",
119 .GUARD_type
= OME_MENU
,
121 .onEnter
= cmsx_menuServo_onEnter
,
122 .onExit
= cmsx_menuServo_onExit
,
123 .onGlobalExit
= NULL
,
124 .entries
= cmsx_menuServoEntries
127 #define SERVO_MIXER_INPUT_CMS_NAMES_COUNT 23
128 const char * const servoMixerInputCmsNames
[SERVO_MIXER_INPUT_CMS_NAMES_COUNT
] = {
154 static void loadServoMixerSettings(void)
156 tmpServoMixer
.targetChannel
= customServoMixers(currentServoMixerIndex
)->targetChannel
;
157 tmpServoMixer
.inputSource
= customServoMixers(currentServoMixerIndex
)->inputSource
;
158 tmpServoMixer
.rate
= customServoMixers(currentServoMixerIndex
)->rate
;
159 tmpServoMixer
.speed
= customServoMixers(currentServoMixerIndex
)->speed
;
162 static void saveServoMixerSettings(void)
164 customServoMixersMutable(currentServoMixerIndex
)->targetChannel
= tmpServoMixer
.targetChannel
;
165 customServoMixersMutable(currentServoMixerIndex
)->inputSource
= tmpServoMixer
.inputSource
;
166 customServoMixersMutable(currentServoMixerIndex
)->rate
= tmpServoMixer
.rate
;
167 customServoMixersMutable(currentServoMixerIndex
)->speed
= tmpServoMixer
.speed
;
171 static long cmsx_menuServoMixer_onEnter(const OSD_Entry
*from
)
175 loadServoMixerSettings();
180 static long cmsx_menuServoMixer_onExit(const OSD_Entry
*from
)
184 saveServoMixerSettings();
189 static long cmsx_menuServoMixerIndexOnChange(displayPort_t
*displayPort
, const void *ptr
)
194 saveServoMixerSettings();
195 currentServoMixerIndex
= tmpcurrentServoMixerIndex
- 1;
196 loadServoMixerSettings();
201 static const OSD_Entry cmsx_menuServoMixerEntries
[] =
203 OSD_LABEL_ENTRY("-- SERVO MIXER --"),
204 OSD_UINT8_CALLBACK_ENTRY("SERVO MIX", cmsx_menuServoMixerIndexOnChange
, (&(const OSD_UINT8_t
){ &tmpcurrentServoMixerIndex
, 1, MAX_SERVO_RULES
, 1})),
205 OSD_UINT8_DYN_ENTRY("SERVO", (&(const OSD_UINT8_t
){ &tmpServoMixer
.targetChannel
, 0, MAX_SUPPORTED_SERVOS
, 1})),
206 OSD_TAB_DYN_ENTRY("INPUT", (&(const OSD_TAB_t
){ &tmpServoMixer
.inputSource
, SERVO_MIXER_INPUT_CMS_NAMES_COUNT
- 1, servoMixerInputCmsNames
})),
207 OSD_INT16_DYN_ENTRY("WEIGHT", (&(const OSD_INT16_t
){&tmpServoMixer
.rate
, -1000, 1000, 1})),
208 OSD_UINT8_DYN_ENTRY("SPEED", (&(const OSD_UINT8_t
){&tmpServoMixer
.speed
, 0, 255, 1})),
209 OSD_BACK_AND_END_ENTRY
212 const CMS_Menu cmsx_menuServoMixer
= {
213 #ifdef CMS_MENU_DEBUG
214 .GUARD_text
= "MENUSERVOMIXER",
215 .GUARD_type
= OME_MENU
,
217 .onEnter
= cmsx_menuServoMixer_onEnter
,
218 .onExit
= cmsx_menuServoMixer_onExit
,
219 .onGlobalExit
= NULL
,
220 .entries
= cmsx_menuServoMixerEntries
223 static void loadMotorMixerSettings(void)
225 tmpMotorMixerThrottle
= primaryMotorMixer(currentMotorMixerIndex
)->throttle
* 1000;
226 tmpMotorMixerRoll
= primaryMotorMixer(currentMotorMixerIndex
)->roll
* 1000;
227 tmpMotorMixerPitch
= primaryMotorMixer(currentMotorMixerIndex
)->pitch
* 1000;
228 tmpMotorMixerYaw
= primaryMotorMixer(currentMotorMixerIndex
)->yaw
* 1000;
231 static void saveMotorMixerSettings(void)
233 primaryMotorMixerMutable(currentMotorMixerIndex
)->throttle
= tmpMotorMixerThrottle
/ 1000.0f
;
234 primaryMotorMixerMutable(currentMotorMixerIndex
)->roll
= tmpMotorMixerRoll
/ 1000.0f
;
235 primaryMotorMixerMutable(currentMotorMixerIndex
)->pitch
= tmpMotorMixerPitch
/ 1000.0f
;
236 primaryMotorMixerMutable(currentMotorMixerIndex
)->yaw
= tmpMotorMixerYaw
/ 1000.0f
;
239 static long cmsx_menuMotorMixer_onEnter(const OSD_Entry
*from
)
243 loadMotorMixerSettings();
248 static long cmsx_menuMotorMixer_onExit(const OSD_Entry
*self
)
252 saveMotorMixerSettings();
257 static long cmsx_menuMotorMixerIndexOnChange(displayPort_t
*displayPort
, const void *ptr
)
262 saveMotorMixerSettings();
263 currentMotorMixerIndex
= tmpcurrentMotorMixerIndex
- 1;
264 loadMotorMixerSettings();
269 static const OSD_Entry cmsx_motorMixerEntries
[] =
271 OSD_LABEL_ENTRY("-- MOTOR MIXER --"),
272 OSD_UINT8_CALLBACK_ENTRY ("MOTOR", cmsx_menuMotorMixerIndexOnChange
, (&(const OSD_UINT8_t
){ &tmpcurrentMotorMixerIndex
, 1, MAX_SUPPORTED_MOTORS
, 1})),
273 OSD_UINT16_DYN_ENTRY("THROTTLE", (&(const OSD_UINT16_t
){ &tmpMotorMixerThrottle
, 0, 1000, 1 })),
274 OSD_INT16_DYN_ENTRY("ROLL", (&(const OSD_INT16_t
){ &tmpMotorMixerRoll
, -2000, 2000, 1 })),
275 OSD_INT16_DYN_ENTRY("PITCH", (&(const OSD_INT16_t
){ &tmpMotorMixerPitch
, -2000, 2000, 1 })),
276 OSD_INT16_DYN_ENTRY("YAW", (&(const OSD_INT16_t
){ &tmpMotorMixerYaw
, -2000, 2000, 1 })),
277 OSD_BACK_AND_END_ENTRY
280 const CMS_Menu cmsx_menuMotorMixer
= {
281 #ifdef CMS_MENU_DEBUG
282 .GUARD_text
= "MENUMMOTORMIXER",
283 .GUARD_type
= OME_MENU
,
285 .onEnter
= cmsx_menuMotorMixer_onEnter
,
286 .onExit
= cmsx_menuMotorMixer_onExit
,
287 .onGlobalExit
= NULL
,
288 .entries
= cmsx_motorMixerEntries
291 static const OSD_Entry cmsx_mixerServoEntries
[] =
293 OSD_LABEL_ENTRY("-- MIXER AND SERVOS --"),
294 OSD_SETTING_ENTRY("PLATFORM", SETTING_PLATFORM_TYPE
),
295 OSD_SETTING_ENTRY("HAS FLAPS", SETTING_HAS_FLAPS
),
296 OSD_SUBMENU_ENTRY("MOTOR MIXER", &cmsx_menuMotorMixer
),
297 OSD_SUBMENU_ENTRY("SERVO MIXER", &cmsx_menuServoMixer
),
298 OSD_SUBMENU_ENTRY("SERVOS", &cmsx_menuServo
),
299 OSD_BACK_AND_END_ENTRY
302 const CMS_Menu cmsx_menuMixerServo
= {
303 #ifdef CMS_MENU_DEBUG
304 .GUARD_text
= "MENUMIXERSERVO",
305 .GUARD_type
= OME_MENU
,
309 .onGlobalExit
= NULL
,
310 .entries
= cmsx_mixerServoEntries