text: /****************************************************************************
   *
   *   Copyright (C) 2012-2019 PX4 Development Team. All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 3. Neither the name PX4 nor the names of its contributors may be
   *    used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   *
   ****************************************************************************/
  
  #pragma once
  
  #include <mixer/MixerBase/Mixer.hpp>
  
  /** simple channel scaler */
  struct mixer_scaler_s {
  	float negative_scale{1.0f};
  	float positive_scale{1.0f};
  	float offset{0.0f};
  	float min_output{-1.0f};
  	float max_output{1.0f};
  };
  
  /** mixer input */
  struct mixer_control_s {
  	uint8_t			control_group;	/**< group from which the input reads */
  	uint8_t			control_index;	/**< index within the control group */
  	mixer_scaler_s		scaler;		/**< scaling applied to the input before use */
  };
  
  #define MIXER_SIMPLE_SIZE(_icount)	(sizeof(struct mixer_simple_s) + (_icount) * sizeof(struct mixer_control_s))
  
  /** simple mixer */
  struct mixer_simple_s {
  	uint8_t			control_count;	/**< number of inputs */
  	mixer_scaler_s		output_scaler;	/**< scaling for the output */
  	float 			slew_rate_rise_time{0.0f}; /**< output max rise time (slew rate limit)*/
  	mixer_control_s		controls[];	/**< actual size of the array is set by control_count */
  };
  
  /**
   * Simple summing mixer.
   *
   * Collects zero or more inputs and mixes them to a single output.
   */
  class SimpleMixer : public Mixer
  {
  public:
  	/**
  	 * Constructor
  	 *
  	 * @param mixinfo		Mixer configuration.  The pointer passed
  	 *				becomes the property of the mixer and
  	 *				will be freed when the mixer is deleted.
  	 */
  	SimpleMixer(ControlCallback control_cb, uintptr_t cb_handle, mixer_simple_s *mixinfo);
  	virtual ~SimpleMixer();
  
  	// no copy, assignment, move, move assignment
  	SimpleMixer(const SimpleMixer &) = delete;
  	SimpleMixer &operator=(const SimpleMixer &) = delete;
  	SimpleMixer(SimpleMixer &&) = delete;
  	SimpleMixer &operator=(SimpleMixer &&) = delete;
  
  	/**
  	 * Factory method with full external configuration.
  	 *
  	 * Given a pointer to a buffer containing a text description of the mixer,
  	 * returns a pointer to a new instance of the mixer.
  	 *
  	 * @param control_cb		The callback to invoke when fetching a
  	 *				control value.
  	 * @param cb_handle		Handle passed to the control callback.
  	 * @param buf			Buffer containing a text description of
  	 *				the mixer.
  	 * @param buflen		Length of the buffer in bytes, adjusted
  	 *				to reflect the bytes consumed.
  	 * @return			A new SimpleMixer instance, or nullptr
  	 *				if the text format is bad.
  	 */
  	static SimpleMixer		*from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf,
  			unsigned &buflen);
  
  	unsigned			mix(float *outputs, unsigned space) override;
  
  	void				groups_required(uint32_t &groups) override;
  
  	/**
  	 * Check that the mixer configuration as loaded is sensible.
  	 *
  	 * Note that this function will call control_cb, but only cares about
  	 * error returns, not the input value.
  	 *
  	 * @return			Zero if the mixer makes sense, nonzero otherwise.
  	 */
  	int				check();
  
  	unsigned			set_trim(float trim) override;
  	unsigned			get_trim(float *trim) override;
  	void				set_dt_once(float dt) override;
  
  private:
  
  	/**
  	 * Perform simpler linear scaling.
  	 *
  	 * @param scaler		The scaler configuration.
  	 * @param input			The value to be scaled.
  	 * @return			The scaled value.
  	 */
  	static float			scale(const mixer_scaler_s &scaler, float input);
  
  	/**
  	 * Validate a scaler
  	 *
  	 * @param scaler		The scaler to be validated.
  	 * @return			Zero if good, nonzero otherwise.
  	 */
  	static int			scale_check(struct mixer_scaler_s &scaler);
  
  	static int parse_output_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, float &slew_rate_rise_time);
  	static int parse_control_scaler(const char *buf, unsigned &buflen, mixer_scaler_s &scaler, uint8_t &control_group,
  					uint8_t &control_index);
  
  	float 				_output_prev{0.f};
  	float				_dt{0.f};
  
  	mixer_simple_s			*_pinfo;
  
  };
  