LCOV - code coverage report
Current view: top level - RC_Channel - RC_Channel.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 52 57 91.2 %
Date: 2026-09-09 11:02:08 Functions: 31 35 88.6 %

          Line data    Source code
       1             : /// @file       RC_Channel.h
       2             : /// @brief      RC_Channel manager, with EEPROM-backed storage of constants.
       3             : #pragma once
       4             : 
       5             : #include "RC_Channel_config.h"
       6             : 
       7             : #if AP_RC_CHANNEL_ENABLED
       8             : 
       9             : #include <AP_Common/AP_Common.h>
      10             : #include <AP_Param/AP_Param.h>
      11             : #include <AP_Math/AP_Math.h>
      12             : #include <AP_Common/Bitmask.h>
      13             : 
      14             : #include <AC_Sprayer/AC_Sprayer_config.h>
      15             : #include <AP_Airspeed/AP_Airspeed_config.h>
      16             : #include <AP_Camera/AP_Camera_config.h>
      17             : #include <AP_Compass/AP_Compass_config.h>
      18             : #include <AP_Gripper/AP_Gripper_config.h>
      19             : #include <AP_OpticalFlow/AP_OpticalFlow_config.h>
      20             : #include <AP_Parachute/AP_Parachute_config.h>
      21             : #include <AP_RangeFinder/AP_RangeFinder_config.h>
      22             : #include <AP_ServoRelayEvents/AP_ServoRelayEvents_config.h>
      23             : #include <AP_Torqeedo/AP_Torqeedo_config.h>
      24             : #include <AP_VisualOdom/AP_VisualOdom_config.h>
      25             : #include <AP_Winch/AP_Winch_config.h>
      26             : #include <AP_VideoTX/AP_VideoTX_config.h>
      27             : #include <AP_Arming/AP_Arming_config.h>
      28             : #include <AP_BattMonitor/AP_BattMonitor_config.h>
      29             : 
      30             : #define NUM_RC_CHANNELS 16
      31             : 
      32             : /// @class      RC_Channel
      33             : /// @brief      Object managing one RC channel
      34             : class RC_Channel {
      35             : public:
      36             :     friend class RC_Channels;
      37             :     // Constructor
      38             :     RC_Channel(void);
      39             : 
      40             :     enum class ControlType {
      41             :         ANGLE = 0,
      42             :         RANGE = 1,
      43             :     };
      44             : 
      45             :     // ch returns the radio channel be read, starting at 1.  so
      46             :     // typically Roll=1, Pitch=2, throttle=3, yaw=4.  If this returns
      47             :     // 0 then this is the dummy object which means that one of roll,
      48             :     // pitch, yaw or throttle has not been configured correctly.
      49           0 :     uint8_t ch() const { return ch_in + 1; }
      50             : 
      51             :     // setup the control preferences
      52             :     void        set_range(uint16_t high);
      53     3261753 :     uint16_t    get_range() const { return high_in; }
      54             :     void        set_angle(uint16_t angle);
      55             :     bool        get_reverse(void) const;
      56             :     void        set_default_dead_zone(int16_t dzone);
      57      996110 :     uint16_t    get_dead_zone(void) const { return dead_zone; }
      58             : 
      59             :     // get the center stick position expressed as a control_in value
      60             :     int16_t     get_control_mid() const;
      61             : 
      62             :     // read input from hal.rcin - create a control_in value
      63             :     bool        update(void);
      64             : 
      65             :     // calculate an angle given dead_zone and trim. This is used by the quadplane code
      66             :     // for hover throttle
      67             :     float       pwm_to_angle_dz_trim(uint16_t dead_zone, uint16_t trim) const;
      68             : 
      69             :     // return a normalised input for a channel, in range -1 to 1,
      70             :     // centered around the channel trim. Ignore deadzone.
      71             :     float       norm_input() const;
      72             : 
      73             :     // return a normalised input for a channel, in range -1 to 1,
      74             :     // centered around the channel trim. Take into account the deadzone
      75             :     float       norm_input_dz() const;
      76             : 
      77             :     // return a normalised input for a channel, in range -1 to 1,
      78             :     // ignores trim and deadzone
      79             :     float       norm_input_ignore_trim() const;
      80             : 
      81             :     // return a normalised input for a channel, in range -1 to 1 (in
      82             :     // return parameter).  Ignores trim and deadzone.  Returns false
      83             :     // if a current value is not available (eg. in RC failsafe)
      84             :     bool       norm_input_ignore_trim(float &norm_in) const;
      85             : 
      86             :     // returns true if input is within deadzone of min
      87             :     bool        in_min_dz() const;
      88             : 
      89             :     uint8_t     percent_input() const;
      90             : 
      91             :     static const struct AP_Param::GroupInfo var_info[];
      92             : 
      93             :     // return true if input is within deadzone of trim
      94             :     bool       in_trim_dz() const;
      95             : 
      96   130940430 :     int16_t    get_radio_in() const { return radio_in;}
      97        9345 :     void       set_radio_in(int16_t val) {radio_in = val;}
      98             : 
      99    74996109 :     int16_t    get_control_in() const { return control_in;}
     100       11588 :     void       set_control_in(int16_t val) { control_in = val;}
     101             : 
     102             :     void       clear_override();
     103             :     void       set_override(const uint16_t v, const uint32_t timestamp_ms);
     104             :     bool       has_override() const;
     105             : 
     106             :     float    stick_mixing(const float servo_in);
     107             : 
     108             :     // get control input with zero deadzone
     109             :     float      get_control_in_zero_dz(void) const;
     110             : 
     111     3451050 :     int16_t    get_radio_min() const {return radio_min.get();}
     112             : 
     113     3361172 :     int16_t    get_radio_max() const {return radio_max.get();}
     114             : 
     115     2450820 :     int16_t    get_radio_trim() const { return radio_trim.get();}
     116             : 
     117           0 :     void       set_and_save_trim() { radio_trim.set_and_save_ifchanged(radio_in);}
     118             : 
     119             :     // set and save trim if changed
     120             :     void       set_and_save_radio_trim(int16_t val) { radio_trim.set_and_save_ifchanged(val);}
     121             : 
     122             :     // check if any of the trim/min/max param are configured, this would indicate that the user has done a calibration at somepoint
     123         918 :     bool       configured() { return radio_min.configured() || radio_max.configured() || radio_trim.configured(); }
     124             : 
     125     1138943 :     ControlType get_type(void) const { return type_in; }
     126             : 
     127             :     AP_Int16    option; // e.g. activate EPM gripper / enable fence
     128             : 
     129             :     // auxiliary switch support
     130             :     void init_aux();
     131             :     bool read_aux();
     132             : 
     133             :     // Aux Switch enumeration
     134             :     enum class AUX_FUNC {
     135             :         DO_NOTHING =           0, // aux switch disabled
     136             :         FLIP =                 2, // flip
     137             :         SIMPLE_MODE =          3, // change to simple mode
     138             :         RTL =                  4, // change to RTL flight mode
     139             :         SAVE_TRIM =            5, // save current position as level
     140             : #if AP_MISSION_ENABLED
     141             :         SAVE_WP =              7, // save mission waypoint or RTL if in auto mode
     142             : #endif  // AP_MISSION_ENABLED
     143             : #if AP_CAMERA_ENABLED
     144             :         CAMERA_TRIGGER =       9, // trigger camera servo or relay
     145             : #endif  // AP_CAMERA_ENABLED
     146             : #if AP_RANGEFINDER_ENABLED
     147             :         RANGEFINDER =         10, // allow enabling or disabling rangefinder in flight which helps avoid surface tracking when you are far above the ground
     148             : #endif  // AP_RANGEFINDER_ENABLED
     149             : #if AP_FENCE_ENABLED
     150             :         FENCE =               11, // allow enabling or disabling fence in flight
     151             : #endif  // AP_FENCE_ENABLED
     152             :         RESETTOARMEDYAW =     12, // UNUSED
     153             :         SUPERSIMPLE_MODE =    13, // change to simple mode in middle, super simple at top
     154             :         ACRO_TRAINER =        14, // low = disabled, middle = leveled, high = leveled and limited
     155             : #if HAL_SPRAYER_ENABLED
     156             :         SPRAYER =             15, // enable/disable the crop sprayer
     157             : #endif  // HAL_SPRAYER_ENABLED
     158             :         AUTO =                16, // change to auto flight mode
     159             :         AUTOTUNE_MODE =       17, // auto tune
     160             :         LAND =                18, // change to LAND flight mode
     161             : #if AP_GRIPPER_ENABLED
     162             :         GRIPPER =             19, // Operate cargo grippers low=off, middle=neutral, high=on
     163             : #endif  // AP_GRIPPER_ENABLED
     164             : #if HAL_PARACHUTE_ENABLED
     165             :         PARACHUTE_ENABLE  =   21, // Parachute enable/disable
     166             :         PARACHUTE_RELEASE =   22, // Parachute release
     167             :         PARACHUTE_3POS =      23, // Parachute disable, enable, release with 3 position switch
     168             : #endif  // HAL_PARACHUTE_ENABLED
     169             : #if AP_MISSION_ENABLED
     170             :         MISSION_RESET =       24, // Reset auto mission to start from first command
     171             : #endif  // AP_MISSION_ENABLED
     172             :         ATTCON_FEEDFWD =      25, // enable/disable the roll and pitch rate feed forward
     173             :         ATTCON_ACCEL_LIM =    26, // enable/disable the roll, pitch and yaw accel limiting
     174             : #if HAL_MOUNT_ENABLED
     175             :         RETRACT_MOUNT1 =      27, // Retract Mount1
     176             : #endif  // HAL_MOUNT_ENABLED
     177             : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     178             : 
     179             :         RELAY =               28, // Relay pin on/off (only supports first relay)
     180             : #endif  // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     181             :         LANDING_GEAR =        29, // Landing gear controller
     182             :         LOST_VEHICLE_SOUND =  30, // Play lost vehicle sound
     183             :         MOTOR_ESTOP =         31, // Emergency Stop Switch
     184             :         MOTOR_INTERLOCK =     32, // Motor On/Off switch
     185             :         BRAKE =               33, // Brake flight mode
     186             : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     187             :         RELAY2 =              34, // Relay2 pin on/off
     188             :         RELAY3 =              35, // Relay3 pin on/off
     189             :         RELAY4 =              36, // Relay4 pin on/off
     190             : #endif  // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     191             :         THROW =               37, // change to THROW flight mode
     192             :         AVOID_ADSB =          38, // enable AP_Avoidance library
     193             :         PRECISION_LOITER =    39, // enable precision loiter
     194             :         AVOID_PROXIMITY =     40, // enable object avoidance using proximity sensors (ie. horizontal lidar)
     195             :         ARMDISARM_UNUSED =    41, // UNUSED
     196             :         SMART_RTL =           42, // change to SmartRTL flight mode
     197             :         INVERTED  =           43, // enable inverted flight
     198             : #if AP_WINCH_ENABLED
     199             :         WINCH_ENABLE =        44, // winch enable/disable
     200             :         WINCH_CONTROL =       45, // winch control
     201             : #endif  // AP_WINCH_ENABLED
     202             :         RC_OVERRIDE_ENABLE =  46, // enable RC Override
     203             :         USER_FUNC1 =          47, // user function #1
     204             :         USER_FUNC2 =          48, // user function #2
     205             :         USER_FUNC3 =          49, // user function #3
     206             :         LEARN_CRUISE =        50, // learn cruise throttle (Rover)
     207             :         MANUAL       =        51, // manual mode
     208             :         ACRO         =        52, // acro mode
     209             :         STEERING     =        53, // steering mode
     210             :         HOLD         =        54, // hold mode
     211             :         GUIDED       =        55, // guided mode
     212             :         LOITER       =        56, // loiter mode
     213             :         FOLLOW       =        57, // follow mode
     214             : #if AP_MISSION_ENABLED
     215             :         CLEAR_WP     =        58, // clear waypoints
     216             : #endif  // AP_MISSION_ENABLED
     217             :         SIMPLE       =        59, // simple mode
     218             :         ZIGZAG       =        60, // zigzag mode
     219             :         ZIGZAG_SaveWP =       61, // zigzag save waypoint
     220             :         COMPASS_LEARN =       62, // learn compass offsets
     221             :         SAILBOAT_TACK =       63, // rover sailboat tack
     222             :         REVERSE_THROTTLE =    64, // reverse throttle input
     223             : #if AP_GPS_ENABLED
     224             :         GPS_DISABLE  =        65, // disable GPS for testing
     225             : #endif  // AP_GPS_ENABLED
     226             : #if AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     227             :         RELAY5 =              66, // Relay5 pin on/off
     228             :         RELAY6 =              67, // Relay6 pin on/off
     229             : #endif  // AP_SERVORELAYEVENTS_ENABLED && AP_RELAY_ENABLED
     230             :         STABILIZE =           68, // stabilize mode
     231             :         POSHOLD   =           69, // poshold mode
     232             :         ALTHOLD   =           70, // althold mode
     233             :         FLOWHOLD  =           71, // flowhold mode
     234             :         CIRCLE    =           72, // circle mode
     235             :         DRIFT     =           73, // drift mode
     236             :         SAILBOAT_MOTOR_3POS = 74, // Sailboat motoring 3pos
     237             :         SURFACE_TRACKING =    75, // Surface tracking upwards or downwards
     238             :         STANDBY  =            76, // Standby mode
     239             :         TAKEOFF   =           77, // takeoff
     240             : #if AP_CAMERA_RUNCAM_ENABLED
     241             :         RUNCAM_CONTROL =      78, // control RunCam device
     242             :         RUNCAM_OSD_CONTROL =  79, // control RunCam OSD
     243             : #endif  // AP_CAMERA_RUNCAM_ENABLED
     244             : #if HAL_VISUALODOM_ENABLED
     245             :         VISODOM_ALIGN =       80, // align visual odometry camera's attitude to AHRS
     246             : #endif  // HAL_VISUALODOM_ENABLED
     247             :         DISARM =              81, // disarm vehicle
     248             :         Q_ASSIST =            82, // disable, enable and force Q assist
     249             :         ZIGZAG_Auto =         83, // zigzag auto switch
     250             :         AIRMODE =             84, // enable / disable airmode for copter
     251             : #if HAL_GENERATOR_ENABLED
     252             :         GENERATOR   =         85, // generator control
     253             : #endif  // HAL_GENERATOR_ENABLED
     254             :         TER_DISABLE =         86, // disable terrain following in CRUISE/FBWB modes
     255             :         CROW_SELECT =         87, // select CROW mode for diff spoilers;high disables,mid forces progressive
     256             :         SOARING =             88, // three-position switch to set soaring mode
     257             :         LANDING_FLARE =       89, // force flare, throttle forced idle, pitch to LAND_PITCH_DEG, tilts up
     258             :         EKF_SOURCE_SET =      90, // change EKF data source set between primary, secondary and tertiary
     259             : #if AP_AIRSPEED_AUTOCAL_ENABLE
     260             :         ARSPD_CALIBRATE=      91, // calibrate airspeed ratio 
     261             : #endif  // AP_AIRSPEED_AUTOCAL_ENABLE
     262             :         FBWA =                92, // Fly-By-Wire-A
     263             : #if AP_MISSION_ENABLED
     264             :         RELOCATE_MISSION =    93, // used in separate branch MISSION_RELATIVE
     265             : #endif  // AP_MISSION_ENABLED
     266             : #if AP_VIDEOTX_ENABLED
     267             :         VTX_POWER =           94, // VTX power level
     268             : #endif  // AP_VIDEOTX_ENABLED
     269             :         FBWA_TAILDRAGGER =    95, // enables FBWA taildragger takeoff mode. Once this feature is enabled it will stay enabled until the aircraft goes above TKOFF_TDRAG_SPD1 airspeed, changes mode, or the pitch goes above the initial pitch when this is engaged or goes below 0 pitch. When enabled the elevator will be forced to TKOFF_TDRAG_ELEV. This option allows for easier takeoffs on taildraggers in FBWA mode, and also makes it easier to test auto-takeoff steering handling in FBWA.
     270             :         MODE_SWITCH_RESET =   96, // trigger re-reading of mode switch
     271             :         WIND_VANE_DIR_OFSSET= 97, // flag for windvane direction offset input, used with windvane type 2
     272             :         TRAINING            = 98, // mode training
     273             : #if AP_MISSION_ENABLED
     274             :         AUTO_RTL =            99, // AUTO RTL via DO_LAND_START
     275             : #endif  // AP_MISSION_ENABLED
     276             : 
     277             : #if AP_INERTIALSENSOR_KILL_IMU_ENABLED
     278             :         // entries from 100-150  are expected to be developer
     279             :         // options used for testing
     280             :         KILL_IMU1 =          100, // disable first IMU (for IMU failure testing)
     281             :         KILL_IMU2 =          101, // disable second IMU (for IMU failure testing)
     282             : #endif  // AP_INERTIALSENSOR_KILL_IMU_ENABLED
     283             : #if AP_CAMERA_ENABLED
     284             :         CAM_MODE_TOGGLE =    102, // Momentary switch to cycle camera modes
     285             : #endif  // AP_CAMERA_ENABLED
     286             : #if AP_AHRS_ENABLED
     287             :         EKF_LANE_SWITCH =    103, // trigger lane switch attempt
     288             :         EKF_YAW_RESET =      104, // trigger yaw reset attempt
     289             : #endif  // AP_AHRS_ENABLED
     290             : #if AP_GPS_ENABLED
     291             :         GPS_DISABLE_YAW =    105, // disable GPS yaw for testing
     292             : #endif  // AP_GPS_ENABLED
     293             : #if AP_AIRSPEED_ENABLED
     294             :         DISABLE_AIRSPEED_USE = 106, // equivalent to AIRSPEED_USE 0
     295             : #endif  // AP_AIRSPEED_ENABLED
     296             :         FW_AUTOTUNE =          107, // fixed wing auto tune
     297             :         QRTL =               108, // QRTL mode
     298             :         CUSTOM_CONTROLLER =  109,  // use Custom Controller
     299             : #if AP_INERTIALSENSOR_KILL_IMU_ENABLED
     300             :         KILL_IMU3 =          110, // disable third IMU (for IMU failure testing)
     301             : #endif  // AP_INERTIALSENSOR_KILL_IMU_ENABLED
     302             : #if HAL_GENERATOR_ENABLED
     303             :         LOWEHEISER_STARTER = 111,  // allows for manually running starter
     304             : #endif  // HAL_GENERATOR_ENABLED
     305             : #if AP_AHRS_ENABLED
     306             :         AHRS_TYPE =          112, // change AHRS_EKF_TYPE
     307             : #endif  // AP_AHRS_ENABLED
     308             : #if HAL_MOUNT_ENABLED
     309             :         RETRACT_MOUNT2 =     113, // Retract Mount2
     310             : #endif  // HAL_MOUNT_ENABLED
     311             : 
     312             :         // if you add something here, make sure to update the documentation of the parameter in RC_Channel.cpp!
     313             :         // also, if you add an option >255, you will need to fix duplicate_options_exist
     314             : 
     315             :         // options 150-199 continue user rc switch options
     316             :         CRUISE =             150,  // CRUISE mode
     317             :         TURTLE =             151,  // Turtle mode - flip over after crash
     318             :         SIMPLE_HEADING_RESET = 152, // reset simple mode reference heading to current
     319             : #if AP_ARMING_ENABLED
     320             :         ARMDISARM =          153, // arm or disarm vehicle
     321             :         ARMDISARM_AIRMODE =  154, // arm or disarm vehicle enabling airmode
     322             : #endif  // AP_ARMING_ENABLED
     323             :         TRIM_TO_CURRENT_SERVO_RC = 155, // trim to current servo and RC
     324             : #if HAL_TORQEEDO_ENABLED
     325             :         TORQEEDO_CLEAR_ERR = 156, // clear torqeedo error
     326             : #endif  // HAL_TORQEEDO_ENABLED
     327             :         EMERGENCY_LANDING_EN = 157, //Force long FS action to FBWA for landing out of range
     328             : #if AP_OPTICALFLOW_ENABLED
     329             :         OPTFLOW_CAL =        158, // optical flow calibration
     330             : #endif  // AP_OPTICALFLOW_ENABLED
     331             :         FORCEFLYING =        159, // enable or disable land detection for GPS based manual modes preventing land detection and maintainting set_throttle_mix_max
     332             :         WEATHER_VANE_ENABLE = 160, // enable/disable weathervaning
     333             :         TURBINE_START =      161, // initialize turbine start sequence
     334             :         FFT_NOTCH_TUNE =     162, // FFT notch tuning function
     335             : #if HAL_MOUNT_ENABLED
     336             :         MOUNT_YAW_LOCK =     163, // Mount earth frame yaw lock forced on all axes, for all mounts
     337             : #endif  // HAL_MOUNT_ENABLED
     338             : #if HAL_LOGGING_ENABLED
     339             :         LOG_PAUSE =          164, // Pauses logging if under logging rate control
     340             : #endif  // HAL_LOGGING_ENABLED
     341             :         ARM_EMERGENCY_STOP = 165, // ARM on high, MOTOR_ESTOP on low
     342             : #if AP_CAMERA_ENABLED
     343             :         CAMERA_REC_VIDEO =   166, // start recording on high, stop recording on low
     344             :         CAMERA_ZOOM =        167, // camera zoom high = zoom in, middle = hold, low = zoom out
     345             :         CAMERA_MANUAL_FOCUS = 168,// camera manual focus.  high = long shot, middle = stop focus, low = close shot
     346             :         CAMERA_AUTO_FOCUS =  169, // camera auto focus
     347             : #endif  // AP_CAMERA_ENABLED
     348             :         QSTABILIZE =         170, // QuadPlane QStabilize mode
     349             : #if COMPASS_CAL_ENABLED
     350             :         MAG_CAL =            171, // Calibrate compasses (disarmed only)
     351             : #endif  // COMPASS_CAL_ENABLED
     352             : #if AP_BATTERY_ENABLED
     353             :         BATTERY_MPPT_ENABLE = 172,// Battery MPPT Power enable. high = ON, mid = auto (controlled by mppt/batt driver), low = OFF. This effects all MPPTs.
     354             : #endif  // AP_BATTERY_ENABLED
     355             :         PLANE_AUTO_LANDING_ABORT = 173, // Abort Glide-slope or VTOL landing during payload place or do_land type mission items
     356             : #if AP_CAMERA_ENABLED
     357             :         CAMERA_IMAGE_TRACKING = 174, // camera image tracking
     358             :         CAMERA_LENS =        175, // camera lens selection
     359             : #endif  // AP_CAMERA_ENABLED
     360             :         VFWD_THR_OVERRIDE =  176, // force enabled VTOL forward throttle method
     361             : #if HAL_MOUNT_ENABLED
     362             :         MOUNT_LRF_ENABLE =   177,  // mount LRF enable/disable
     363             : #endif  // HAL_MOUNT_ENABLED
     364             :         FLIGHTMODE_PAUSE =   178,  // e.g. pause movement towards waypoint
     365             :         ICE_START_STOP =     179, // AP_ICEngine start stop
     366             :         AUTOTUNE_TEST_GAINS = 180, // auto tune tuning switch to test or revert gains
     367             :         QUICKTUNE =          181,  //quicktune 3 position switch
     368             :         AHRS_AUTO_TRIM =     182,  // in-flight AHRS autotrim
     369             :         AUTOLAND =           183,  //Fixed Wing AUTOLAND Mode
     370             :         SYSTEMID =           184,  // system ID as an aux switch
     371             :         MOUNT_RP_LOCK =      185,  // mount lock modes for roll and pitch axes, for all mounts that support it
     372             : #if AP_MOUNT_POI_LOCK_ENABLED
     373             :         MOUNT_POI_LOCK =     186,  // Lock mount target to current ROI seen and switch mount to GPS Targeting mode
     374             : #endif  // AP_MOUNT_POI_LOCK_ENABLED
     375             : #if AP_AHRS_EKF_RESET_ENABLED
     376             :         EKF_RESET =          187, // trigger full EKF bootstrap reset
     377             : #endif  // AP_AHRS_EKF_RESET_ENABLED
     378             :         // inputs from 200 will eventually used to replace RCMAP
     379             :         ROLL =               201, // roll input
     380             :         PITCH =              202, // pitch input
     381             :         THROTTLE =           203, // throttle pilot input
     382             :         YAW =                204, // yaw pilot input
     383             :         MAINSAIL =           207, // mainsail input
     384             :         FLAP =               208, // flap input
     385             :         FWD_THR =            209, // VTOL manual forward throttle
     386             :         AIRBRAKE =           210, // manual airbrake control
     387             :         WALKING_HEIGHT =     211, // walking robot height input
     388             : #if HAL_MOUNT_ENABLED
     389             :         MOUNT1_ROLL =        212, // mount1 roll input
     390             :         MOUNT1_PITCH =       213, // mount1 pitch input
     391             :         MOUNT1_YAW =         214, // mount1 yaw input
     392             :         MOUNT2_ROLL =        215, // mount2 roll input
     393             :         MOUNT2_PITCH =       216, // mount3 pitch input
     394             :         MOUNT2_YAW =         217, // mount4 yaw input
     395             : #endif  // HAL_MOUNT_ENABLED
     396             : #if HAL_GENERATOR_ENABLED
     397             :         LOWEHEISER_THROTTLE= 218, // allows for throttle on slider
     398             : #endif  // HAL_GENERATOR_ENABLED
     399             : #if AP_RC_TRANSMITTER_TUNING_ENABLED
     400             :         TRANSMITTER_TUNING = 219, // use a transmitter knob or slider for in-flight tuning
     401             :         TRANSMITTER_TUNING2 = 220, // use another transmitter knob or slider for in-flight tuning
     402             : #endif  // AP_RC_TRANSMITTER_TUNING_ENABLED
     403             : 
     404             :         // inputs 248-249 are reserved for the Skybrush fork at
     405             :         // https://github.com/skybrush-io/ardupilot
     406             : 
     407             :         // inputs 250-254 are reserved for the custom integrations.
     408             :         // No code which uses these auxiliary channel options will be
     409             :         // merged into ArduPilot master, so external code can use this
     410             :         // an not conflict when rebased on newer ArduPilot codebases.
     411             :         // No guarantees are made in terms of conflicting with other
     412             :         // external projects.  See the SCRIPTING_1 range instead if
     413             :         // you are writing a Lua script.
     414             : 
     415             : #if AP_SCRIPTING_ENABLED
     416             :         // inputs for the use of onboard lua scripting
     417             :         SCRIPTING_1 =        300,
     418             :         SCRIPTING_2 =        301,
     419             :         SCRIPTING_3 =        302,
     420             :         SCRIPTING_4 =        303,
     421             :         SCRIPTING_5 =        304,
     422             :         SCRIPTING_6 =        305,
     423             :         SCRIPTING_7 =        306,
     424             :         SCRIPTING_8 =        307,
     425             :         SCRIPTING_9 =        308,
     426             :         SCRIPTING_10 =       309,
     427             :         SCRIPTING_11 =       310,
     428             :         SCRIPTING_12 =       311,
     429             :         SCRIPTING_13 =       312,
     430             :         SCRIPTING_14 =       313,
     431             :         SCRIPTING_15 =       314,
     432             :         SCRIPTING_16 =       315,
     433             :         STOP_RESTART_SCRIPTING =     316,   // emergency scripting disablement
     434             : #endif  // AP_SCRIPTING_ENABLED
     435             : 
     436             :         // this must be higher than any aux function above
     437             :         AUX_FUNCTION_MAX =   317,
     438             :     };
     439             : 
     440             :     // auxiliary switch handling (n.b.: we store this as 2-bits!):
     441             :     enum class AuxSwitchPos : uint8_t {
     442             :         LOW,       // indicates auxiliary switch is in the low position (pwm <1200)
     443             :         MIDDLE,    // indicates auxiliary switch is in the middle position (pwm >1200, <1800)
     444             :         HIGH       // indicates auxiliary switch is in the high position (pwm >1800)
     445             :     };
     446             : 
     447             :     // Trigger structure containing the function, position, source and source index
     448             :     struct AuxFuncTrigger {
     449             :         AUX_FUNC func;
     450             :         AuxSwitchPos pos;
     451             :         // @LoggerEnum: AuxFuncTrigger::Source
     452             :         enum class Source : uint8_t {
     453             :             INIT,      // Source index is RC channel index
     454             :             RC,        // Source index is RC channel index
     455             :             BUTTON,    // Source index is button index
     456             :             MAVLINK,   // Source index is MAVLink channel number
     457             :             MISSION,   // Source index is mission item index
     458             :             SCRIPTING, // Source index is not used (always 0)
     459             :         } source;
     460             :         uint16_t source_index;
     461             :     };
     462             : 
     463             :     AuxSwitchPos get_aux_switch_pos() const;
     464             : 
     465             :     // aux position for stick gestures used by RunCam menus etc
     466             :     AuxSwitchPos get_stick_gesture_pos() const;
     467             : 
     468             :     // wrapper function around do_aux_function which allows us to log
     469             :     bool run_aux_function(AUX_FUNC ch_option, AuxSwitchPos pos, AuxFuncTrigger::Source source, uint16_t source_index);
     470             : 
     471             : #if AP_RC_CHANNEL_AUX_FUNCTION_STRINGS_ENABLED
     472             :     const char *string_for_aux_function(AUX_FUNC function) const;
     473             :     const char *string_for_aux_pos(AuxSwitchPos pos) const;
     474             : #endif
     475             :     // pwm value under which we consider that Radio value is invalid
     476             :     static const uint16_t RC_MIN_LIMIT_PWM = 800;
     477             :     // pwm value above which we consider that Radio value is invalid
     478             :     static const uint16_t RC_MAX_LIMIT_PWM = 2200;
     479             : 
     480             :     // pwm value above which we condider that Radio min value is invalid
     481             :     static const uint16_t RC_CALIB_MIN_LIMIT_PWM = 1300;
     482             :     // pwm value under which we condider that Radio max value is invalid
     483             :     static const uint16_t RC_CALIB_MAX_LIMIT_PWM = 1700;
     484             : 
     485             :     // pwm value above which the switch/button will be invoked:
     486             :     static const uint16_t AUX_SWITCH_PWM_TRIGGER_HIGH = 1800;
     487             :     // pwm value below which the switch/button will be disabled:
     488             :     static const uint16_t AUX_SWITCH_PWM_TRIGGER_LOW = 1200;
     489             : 
     490             :     // pwm value above which the option will be invoked:
     491             :     static const uint16_t AUX_PWM_TRIGGER_HIGH = 1700;
     492             :     // pwm value below which the option will be disabled:
     493             :     static const uint16_t AUX_PWM_TRIGGER_LOW = 1300;
     494             : 
     495             : protected:
     496             : 
     497             :     __INITFUNC__ virtual void init_aux_function(AUX_FUNC ch_option, AuxSwitchPos);
     498             : 
     499             :     // virtual function to be overridden my subclasses
     500             :     virtual bool do_aux_function(const AuxFuncTrigger &trigger);
     501             : 
     502             :     void do_aux_function_armdisarm(const AuxSwitchPos ch_flag);
     503             :     void do_aux_function_avoid_adsb(const AuxSwitchPos ch_flag);
     504             :     void do_aux_function_avoid_proximity(const AuxSwitchPos ch_flag);
     505             :     void do_aux_function_camera_trigger(const AuxSwitchPos ch_flag);
     506             :     bool do_aux_function_record_video(const AuxSwitchPos ch_flag);
     507             :     bool do_aux_function_camera_zoom(const AuxSwitchPos ch_flag);
     508             :     bool do_aux_function_camera_manual_focus(const AuxSwitchPos ch_flag);
     509             :     bool do_aux_function_camera_auto_focus(const AuxSwitchPos ch_flag);
     510             :     bool do_aux_function_camera_image_tracking(const AuxSwitchPos ch_flag);
     511             :     bool do_aux_function_camera_lens(const AuxSwitchPos ch_flag);
     512             :     void do_aux_function_runcam_control(const AuxSwitchPos ch_flag);
     513             :     void do_aux_function_runcam_osd_control(const AuxSwitchPos ch_flag);
     514             :     void do_aux_function_fence(const AuxSwitchPos ch_flag);
     515             :     void do_aux_function_clear_wp(const AuxSwitchPos ch_flag);
     516             :     void do_aux_function_gripper(const AuxSwitchPos ch_flag);
     517             :     void do_aux_function_lost_vehicle_sound(const AuxSwitchPos ch_flag);
     518             :     void do_aux_function_mission_reset(const AuxSwitchPos ch_flag);
     519             :     void do_aux_function_rc_override_enable(const AuxSwitchPos ch_flag);
     520             :     void do_aux_function_relay(uint8_t relay, bool val);
     521             :     void do_aux_function_sprayer(const AuxSwitchPos ch_flag);
     522             :     void do_aux_function_generator(const AuxSwitchPos ch_flag);
     523             :     void do_aux_function_fft_notch_tune(const AuxSwitchPos ch_flag);
     524             :     void do_aux_function_retract_mount(const AuxSwitchPos ch_flag, const uint8_t instance);
     525             : 
     526             :     typedef int8_t modeswitch_pos_t;
     527           0 :     virtual void mode_switch_changed(modeswitch_pos_t new_pos) {
     528             :         // no action by default (e.g. Tracker, Sub, who do their own thing)
     529           0 :     };
     530             : 
     531             :     // the input channel this corresponds to
     532             :     uint8_t ch_in;
     533             : 
     534             : private:
     535             : 
     536             :     // pwm is stored here; if an override is active, override_value is stored instead
     537             :     int16_t     radio_in;
     538             :     // stores the raw pwm value read from hal.rcin
     539             :     int16_t     raw_radio_in;
     540             : 
     541             :     // value generated from PWM normalised to configured scale
     542             :     int16_t    control_in;
     543             : 
     544             :     AP_Int16    radio_min;
     545             :     AP_Int16    radio_trim;
     546             :     AP_Int16    radio_max;
     547             : 
     548             :     AP_Int8     reversed;
     549             :     AP_Int16    dead_zone;
     550             : 
     551             :     ControlType type_in;
     552             :     int16_t     high_in;
     553             : 
     554             :     // overrides
     555             :     uint16_t override_value;
     556             :     uint32_t last_override_time;
     557             : 
     558             :     // return true if raw input is within deadzone of trim
     559             :     bool in_raw_trim_dz() const;
     560         664 :     int16_t get_raw_radio_in() const { return raw_radio_in; }
     561             : 
     562             :     float pwm_to_angle() const;
     563             :     float pwm_to_angle_dz(uint16_t dead_zone) const;
     564             : 
     565             :     float pwm_to_range() const;
     566             :     float pwm_to_range_dz(uint16_t dead_zone) const;
     567             : 
     568             :     bool read_3pos_switch(AuxSwitchPos &ret) const WARN_IF_UNUSED;
     569             :     bool read_6pos_switch(int8_t& position) WARN_IF_UNUSED;
     570             : 
     571             :     // Structure used to detect and debounce switch changes
     572             :     struct {
     573             :         int8_t debounce_position = -1;
     574             :         int8_t current_position = -1;
     575             :         uint32_t last_edge_time_ms;
     576             :         bool initialised;
     577             :     } switch_state;
     578             : 
     579             :     void reset_mode_switch();
     580             :     void read_mode_switch();
     581             :     bool debounce_completed(int8_t position);
     582             :     // returns true if the first time we successfully read the
     583             :     // channel's three-position-switch position we should record that
     584             :     // position as the current position *without* executing the
     585             :     // associated auxiliary function.  e.g. do not attempt to arm a
     586             :     // vehicle when the user turns on their transmitter with the arm
     587             :     // switch high!
     588             :     bool init_position_on_first_radio_read(AUX_FUNC func) const;
     589             : 
     590             : #if AP_RC_CHANNEL_AUX_FUNCTION_STRINGS_ENABLED
     591             :     // Structure to lookup switch change announcements
     592             :     struct LookupTable{
     593             :        AUX_FUNC option;
     594             :        const char *announcement;
     595             :     };
     596             : 
     597             :     static const LookupTable lookuptable[];
     598             : #endif
     599             : };
     600             : 
     601             : 
     602             : /*
     603             :   class RC_Channels. Hold the full set of RC_Channel objects
     604             : */
     605             : class RC_Channels {
     606             : public:
     607             :     friend class SRV_Channels;
     608             :     friend class RC_Channel;
     609             :     // constructor
     610             :     RC_Channels(void);
     611             : 
     612             :     __INITFUNC__ void init(void);
     613             : 
     614             :     // get singleton instance
     615   665596969 :     static RC_Channels *get_singleton() {
     616   665596969 :         return _singleton;
     617             :     }
     618             : 
     619             :     static const struct AP_Param::GroupInfo var_info[];
     620             : 
     621             :     // this function is implemented in the child class in the vehicle
     622             :     // code
     623             :     virtual RC_Channel *channel(uint8_t chan) = 0;
     624             :     virtual const RC_Channel *channel(uint8_t chan) const = 0;
     625             :     // helper used by scripting to convert the above function from 0 to 1 indexeing
     626             :     // range is checked correctly by the underlying channel function
     627        3851 :     RC_Channel *lua_rc_channel(const uint8_t chan) {
     628        3851 :         return channel(chan -1);
     629             :     }
     630             : 
     631             :     uint8_t get_radio_in(uint16_t *chans, const uint8_t num_channels); // reads a block of chanel radio_in values starting from channel 0
     632             :                                                                        // returns the number of valid channels
     633             : 
     634             :     static uint8_t get_valid_channel_count(void);                      // returns the number of valid channels in the last read
     635             :     static int16_t get_receiver_rssi(void);                            // returns [0, 255] for receiver RSSI (0 is no link) if present, otherwise -1
     636             :     static int16_t get_receiver_link_quality(void);                         // returns 0-100 % of last 100 packets received at receiver are valid
     637             :     bool read_input(void);                                             // returns true if new input has been read in
     638             :     static void clear_overrides(void);                                 // clears any active overrides
     639             :     static void set_override(const uint8_t chan, const int16_t value, const uint32_t timestamp_ms = 0); // set a channels override value
     640             :     static bool has_active_overrides(void);                            // returns true if there are overrides applied that are valid
     641             : 
     642             :     // returns a mask indicating which channels have overrides.  Bit 0
     643             :     // is RC channel 1.  Beware this is not a cheap call.
     644             :     uint16_t get_override_mask() const;
     645             : 
     646             :     class RC_Channel *find_channel_for_option(const RC_Channel::AUX_FUNC option);
     647             :     bool duplicate_options_exist();
     648             : 
     649             :     void init_aux_all();
     650             :     void read_aux_all();
     651             : 
     652             :     // mode switch handling
     653             :     void reset_mode_switch();
     654             :     virtual void read_mode_switch();
     655             : 
     656           0 :     virtual bool in_rc_failsafe() const { return true; };
     657             :     virtual bool has_valid_input() const;
     658      356241 :     virtual RC_Channel *get_arming_channel(void) const { return nullptr; };
     659             : 
     660        4110 :     bool gcs_overrides_enabled() const { return _gcs_overrides_enabled; }
     661          44 :     void set_gcs_overrides_enabled(bool enable) {
     662          44 :         _gcs_overrides_enabled = enable;
     663          44 :         if (!_gcs_overrides_enabled) {
     664          25 :             clear_overrides();
     665             :         }
     666          44 :     }
     667             : 
     668             :     enum class Option {
     669             :         IGNORE_RECEIVER         = (1U << 0), // RC receiver modules
     670             :         IGNORE_OVERRIDES        = (1U << 1), // MAVLink overrides
     671             :         IGNORE_FAILSAFE         = (1U << 2), // ignore RC failsafe bits
     672             :         FPORT_PAD               = (1U << 3), // pad fport telem output
     673             :         LOG_RAW_DATA            = (1U << 4), // log rc input bytes
     674             :         ARMING_CHECK_THROTTLE   = (1U << 5), // run an arming check for neutral throttle
     675             :         ARMING_SKIP_CHECK_RPY   = (1U << 6), // skip the an arming checks for the roll/pitch/yaw channels
     676             :         ALLOW_SWITCH_REV        = (1U << 7), // honor the reversed flag on switches
     677             :         CRSF_CUSTOM_TELEMETRY   = (1U << 8), // use passthrough data for crsf telemetry
     678             :         SUPPRESS_CRSF_MESSAGE   = (1U << 9), // suppress CRSF mode/rate message for ELRS systems
     679             :         MULTI_RECEIVER_SUPPORT  = (1U << 10), // allow multiple receivers
     680             :         USE_CRSF_LQ_AS_RSSI     = (1U << 11), // returns CRSF link quality as RSSI value, instead of RSSI
     681             :         CRSF_FM_DISARM_STAR     = (1U << 12), // when disarmed, add a star at the end of the flight mode in CRSF telemetry
     682             :         ELRS_420KBAUD           = (1U << 13), // use 420kbaud for ELRS protocol
     683             :         CLEAR_OVERRIDES_BY_RC   = (1U << 14), // clear MAVLink overrides when the pilot moves the RC sticks (per-vehicle definition)
     684             :     };
     685             : 
     686   279869948 :     bool option_is_enabled(Option option) const {
     687   279869948 :         return _options & uint32_t(option);
     688             :     }
     689             : 
     690      182985 :     virtual bool arming_check_throttle() const {
     691      182985 :         return option_is_enabled(Option::ARMING_CHECK_THROTTLE);
     692             :     }
     693             : 
     694             :     // returns true if overrides should time out.  If true is returned
     695             :     // then returned_timeout_ms will contain the timeout in
     696             :     // milliseconds, with 0 meaning overrides are disabled.
     697     2691019 :     bool get_override_timeout_ms(uint32_t &returned_timeout_ms) const {
     698     2691019 :         const float value = _override_timeout.get();
     699     2691019 :         if (is_positive(value)) {
     700     2686926 :             returned_timeout_ms = uint32_t(value * 1e3f);
     701     2686926 :             return true;
     702             :         }
     703        4093 :         if (is_zero(value)) {
     704         112 :             returned_timeout_ms = 0;
     705         112 :             return true;
     706             :         }
     707             :         // overrides will not time out
     708        3981 :         return false;
     709             :     }
     710             : 
     711             :     // get mask of enabled protocols
     712             :     uint32_t enabled_protocols() const;
     713             : 
     714             :     // returns true if we have had a direct detach RC receiver, does not include overrides
     715   122758294 :     bool has_had_rc_receiver() const { return _has_had_rc_receiver; }
     716             : 
     717             :     // returns true if we have had an override on any channel
     718         316 :     bool has_had_rc_override() const { return _has_had_override; }
     719             : 
     720             :     /*
     721             :       get the RC input PWM value given a channel number.  Note that
     722             :       channel numbers start at 1, as this API is designed for use in
     723             :       LUA
     724             :     */
     725             :     bool get_pwm(uint8_t channel, uint16_t &pwm) const;
     726             : 
     727        1028 :     uint32_t last_input_ms() const { return last_update_ms; };
     728             : 
     729             :     // method for other parts of the system (e.g. Button and mavlink)
     730             :     // to trigger auxiliary functions
     731          29 :     bool run_aux_function(RC_Channel::AUX_FUNC ch_option, RC_Channel::AuxSwitchPos pos, RC_Channel::AuxFuncTrigger::Source source, uint16_t source_index) {
     732          29 :         return channel(0)->run_aux_function(ch_option, pos, source, source_index);
     733             :     }
     734             : 
     735             :     // check if flight mode channel is assigned RC option
     736             :     // return true if assigned
     737             :     bool flight_mode_channel_conflicts_with_rc_option() const;
     738             : 
     739             :     // flight_mode_channel_number must be overridden in vehicle specific code
     740             :     virtual int8_t flight_mode_channel_number() const = 0;
     741             : 
     742             :     // set and get calibrating flag, stops arming if true
     743          43 :     void calibrating(bool b) { gcs_is_calibrating = b; }
     744      140537 :     bool calibrating() { return gcs_is_calibrating; }
     745             : 
     746             : #if AP_SCRIPTING_ENABLED
     747             :     // get last aux cached value for scripting. Returns false if never set, otherwise 0,1,2
     748             :     bool get_aux_cached(RC_Channel::AUX_FUNC aux_fn, uint8_t &pos);
     749             : #endif
     750             : 
     751             :     // returns true if we've ever seen RC input, via overrides or via
     752             :     // AP_RCProtocol
     753   137199395 :     bool has_ever_seen_rc_input() const {
     754   137199395 :         return _has_ever_seen_rc_input;
     755             :     }
     756             : 
     757             :     // get failsafe timeout in milliseconds
     758    66524604 :     uint32_t get_fs_timeout_ms() const { return MAX(_fs_timeout * 1000, 100); }
     759             : 
     760             :     // methods which return RC input channels used for various axes.
     761             :     const RC_Channel &get_roll_channel() const;
     762             :     const RC_Channel &get_pitch_channel() const;
     763             :     const RC_Channel &get_yaw_channel() const;
     764             :     const RC_Channel &get_throttle_channel() const;
     765             :     const RC_Channel &get_forward_channel() const;
     766             :     const RC_Channel &get_lateral_channel() const;
     767             : 
     768             :     RC_Channel &get_roll_channel();
     769             :     RC_Channel &get_pitch_channel();
     770             :     RC_Channel &get_yaw_channel();
     771             :     RC_Channel &get_throttle_channel();
     772             :     RC_Channel &get_forward_channel();
     773             :     RC_Channel &get_lateral_channel();
     774             : 
     775        3731 :     bool seen_neutral_rudder() const { return have_seen_neutral_rudder; }
     776             : 
     777             :     // returns true when pilot input should clear an active MAVLink override; vehicles override to define which axes count
     778             :     virtual bool has_pilot_input_for_override_clear();
     779             : 
     780             : protected:
     781             : 
     782        3585 :     void new_override_received() {
     783        3585 :         has_new_overrides = true;
     784        3585 :         _has_had_override = true;
     785        3585 :     }
     786             : 
     787             :     // returns true if the channel's raw pwm is outside its trim deadzone
     788             :     static bool channel_outside_trim_dz(const RC_Channel &ch);
     789             : 
     790             :     // returns true if throttle moved beyond deadzone since override start
     791             :     bool throttle_moved_since_override_start() const;
     792             : 
     793             : private:
     794             :     static RC_Channels *_singleton;
     795             :     // this static arrangement is to avoid static pointers in AP_Param tables
     796             :     static RC_Channel *channels;
     797             : 
     798             :     uint32_t last_update_ms;
     799             :     bool has_new_overrides;
     800             :     bool _has_had_rc_receiver; // true if we have had a direct detach RC receiver, does not include overrides
     801             :     bool _has_had_override; // true if we have had an override on any channel
     802             :     int16_t override_start_throttle; // throttle value at the moment an override was activated
     803             : 
     804             :     AP_Float _override_timeout;
     805             :     AP_Int32  _options;
     806             :     AP_Int32  _protocols;
     807             :     AP_Float _fs_timeout;
     808             : 
     809             :     // set to true if we see overrides or other RC input
     810             :     bool _has_ever_seen_rc_input;
     811             : 
     812             :     RC_Channel *flight_mode_channel();
     813             :     const RC_Channel *flight_mode_channel() const;
     814             : 
     815             :     // Allow override by default at start
     816             :     bool _gcs_overrides_enabled = true;
     817             : 
     818             :     // true if GCS is performing a RC calibration
     819             :     bool gcs_is_calibrating;
     820             : 
     821             : #if AP_SCRIPTING_ENABLED
     822             :     // bitmask of last aux function value, 2 bits per function
     823             :     // value 0 means never set, otherwise level+1
     824             :     HAL_Semaphore aux_cache_sem;
     825             :     Bitmask<unsigned(RC_Channel::AUX_FUNC::AUX_FUNCTION_MAX)*2> aux_cached;
     826             : 
     827             :     void set_aux_cached(RC_Channel::AUX_FUNC aux_fn, RC_Channel::AuxSwitchPos pos);
     828             : #endif
     829             : 
     830             :     const RC_Channel &get_rcmap_channel_nonnull(uint8_t rcmap_number) const;
     831             :     RC_Channel &get_rcmap_channel_nonnull(uint8_t rcmap_number);
     832             : 
     833             :     // time that rudder arming has been running
     834             :     uint32_t rudder_arm_timer;
     835             :     // true if we have seen a neutral rudder control input after
     836             :     // arming via rudder-input:
     837             :     bool have_seen_neutral_rudder;
     838             :     // check for arm/disarm command based on rudder stick position:
     839             :     void rudder_arm_disarm_check();
     840             : 
     841             :     // returns true if pilot stick input has exited any deadzone (or throttle moved)
     842             :     bool should_ignore_overrides(void);
     843      967932 :     void set_override_start_throttle(int16_t pwm) { override_start_throttle = pwm; }
     844             : };
     845             : 
     846             : RC_Channels &rc();
     847             : 
     848             : #endif  // AP_RC_CHANNEL_ENABLED

Generated by: LCOV version 1.14