2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
29 #include "blackbox/blackbox.h"
30 #include "blackbox/blackbox_fielddefs.h"
32 #include "build/build_config.h"
34 #include "common/axis.h"
35 #include "common/maths.h"
36 #include "common/utils.h"
38 #include "config/feature.h"
40 #include "drivers/time.h"
42 #include "flight/pid.h"
44 #include "io/beeper.h"
45 #include "io/ledstrip.h"
46 #include "io/motors.h"
47 #include "io/pidaudio.h"
50 #include "fc/config.h"
51 #include "fc/controlrate_profile.h"
52 #include "fc/rc_controls.h"
56 #include "pg/pg_ids.h"
61 #include "rc_adjustments.h"
63 #define ADJUSTMENT_RANGE_COUNT_INVALID -1
65 PG_REGISTER_ARRAY(adjustmentRange_t
, MAX_ADJUSTMENT_RANGE_COUNT
, adjustmentRanges
, PG_ADJUSTMENT_RANGE_CONFIG
, 1);
67 uint8_t pidAudioPositionToModeMap
[7] = {
68 // on a pot with a center detent, it's easy to have center area for off/default, then three positions to the left and three to the right.
69 // current implementation yields RC values as below.
71 PID_AUDIO_PIDSUM_X
, // 900 - ~1071 - Min
72 PID_AUDIO_PIDSUM_Y
, // ~1071 - ~1242
73 PID_AUDIO_PIDSUM_XY
, // ~1242 - ~1414
74 PID_AUDIO_OFF
, // ~1414 - ~1585 - Center
75 PID_AUDIO_OFF
, // ~1585 - ~1757
76 PID_AUDIO_OFF
, // ~1757 - ~1928
77 PID_AUDIO_OFF
, // ~1928 - 2100 - Max
79 // Note: Last 3 positions are currently pending implementations and use PID_AUDIO_OFF for now.
82 static int activeAdjustmentCount
= ADJUSTMENT_RANGE_COUNT_INVALID
;
83 static uint8_t activeAdjustmentArray
[MAX_ADJUSTMENT_RANGE_COUNT
];
84 static int activeAbsoluteAdjustmentCount
;
85 static uint8_t activeAbsoluteAdjustmentArray
[MAX_ADJUSTMENT_RANGE_COUNT
];
87 static void blackboxLogInflightAdjustmentEvent(adjustmentFunction_e adjustmentFunction
, int32_t newValue
)
90 UNUSED(adjustmentFunction
);
93 if (blackboxConfig()->device
) {
94 flightLogEvent_inflightAdjustment_t eventData
;
95 eventData
.adjustmentFunction
= adjustmentFunction
;
96 eventData
.newValue
= newValue
;
97 eventData
.floatFlag
= false;
98 blackboxLogEvent(FLIGHT_LOG_EVENT_INFLIGHT_ADJUSTMENT
, (flightLogEventData_t
*)&eventData
);
104 static void blackboxLogInflightAdjustmentEventFloat(adjustmentFunction_e adjustmentFunction
, float newFloatValue
)
107 UNUSED(adjustmentFunction
);
108 UNUSED(newFloatValue
);
110 if (blackboxConfig()->device
) {
111 flightLogEvent_inflightAdjustment_t eventData
;
112 eventData
.adjustmentFunction
= adjustmentFunction
;
113 eventData
.newFloatValue
= newFloatValue
;
114 eventData
.floatFlag
= true;
115 blackboxLogEvent(FLIGHT_LOG_EVENT_INFLIGHT_ADJUSTMENT
, (flightLogEventData_t
*)&eventData
);
121 STATIC_UNIT_TESTED
uint8_t adjustmentStateMask
= 0;
123 #define MARK_ADJUSTMENT_FUNCTION_AS_BUSY(adjustmentIndex) adjustmentStateMask |= (1 << adjustmentIndex)
124 #define MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex) adjustmentStateMask &= ~(1 << adjustmentIndex)
126 #define IS_ADJUSTMENT_FUNCTION_BUSY(adjustmentIndex) (adjustmentStateMask & (1 << adjustmentIndex))
128 // sync with adjustmentFunction_e
129 static const adjustmentConfig_t defaultAdjustmentConfigs
[ADJUSTMENT_FUNCTION_COUNT
- 1] = {
131 .adjustmentFunction
= ADJUSTMENT_RC_RATE
,
132 .mode
= ADJUSTMENT_MODE_STEP
,
133 .data
= { .step
= 1 }
135 .adjustmentFunction
= ADJUSTMENT_RC_EXPO
,
136 .mode
= ADJUSTMENT_MODE_STEP
,
137 .data
= { .step
= 1 }
139 .adjustmentFunction
= ADJUSTMENT_THROTTLE_EXPO
,
140 .mode
= ADJUSTMENT_MODE_STEP
,
141 .data
= { .step
= 1 }
143 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_RATE
,
144 .mode
= ADJUSTMENT_MODE_STEP
,
145 .data
= { .step
= 1 }
147 .adjustmentFunction
= ADJUSTMENT_YAW_RATE
,
148 .mode
= ADJUSTMENT_MODE_STEP
,
149 .data
= { .step
= 1 }
151 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_P
,
152 .mode
= ADJUSTMENT_MODE_STEP
,
153 .data
= { .step
= 1 }
155 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_I
,
156 .mode
= ADJUSTMENT_MODE_STEP
,
157 .data
= { .step
= 1 }
159 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_D
,
160 .mode
= ADJUSTMENT_MODE_STEP
,
161 .data
= { .step
= 1 }
163 .adjustmentFunction
= ADJUSTMENT_YAW_P
,
164 .mode
= ADJUSTMENT_MODE_STEP
,
165 .data
= { .step
= 1 }
167 .adjustmentFunction
= ADJUSTMENT_YAW_I
,
168 .mode
= ADJUSTMENT_MODE_STEP
,
169 .data
= { .step
= 1 }
171 .adjustmentFunction
= ADJUSTMENT_YAW_D
,
172 .mode
= ADJUSTMENT_MODE_STEP
,
173 .data
= { .step
= 1 }
175 .adjustmentFunction
= ADJUSTMENT_RATE_PROFILE
,
176 .mode
= ADJUSTMENT_MODE_SELECT
,
177 .data
= { .switchPositions
= 3 }
179 .adjustmentFunction
= ADJUSTMENT_PITCH_RATE
,
180 .mode
= ADJUSTMENT_MODE_STEP
,
181 .data
= { .step
= 1 }
183 .adjustmentFunction
= ADJUSTMENT_ROLL_RATE
,
184 .mode
= ADJUSTMENT_MODE_STEP
,
185 .data
= { .step
= 1 }
187 .adjustmentFunction
= ADJUSTMENT_PITCH_P
,
188 .mode
= ADJUSTMENT_MODE_STEP
,
189 .data
= { .step
= 1 }
191 .adjustmentFunction
= ADJUSTMENT_PITCH_I
,
192 .mode
= ADJUSTMENT_MODE_STEP
,
193 .data
= { .step
= 1 }
195 .adjustmentFunction
= ADJUSTMENT_PITCH_D
,
196 .mode
= ADJUSTMENT_MODE_STEP
,
197 .data
= { .step
= 1 }
199 .adjustmentFunction
= ADJUSTMENT_ROLL_P
,
200 .mode
= ADJUSTMENT_MODE_STEP
,
201 .data
= { .step
= 1 }
203 .adjustmentFunction
= ADJUSTMENT_ROLL_I
,
204 .mode
= ADJUSTMENT_MODE_STEP
,
205 .data
= { .step
= 1 }
207 .adjustmentFunction
= ADJUSTMENT_ROLL_D
,
208 .mode
= ADJUSTMENT_MODE_STEP
,
209 .data
= { .step
= 1 }
211 .adjustmentFunction
= ADJUSTMENT_RC_RATE_YAW
,
212 .mode
= ADJUSTMENT_MODE_STEP
,
213 .data
= { .step
= 1 }
215 .adjustmentFunction
= ADJUSTMENT_PITCH_ROLL_F
,
216 .mode
= ADJUSTMENT_MODE_STEP
,
217 .data
= { .step
= 1 }
219 .adjustmentFunction
= ADJUSTMENT_FEEDFORWARD_TRANSITION
,
220 .mode
= ADJUSTMENT_MODE_STEP
,
221 .data
= { .step
= 1 }
223 .adjustmentFunction
= ADJUSTMENT_HORIZON_STRENGTH
,
224 .mode
= ADJUSTMENT_MODE_SELECT
,
225 .data
= { .switchPositions
= 255 }
227 .adjustmentFunction
= ADJUSTMENT_PID_AUDIO
,
228 .mode
= ADJUSTMENT_MODE_SELECT
,
229 .data
= { .switchPositions
= ARRAYLEN(pidAudioPositionToModeMap
) }
231 .adjustmentFunction
= ADJUSTMENT_PITCH_F
,
232 .mode
= ADJUSTMENT_MODE_STEP
,
233 .data
= { .step
= 1 }
235 .adjustmentFunction
= ADJUSTMENT_ROLL_F
,
236 .mode
= ADJUSTMENT_MODE_STEP
,
237 .data
= { .step
= 1 }
239 .adjustmentFunction
= ADJUSTMENT_YAW_F
,
240 .mode
= ADJUSTMENT_MODE_STEP
,
241 .data
= { .step
= 1 }
243 .adjustmentFunction
= ADJUSTMENT_OSD_PROFILE
,
244 .mode
= ADJUSTMENT_MODE_SELECT
,
245 .data
= { .switchPositions
= 3 }
247 .adjustmentFunction
= ADJUSTMENT_LED_PROFILE
,
248 .mode
= ADJUSTMENT_MODE_SELECT
,
249 .data
= { .switchPositions
= 3 }
253 #if defined(USE_OSD) && defined(USE_OSD_ADJUSTMENTS)
254 static const char * const adjustmentLabels
[] = {
290 static int adjustmentRangeNameIndex
= 0;
291 static int adjustmentRangeValue
= -1;
294 #define ADJUSTMENT_FUNCTION_CONFIG_INDEX_OFFSET 1
296 STATIC_UNIT_TESTED adjustmentState_t adjustmentStates
[MAX_SIMULTANEOUS_ADJUSTMENT_COUNT
];
298 STATIC_UNIT_TESTED
void configureAdjustment(uint8_t index
, uint8_t auxSwitchChannelIndex
, const adjustmentConfig_t
*adjustmentConfig
)
300 adjustmentState_t
*adjustmentState
= &adjustmentStates
[index
];
302 if (adjustmentState
->config
== adjustmentConfig
) {
303 // already configured
306 adjustmentState
->auxChannelIndex
= auxSwitchChannelIndex
;
307 adjustmentState
->config
= adjustmentConfig
;
308 adjustmentState
->timeoutAt
= 0;
310 MARK_ADJUSTMENT_FUNCTION_AS_READY(index
);
313 static int applyStepAdjustment(controlRateConfig_t
*controlRateConfig
, uint8_t adjustmentFunction
, int delta
)
316 beeperConfirmationBeeps(delta
> 0 ? 2 : 1);
318 switch (adjustmentFunction
) {
319 case ADJUSTMENT_RC_RATE
:
320 case ADJUSTMENT_ROLL_RC_RATE
:
321 newValue
= constrain((int)controlRateConfig
->rcRates
[FD_ROLL
] + delta
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
322 controlRateConfig
->rcRates
[FD_ROLL
] = newValue
;
323 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RC_RATE
, newValue
);
324 if (adjustmentFunction
== ADJUSTMENT_ROLL_RC_RATE
) {
327 // fall through for combined ADJUSTMENT_RC_EXPO
329 case ADJUSTMENT_PITCH_RC_RATE
:
330 newValue
= constrain((int)controlRateConfig
->rcRates
[FD_PITCH
] + delta
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
331 controlRateConfig
->rcRates
[FD_PITCH
] = newValue
;
332 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RC_RATE
, newValue
);
334 case ADJUSTMENT_RC_EXPO
:
335 case ADJUSTMENT_ROLL_RC_EXPO
:
336 newValue
= constrain((int)controlRateConfig
->rcExpo
[FD_ROLL
] + delta
, 0, CONTROL_RATE_CONFIG_RC_EXPO_MAX
);
337 controlRateConfig
->rcExpo
[FD_ROLL
] = newValue
;
338 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RC_EXPO
, newValue
);
339 if (adjustmentFunction
== ADJUSTMENT_ROLL_RC_EXPO
) {
342 // fall through for combined ADJUSTMENT_RC_EXPO
344 case ADJUSTMENT_PITCH_RC_EXPO
:
345 newValue
= constrain((int)controlRateConfig
->rcExpo
[FD_PITCH
] + delta
, 0, CONTROL_RATE_CONFIG_RC_EXPO_MAX
);
346 controlRateConfig
->rcExpo
[FD_PITCH
] = newValue
;
347 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RC_EXPO
, newValue
);
349 case ADJUSTMENT_THROTTLE_EXPO
:
350 newValue
= constrain((int)controlRateConfig
->thrExpo8
+ delta
, 0, 100); // FIXME magic numbers repeated in cli.c
351 controlRateConfig
->thrExpo8
= newValue
;
353 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_THROTTLE_EXPO
, newValue
);
355 case ADJUSTMENT_PITCH_ROLL_RATE
:
356 case ADJUSTMENT_PITCH_RATE
:
357 newValue
= constrain((int)controlRateConfig
->rates
[FD_PITCH
] + delta
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
358 controlRateConfig
->rates
[FD_PITCH
] = newValue
;
359 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RATE
, newValue
);
360 if (adjustmentFunction
== ADJUSTMENT_PITCH_RATE
) {
363 // fall through for combined ADJUSTMENT_PITCH_ROLL_RATE
365 case ADJUSTMENT_ROLL_RATE
:
366 newValue
= constrain((int)controlRateConfig
->rates
[FD_ROLL
] + delta
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
367 controlRateConfig
->rates
[FD_ROLL
] = newValue
;
368 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RATE
, newValue
);
370 case ADJUSTMENT_YAW_RATE
:
371 newValue
= constrain((int)controlRateConfig
->rates
[FD_YAW
] + delta
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
372 controlRateConfig
->rates
[FD_YAW
] = newValue
;
373 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_RATE
, newValue
);
375 case ADJUSTMENT_PITCH_ROLL_P
:
376 case ADJUSTMENT_PITCH_P
:
377 newValue
= constrain((int)currentPidProfile
->pid
[PID_PITCH
].P
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
378 currentPidProfile
->pid
[PID_PITCH
].P
= newValue
;
379 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_P
, newValue
);
381 if (adjustmentFunction
== ADJUSTMENT_PITCH_P
) {
384 // fall through for combined ADJUSTMENT_PITCH_ROLL_P
386 case ADJUSTMENT_ROLL_P
:
387 newValue
= constrain((int)currentPidProfile
->pid
[PID_ROLL
].P
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
388 currentPidProfile
->pid
[PID_ROLL
].P
= newValue
;
389 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_P
, newValue
);
391 case ADJUSTMENT_PITCH_ROLL_I
:
392 case ADJUSTMENT_PITCH_I
:
393 newValue
= constrain((int)currentPidProfile
->pid
[PID_PITCH
].I
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
394 currentPidProfile
->pid
[PID_PITCH
].I
= newValue
;
395 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_I
, newValue
);
396 if (adjustmentFunction
== ADJUSTMENT_PITCH_I
) {
399 // fall through for combined ADJUSTMENT_PITCH_ROLL_I
401 case ADJUSTMENT_ROLL_I
:
402 newValue
= constrain((int)currentPidProfile
->pid
[PID_ROLL
].I
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
403 currentPidProfile
->pid
[PID_ROLL
].I
= newValue
;
404 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_I
, newValue
);
406 case ADJUSTMENT_PITCH_ROLL_D
:
407 case ADJUSTMENT_PITCH_D
:
408 newValue
= constrain((int)currentPidProfile
->pid
[PID_PITCH
].D
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
409 currentPidProfile
->pid
[PID_PITCH
].D
= newValue
;
410 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_D
, newValue
);
411 if (adjustmentFunction
== ADJUSTMENT_PITCH_D
) {
414 // fall through for combined ADJUSTMENT_PITCH_ROLL_D
416 case ADJUSTMENT_ROLL_D
:
417 newValue
= constrain((int)currentPidProfile
->pid
[PID_ROLL
].D
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
418 currentPidProfile
->pid
[PID_ROLL
].D
= newValue
;
419 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_D
, newValue
);
421 case ADJUSTMENT_YAW_P
:
422 newValue
= constrain((int)currentPidProfile
->pid
[PID_YAW
].P
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
423 currentPidProfile
->pid
[PID_YAW
].P
= newValue
;
424 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_P
, newValue
);
426 case ADJUSTMENT_YAW_I
:
427 newValue
= constrain((int)currentPidProfile
->pid
[PID_YAW
].I
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
428 currentPidProfile
->pid
[PID_YAW
].I
= newValue
;
429 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_I
, newValue
);
431 case ADJUSTMENT_YAW_D
:
432 newValue
= constrain((int)currentPidProfile
->pid
[PID_YAW
].D
+ delta
, 0, 200); // FIXME magic numbers repeated in cli.c
433 currentPidProfile
->pid
[PID_YAW
].D
= newValue
;
434 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_D
, newValue
);
436 case ADJUSTMENT_RC_RATE_YAW
:
437 newValue
= constrain((int)controlRateConfig
->rcRates
[FD_YAW
] + delta
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
438 controlRateConfig
->rcRates
[FD_YAW
] = newValue
;
439 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_RC_RATE_YAW
, newValue
);
441 case ADJUSTMENT_PITCH_ROLL_F
:
442 case ADJUSTMENT_PITCH_F
:
443 newValue
= constrain(currentPidProfile
->pid
[PID_PITCH
].F
+ delta
, 0, 2000);
444 currentPidProfile
->pid
[PID_PITCH
].F
= newValue
;
445 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_F
, newValue
);
447 if (adjustmentFunction
== ADJUSTMENT_PITCH_F
) {
450 // fall through for combined ADJUSTMENT_PITCH_ROLL_F
452 case ADJUSTMENT_ROLL_F
:
453 newValue
= constrain(currentPidProfile
->pid
[PID_ROLL
].F
+ delta
, 0, 2000);
454 currentPidProfile
->pid
[PID_ROLL
].F
= newValue
;
455 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_F
, newValue
);
457 case ADJUSTMENT_YAW_F
:
458 newValue
= constrain(currentPidProfile
->pid
[PID_YAW
].F
+ delta
, 0, 2000);
459 currentPidProfile
->pid
[PID_YAW
].F
= newValue
;
460 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_F
, newValue
);
462 case ADJUSTMENT_FEEDFORWARD_TRANSITION
:
463 newValue
= constrain(currentPidProfile
->feedForwardTransition
+ delta
, 1, 100); // FIXME magic numbers repeated in cli.c
464 currentPidProfile
->feedForwardTransition
= newValue
;
465 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_FEEDFORWARD_TRANSITION
, newValue
);
475 static int applyAbsoluteAdjustment(controlRateConfig_t
*controlRateConfig
, adjustmentFunction_e adjustmentFunction
, int value
)
479 if ( !controlRateConfig
|| !currentPidProfile
) {
483 switch (adjustmentFunction
) {
484 case ADJUSTMENT_RC_RATE
:
485 case ADJUSTMENT_ROLL_RC_RATE
:
486 newValue
= constrain(value
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
487 controlRateConfig
->rcRates
[FD_ROLL
] = newValue
;
488 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RC_RATE
, newValue
);
489 if (adjustmentFunction
== ADJUSTMENT_ROLL_RC_RATE
) {
492 // fall through for combined ADJUSTMENT_RC_EXPO
494 case ADJUSTMENT_PITCH_RC_RATE
:
495 newValue
= constrain(value
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
496 controlRateConfig
->rcRates
[FD_PITCH
] = newValue
;
497 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RC_RATE
, newValue
);
499 case ADJUSTMENT_RC_EXPO
:
500 case ADJUSTMENT_ROLL_RC_EXPO
:
501 newValue
= constrain(value
, 1, CONTROL_RATE_CONFIG_RC_EXPO_MAX
);
502 controlRateConfig
->rcExpo
[FD_ROLL
] = newValue
;
503 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RC_EXPO
, newValue
);
504 if (adjustmentFunction
== ADJUSTMENT_ROLL_RC_EXPO
) {
507 // fall through for combined ADJUSTMENT_RC_EXPO
509 case ADJUSTMENT_PITCH_RC_EXPO
:
510 newValue
= constrain(value
, 0, CONTROL_RATE_CONFIG_RC_EXPO_MAX
);
511 controlRateConfig
->rcExpo
[FD_PITCH
] = newValue
;
512 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RC_EXPO
, newValue
);
514 case ADJUSTMENT_THROTTLE_EXPO
:
515 newValue
= constrain(value
, 0, 100); // FIXME magic numbers repeated in cli.c
516 controlRateConfig
->thrExpo8
= newValue
;
518 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_THROTTLE_EXPO
, newValue
);
520 case ADJUSTMENT_PITCH_ROLL_RATE
:
521 case ADJUSTMENT_PITCH_RATE
:
522 newValue
= constrain(value
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
523 controlRateConfig
->rates
[FD_PITCH
] = newValue
;
524 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_RATE
, newValue
);
525 if (adjustmentFunction
== ADJUSTMENT_PITCH_RATE
) {
528 // fall through for combined ADJUSTMENT_PITCH_ROLL_RATE
530 case ADJUSTMENT_ROLL_RATE
:
531 newValue
= constrain(value
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
532 controlRateConfig
->rates
[FD_ROLL
] = newValue
;
533 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_RATE
, newValue
);
535 case ADJUSTMENT_YAW_RATE
:
536 newValue
= constrain(value
, 0, CONTROL_RATE_CONFIG_RATE_MAX
);
537 controlRateConfig
->rates
[FD_YAW
] = newValue
;
538 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_RATE
, newValue
);
540 case ADJUSTMENT_PITCH_ROLL_P
:
541 case ADJUSTMENT_PITCH_P
:
542 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
543 currentPidProfile
->pid
[PID_PITCH
].P
= newValue
;
544 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_P
, newValue
);
546 if (adjustmentFunction
== ADJUSTMENT_PITCH_P
) {
549 // fall through for combined ADJUSTMENT_PITCH_ROLL_P
551 case ADJUSTMENT_ROLL_P
:
552 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
553 currentPidProfile
->pid
[PID_ROLL
].P
= newValue
;
554 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_P
, newValue
);
556 case ADJUSTMENT_PITCH_ROLL_I
:
557 case ADJUSTMENT_PITCH_I
:
558 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
559 currentPidProfile
->pid
[PID_PITCH
].I
= newValue
;
560 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_I
, newValue
);
561 if (adjustmentFunction
== ADJUSTMENT_PITCH_I
) {
564 // fall through for combined ADJUSTMENT_PITCH_ROLL_I
566 case ADJUSTMENT_ROLL_I
:
567 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
568 currentPidProfile
->pid
[PID_ROLL
].I
= newValue
;
569 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_I
, newValue
);
571 case ADJUSTMENT_PITCH_ROLL_D
:
572 case ADJUSTMENT_PITCH_D
:
573 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
574 currentPidProfile
->pid
[PID_PITCH
].D
= newValue
;
575 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_D
, newValue
);
576 if (adjustmentFunction
== ADJUSTMENT_PITCH_D
) {
579 // fall through for combined ADJUSTMENT_PITCH_ROLL_D
581 case ADJUSTMENT_ROLL_D
:
582 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
583 currentPidProfile
->pid
[PID_ROLL
].D
= newValue
;
584 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_D
, newValue
);
586 case ADJUSTMENT_YAW_P
:
587 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
588 currentPidProfile
->pid
[PID_YAW
].P
= newValue
;
589 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_P
, newValue
);
591 case ADJUSTMENT_YAW_I
:
592 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
593 currentPidProfile
->pid
[PID_YAW
].I
= newValue
;
594 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_I
, newValue
);
596 case ADJUSTMENT_YAW_D
:
597 newValue
= constrain(value
, 0, 200); // FIXME magic numbers repeated in cli.c
598 currentPidProfile
->pid
[PID_YAW
].D
= newValue
;
599 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_D
, newValue
);
601 case ADJUSTMENT_RC_RATE_YAW
:
602 newValue
= constrain(value
, 1, CONTROL_RATE_CONFIG_RC_RATES_MAX
);
603 controlRateConfig
->rcRates
[FD_YAW
] = newValue
;
604 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_RC_RATE_YAW
, newValue
);
606 case ADJUSTMENT_PITCH_ROLL_F
:
607 case ADJUSTMENT_PITCH_F
:
608 newValue
= constrain(value
, 0, 2000);
609 currentPidProfile
->pid
[PID_PITCH
].F
= newValue
;
610 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_PITCH_F
, newValue
);
612 if (adjustmentFunction
== ADJUSTMENT_PITCH_F
) {
615 // fall through for combined ADJUSTMENT_PITCH_ROLL_F
617 case ADJUSTMENT_ROLL_F
:
618 newValue
= constrain(value
, 0, 2000);
619 currentPidProfile
->pid
[PID_ROLL
].F
= newValue
;
620 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_ROLL_F
, newValue
);
622 case ADJUSTMENT_YAW_F
:
623 newValue
= constrain(value
, 0, 2000);
624 currentPidProfile
->pid
[PID_YAW
].F
= newValue
;
625 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_YAW_F
, newValue
);
627 case ADJUSTMENT_FEEDFORWARD_TRANSITION
:
628 newValue
= constrain(value
, 1, 100); // FIXME magic numbers repeated in cli.c
629 currentPidProfile
->feedForwardTransition
= newValue
;
630 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_FEEDFORWARD_TRANSITION
, newValue
);
640 static uint8_t applySelectAdjustment(adjustmentFunction_e adjustmentFunction
, uint8_t position
)
644 switch (adjustmentFunction
) {
645 case ADJUSTMENT_RATE_PROFILE
:
646 if (getCurrentControlRateProfileIndex() != position
) {
647 changeControlRateProfile(position
);
648 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_RATE_PROFILE
, position
);
650 beeps
= position
+ 1;
653 case ADJUSTMENT_HORIZON_STRENGTH
:
655 uint8_t newValue
= constrain(position
, 0, 200); // FIXME magic numbers repeated in serial_cli.c
656 if (currentPidProfile
->pid
[PID_LEVEL
].D
!= newValue
) {
657 beeps
= ((newValue
- currentPidProfile
->pid
[PID_LEVEL
].D
) / 8) + 1;
658 currentPidProfile
->pid
[PID_LEVEL
].D
= newValue
;
659 blackboxLogInflightAdjustmentEvent(ADJUSTMENT_HORIZON_STRENGTH
, position
);
663 case ADJUSTMENT_PID_AUDIO
:
666 pidAudioModes_e newMode
= pidAudioPositionToModeMap
[position
];
667 if (newMode
!= pidAudioGetMode()) {
668 pidAudioSetMode(newMode
);
673 case ADJUSTMENT_OSD_PROFILE
:
674 #ifdef USE_OSD_PROFILES
675 if (getCurrentOsdProfileIndex() != (position
+ 1)) {
676 changeOsdProfileIndex(position
+1);
680 case ADJUSTMENT_LED_PROFILE
:
682 if (getLedProfile() != position
) {
683 setLedProfile(position
);
693 beeperConfirmationBeeps(beeps
);
699 static void calcActiveAdjustmentRanges(void)
701 adjustmentRange_t defaultAdjustmentRange
;
702 memset(&defaultAdjustmentRange
, 0, sizeof(defaultAdjustmentRange
));
704 activeAdjustmentCount
= 0;
705 activeAbsoluteAdjustmentCount
= 0;
706 for (int i
= 0; i
< MAX_ADJUSTMENT_RANGE_COUNT
; i
++) {
707 const adjustmentRange_t
* const adjustmentRange
= adjustmentRanges(i
);
708 if (memcmp(adjustmentRange
, &defaultAdjustmentRange
, sizeof(defaultAdjustmentRange
)) != 0) {
709 if (adjustmentRange
->adjustmentCenter
== 0) {
710 activeAdjustmentArray
[activeAdjustmentCount
++] = i
;
712 activeAbsoluteAdjustmentArray
[activeAbsoluteAdjustmentCount
++] = i
;
718 static void updateAdjustmentStates(void)
720 for (int index
= 0; index
< activeAdjustmentCount
; index
++) {
721 const adjustmentRange_t
* const adjustmentRange
= adjustmentRanges(activeAdjustmentArray
[index
]);
722 // Only use slots if center value has not been specified, otherwise apply values directly (scaled) from aux channel
723 if (isRangeActive(adjustmentRange
->auxChannelIndex
, &adjustmentRange
->range
) &&
724 (adjustmentRange
->adjustmentCenter
== 0)) {
725 const adjustmentConfig_t
*adjustmentConfig
= &defaultAdjustmentConfigs
[adjustmentRange
->adjustmentConfig
- ADJUSTMENT_FUNCTION_CONFIG_INDEX_OFFSET
];
726 configureAdjustment(adjustmentRange
->adjustmentIndex
, adjustmentRange
->auxSwitchChannelIndex
, adjustmentConfig
);
731 #define RESET_FREQUENCY_2HZ (1000 / 2)
733 void processRcAdjustments(controlRateConfig_t
*controlRateConfig
)
735 const uint32_t now
= millis();
739 const bool canUseRxData
= rxIsReceivingSignal();
741 // Recalculate the new active adjustments if required
742 if (activeAdjustmentCount
== ADJUSTMENT_RANGE_COUNT_INVALID
) {
743 calcActiveAdjustmentRanges();
746 updateAdjustmentStates();
748 // Process Increment/Decrement adjustments
749 for (int adjustmentIndex
= 0; adjustmentIndex
< MAX_SIMULTANEOUS_ADJUSTMENT_COUNT
; adjustmentIndex
++) {
750 adjustmentState_t
*adjustmentState
= &adjustmentStates
[adjustmentIndex
];
752 if (!adjustmentState
->config
) {
755 const adjustmentFunction_e adjustmentFunction
= adjustmentState
->config
->adjustmentFunction
;
756 if (adjustmentFunction
== ADJUSTMENT_NONE
) {
760 if (cmp32(now
, adjustmentState
->timeoutAt
) >= 0) {
761 adjustmentState
->timeoutAt
= now
+ RESET_FREQUENCY_2HZ
;
762 MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex
);
764 #if defined(USE_OSD) && defined(USE_OSD_ADJUSTMENTS)
765 adjustmentRangeValue
= -1;
773 const uint8_t channelIndex
= NON_AUX_CHANNEL_COUNT
+ adjustmentState
->auxChannelIndex
;
775 if (adjustmentState
->config
->mode
== ADJUSTMENT_MODE_STEP
) {
777 if (rcData
[channelIndex
] > rxConfig()->midrc
+ 200) {
778 delta
= adjustmentState
->config
->data
.step
;
779 } else if (rcData
[channelIndex
] < rxConfig()->midrc
- 200) {
780 delta
= -adjustmentState
->config
->data
.step
;
782 // returning the switch to the middle immediately resets the ready state
783 MARK_ADJUSTMENT_FUNCTION_AS_READY(adjustmentIndex
);
784 adjustmentState
->timeoutAt
= now
+ RESET_FREQUENCY_2HZ
;
787 if (IS_ADJUSTMENT_FUNCTION_BUSY(adjustmentIndex
)) {
791 newValue
= applyStepAdjustment(controlRateConfig
, adjustmentFunction
, delta
);
792 pidInitConfig(currentPidProfile
);
793 } else if (adjustmentState
->config
->mode
== ADJUSTMENT_MODE_SELECT
) {
794 int switchPositions
= adjustmentState
->config
->data
.switchPositions
;
795 if (adjustmentFunction
== ADJUSTMENT_RATE_PROFILE
&& systemConfig()->rateProfile6PosSwitch
) {
798 const uint16_t rangeWidth
= (2100 - 900) / switchPositions
;
799 const uint8_t position
= (constrain(rcData
[channelIndex
], 900, 2100 - 1) - 900) / rangeWidth
;
800 newValue
= applySelectAdjustment(adjustmentFunction
, position
);
803 #if defined(USE_OSD) && defined(USE_OSD_ADJUSTMENTS)
805 && adjustmentState
->config
->adjustmentFunction
!= ADJUSTMENT_RATE_PROFILE
// Rate profile already has an OSD element
806 #ifdef USE_OSD_PROFILES
807 && adjustmentState
->config
->adjustmentFunction
!= ADJUSTMENT_OSD_PROFILE
810 && adjustmentState
->config
->adjustmentFunction
!= ADJUSTMENT_LED_PROFILE
813 adjustmentRangeNameIndex
= adjustmentFunction
;
814 adjustmentRangeValue
= newValue
;
819 MARK_ADJUSTMENT_FUNCTION_AS_BUSY(adjustmentIndex
);
822 // Process Absolute adjustments
823 for (int i
= 0; i
< activeAbsoluteAdjustmentCount
; i
++) {
824 static int16_t lastRcData
[MAX_ADJUSTMENT_RANGE_COUNT
] = { 0 };
825 int index
= activeAbsoluteAdjustmentArray
[i
];
826 const adjustmentRange_t
* const adjustmentRange
= adjustmentRanges(index
);
827 const uint8_t channelIndex
= NON_AUX_CHANNEL_COUNT
+ adjustmentRange
->auxSwitchChannelIndex
;
828 const adjustmentConfig_t
*adjustmentConfig
= &defaultAdjustmentConfigs
[adjustmentRange
->adjustmentConfig
- ADJUSTMENT_FUNCTION_CONFIG_INDEX_OFFSET
];
830 // If setting is defined for step adjustment and center value has been specified, apply values directly (scaled) from aux channel
831 if ((rcData
[channelIndex
] != lastRcData
[index
]) &&
832 adjustmentRange
->adjustmentCenter
&&
833 (adjustmentConfig
->mode
== ADJUSTMENT_MODE_STEP
) &&
834 isRangeActive(adjustmentRange
->auxChannelIndex
, &adjustmentRange
->range
)) {
835 int value
= (((rcData
[channelIndex
] - PWM_RANGE_MIDDLE
) * adjustmentRange
->adjustmentScale
) / (PWM_RANGE_MIDDLE
- PWM_RANGE_MIN
)) + adjustmentRange
->adjustmentCenter
;
837 lastRcData
[index
] = rcData
[channelIndex
];
838 applyAbsoluteAdjustment(controlRateConfig
, adjustmentConfig
->adjustmentFunction
, value
);
839 pidInitConfig(currentPidProfile
);
844 void resetAdjustmentStates(void)
846 memset(adjustmentStates
, 0, sizeof(adjustmentStates
));
849 #if defined(USE_OSD) && defined(USE_OSD_ADJUSTMENTS)
850 const char *getAdjustmentsRangeName(void)
852 if (adjustmentRangeNameIndex
> 0) {
853 return &adjustmentLabels
[adjustmentRangeNameIndex
- 1][0];
859 int getAdjustmentsRangeValue(void)
861 return adjustmentRangeValue
;
865 void activeAdjustmentRangeReset(void)
867 activeAdjustmentCount
= ADJUSTMENT_RANGE_COUNT_INVALID
;