#ifndef BUTTON_H
#define BUTTON_H

#include <stdint.h>
#include "check.h"

/**
 * \addtogroup Button
 *
 * \brief Enables event-driven and polling access to the buttons of the SPiCboard
 *
 * The SPiCboard is equipped with two buttons. Button 0 is debounced in
 * hardware, whereas Button 1 needs to be debounced in software by the
 * button module. Debouncing is transparent to the application, that
 * can use both buttons through the provided interface without the
 * need to care about debouncing.
 *
 * The debouncing code makes use of a timer. When no callbacks
 * are registered for Button 1, the debouncing code is disabled and all
 * alarms registered at the timer should be canceled.
 *
 * The button module uses dynamic memory management to maintain the
 * callback queues.
 *
 * @{
 * \file button.h
 * \version \$Rev: 7715 $
 */

/**
 * \brief Identifiers for all available buttons
 */
typedef enum {
	BUTTON0 = 0, /**< Button 0 */
	BUTTON1 = 1  /**< Button 1 */
} __attribute__ ((__packed__)) BUTTON;

CHECK_ENUM_SIZE(BUTTON, 1)


/**
 * \brief States for buttons
 *
 * Pressed and released states for buttons.
 */
typedef enum {
	UNKNOWN  = 0, /**< Buttonstate is unknown (invalid button?) */
	PRESSED  = 4, /**< Button is pressed  */
	RELEASED = 8  /**< Button is released */
} __attribute__ ((__packed__)) BUTTONSTATE;

CHECK_ENUM_SIZE(BUTTONSTATE, 1)

/**
 * \brief Events for buttons
 *
 * Down (on press) and up (on release) events for buttons.
 */
typedef enum {
	ONPRESS   = 0, /**< Button is pressed  */
	ONRELEASE = 2  /**< Button is released */
} __attribute__ ((__packed__)) BUTTONEVENT;

CHECK_ENUM_SIZE(BUTTONEVENT, 1)

/**
 * \brief Type for button event callback functions
 *
 * A button callback function is called on the interrupt level whenever
 * an event at a button occurs that the function was registered for.
 * The callback function is passed the button id and the type of event
 * that occurred. This way, the same callback function can be registered
 * for different buttons and events.
 */
typedef void (*BUTTONCALLBACK) (BUTTON, BUTTONEVENT);

/**
 * \brief Register a callback function for a button event
 *
 * Interrupts must be enabled to receive the callbacks.
 *
 * \param btn       the id of the button
 * \param eve       the type of event that the callback function should be invoked for.
 * \param callback  pointer to the callback function. This function is called from the
 *                  interrupt handler.
 *
 * \retval 0   success,
 * \retval !0  error
 *
 * \sa sb_button_unregisterCallback
 */
int8_t sb_button_registerCallback(BUTTON btn, BUTTONEVENT eve, BUTTONCALLBACK callback);

/**
 * \brief Unregister a callback function for a button event
 *
 * \param btn       the id of the button
 * \param eve       the type of event that the callback function should be invoked for.
 * \param callback  pointer to the callback function
 *
 * \return 0 on success, negative value on error
 *
 * \retval  0  success
 * \retval -1  the callback function was not registered with the given button/event combination
 *
 * \sa         sb_button_registerCallback
 */
int8_t sb_button_unregisterCallback(BUTTON btn, BUTTONEVENT eve, BUTTONCALLBACK callback);

/**
 * \brief Query the current state of a button
 *
 * \param btn  id of the button
 *
 * \return the buttons current state (pressed or released - or unknown if invalid button) as a \ref BUTTONSTATE
 */
BUTTONSTATE sb_button_getState(BUTTON btn);

/** @}*/

#endif

