/*
 *
 *
 *    hysteresis.h
 *
 *    Emulates a Schmitt trigger.
 *
 *    Copyright (C) 2016 by Matt Roberts.
 *    License: GNU GPL3 (www.gnu.org)
 *
 *
 */

#ifndef __KK5JY_HYSTERESIS_H
#define __KK5JY_HYSTERESIS_H

namespace KK5JY {
	namespace DSP {
		//
		//
		//   hysteresis trigger
		//
		//
		template <typename sample_t = double>
		class Hysteresis {
			private:
				// the output state
				bool m_State;
				// limits
				sample_t lower, higher;
				sample_t m_Offset;

			public: // ctors/dtors
				Hysteresis(sample_t l, sample_t h) : m_State(false), lower(l), higher(h), m_Offset(0) { /* nop */ }
				~Hysteresis() { /* nop */ };
			private: // disallowed ctors
				Hysteresis();
				Hysteresis(const Hysteresis &);

			public: // public methods
				// run one sample through the counter
				bool run(sample_t in);

				// return the current state
				bool state() const { return m_State; }

			public: // mutators and accessors
				// set or get the offset
				void offset(sample_t value) { m_Offset = value; }
				sample_t offset() const { return m_Offset; }

				// return the current thresholds
				sample_t high() const { return higher; }
				sample_t low() const { return lower; }

				// reconfigure the trigger levels
				void high(sample_t new_value) { higher = new_value; };
				void low(sample_t new_value) { lower = new_value; };
		};

		template <typename sample_t>
		inline bool Hysteresis<sample_t>::run(sample_t in) {
			in += m_Offset;
			if (m_State) {
				if (in < lower)
					m_State = false;
			} else {
				if (in >= higher)
					m_State = true;
			}
			return m_State;
		}
	}
}
#endif
