/*! \file pigpio.h
 * \brief GPIO
*/
/*
	PIP - Platform Independent Primitives
	GPIO
	Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIGPIO_H
#define PIGPIO_H

#include "pithread.h"


class PIP_EXPORT PIGPIO: public PIThread
{
	PIOBJECT_SUBCLASS(PIGPIO, PIThread)
public:
	PIGPIO();
	virtual ~PIGPIO();

	//! \brief Work mode for pin
	enum Direction {
		In  /** Input direction (read) */,
		Out /** Output direction (write) */
	};

	//! \brief Returns singleton object of %PIGPIO
	static PIGPIO * instance();

	//! \brief Initialize pin \"gpio_num\" for \"dir\" mode
	void initPin(int gpio_num, Direction dir = PIGPIO::In);

	//! \brief Set pin \"gpio_num\" value to \"value\"
	void pinSet  (int gpio_num, bool value);

	//! \brief Set pin \"gpio_num\" value to \b true
	void pinHigh (int gpio_num) {pinSet(gpio_num, true );}

	//! \brief Set pin \"gpio_num\" value to \b false
	void pinLow  (int gpio_num) {pinSet(gpio_num, false);}

	//! \brief Returns pin \"gpio_num\" state
	bool pinState(int gpio_num);

	//! \brief Starts watch for pin \"gpio_num\".
	//! \details Pins watching starts only with \a PIThread::start() function!
	//! This function doesn`t affect thread state
	void pinBeginWatch(int gpio_num);

	//! \brief End watch for pin \"gpio_num\".
	//! \details Pins watching starts only with \a PIThread::start() function!
	//! This function doesn`t affect thread state
	void pinEndWatch  (int gpio_num);

	//! \brief End watch for all pins.
	//! \details Pins watching starts only with \a PIThread::start() function!
	//! This function doesn`t affect thread state
	void clearWatch();

	EVENT2(pinChanged, int, gpio_num, bool, new_value)

	//! \events
	//! \{

		//! \fn void pinChanged(int gpio_num, bool new_value)
		//! \brief Raise on pin \"gpio_num\" state changes to \"new_value\"
		//! \details Important! This event will be raised only with started
		//! thread.

	//! \}

private:
	struct PIP_EXPORT GPIOData {
		GPIOData() {dir = PIGPIO::In; num = fd = -1;}
		PIString name;
		int dir;
		int num;
		int fd;
	};
	void exportGPIO(int gpio_num);
	void openGPIO(GPIOData & g);
	bool getPinState(int gpio_num);
	void begin();
	void run();
	void end();

	static PIString GPIOName(int gpio_num);

	PIMap<int, GPIOData> gpio_;
	PIMap<int, bool> watch_state;
	PIMutex mutex;

};


#endif // PIDIR_H
