/**
 * \file
 *
 * \brief SENSORS_XPLAINED_BOARD extension board init.
 *
 * This file contains an initialization function for Xplained Sensor boards.
 *
 * - Compiler:           IAR EWAVR32 and GNU GCC for AVR
 * - Supported devices:  Atmel Sensors Xplained extension boards.
 * - AppNote:
 *
 ******************************************************************************/

/* Copyright (c) 2010 Atmel Corporation. All rights reserved.
 *
 * \page License
 *
 * 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. The name of Atmel may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 * Atmel AVR product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
 */


//! \name Atmel Xplained Development Board Definitions

#include <board.h>
#include <gpio.h>


#if UC3
#   define PIN_OUTPUT_FLAGS         (GPIO_DIR_OUTPUT | GPIO_INIT_HIGH)
#   define PIN_INPUT_FLAGS          (GPIO_DIR_INPUT)
#elif XMEGA
#   define PIN_OUTPUT_FLAGS         (IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH)
#   define PIN_INPUT_FLAGS          (IOPORT_DIR_INPUT)
#endif


#if  defined(__AVR32__) || defined(__ICCAVR32__)
#if !defined(AVR32_GPIO_IRQ_GROUP)
#   define AVR32_GPIO_IRQ_GROUP     (AVR32_GPIO_IRQ_0 / 32)
#endif
#if  defined(CONFIG_GPIO_INT_LVL)
#   define GPIO_INT_LVL             CONFIG_GPIO_INT_LVL
#else
#   define GPIO_INT_LVL             0
#endif
#endif    //(__AVR32__) || (__ICCAVR32__)


//! \internal Sensor Board GPIO interrupt handler callback pointers

static GPIO_IRQ_HANDLER sensor_pin3_handler;
static volatile void *  sensor_pin3_arg;

static GPIO_IRQ_HANDLER sensor_pin4_handler;
static volatile void *  sensor_pin4_arg;

static GPIO_IRQ_HANDLER sensor_pin5_handler;
static volatile void *  sensor_pin5_arg;

/*! \internal Sensor Board GPIO interrupt handler
 *
 * This is the default ISR for the Xplained Sensor board GPIO pins.
 *
 * \return  Nothing.
 */
#if UC3
ISR (sensor_board_gpio_irq, AVR32_GPIO_IRQ_GROUP, GPIO_INT_LVL) {

    if (gpio_get_pin_interrupt_flag (SENSOR_BOARD_PIN3)) {

        (sensor_pin3_handler)(sensor_pin3_arg);

        gpio_clear_pin_interrupt_flag (SENSOR_BOARD_PIN3);
        }
    else if (gpio_get_pin_interrupt_flag (SENSOR_BOARD_PIN4)) {

        (sensor_pin4_handler)(sensor_pin4_arg);

        gpio_clear_pin_interrupt_flag (SENSOR_BOARD_PIN4);
        }
    else if (gpio_get_pin_interrupt_flag (SENSOR_BOARD_PIN5)) {

        (sensor_pin5_handler)(sensor_pin5_arg);

        gpio_clear_pin_interrupt_flag (SENSOR_BOARD_PIN5);
        }
    }
#endif // UC3

/*! \brief This function initializes sensor board target resources
 *
 * This function should be called to ensure proper initialization
 * of sensor extension board hardware connected to an "Xplained"
 * development platform.
 *
 * \return  Nothing.
 */
void sensor_board_init (void) {
    //
    // Configure all defined Xplained Sensor board I/O pins.
    // 
    // \todo
    // Determine whether the interrupt event flag (rising edge, falling
    // edge, toggle, etc.) should be a statically configurable parameter
    // for devices requiring more flexibility in how events are detected.
    //
#if (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_1) || \
    (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_2) || \
    (EXT_BOARD == SENSORS_XPLAINED_INERTIAL_A1)

	gpio_configure_pin (SENSOR_BOARD_PIN3, PIN_INPUT_FLAGS);
	gpio_configure_pin (SENSOR_BOARD_PIN4, PIN_INPUT_FLAGS);
	gpio_configure_pin (SENSOR_BOARD_PIN5, PIN_INPUT_FLAGS);

#elif (EXT_BOARD == SENSORS_XPLAINED_PRESSURE_1)

	gpio_configure_pin (SENSOR_BOARD_PIN3, PIN_OUTPUT_FLAGS);
	gpio_configure_pin (SENSOR_BOARD_PIN4, PIN_INPUT_FLAGS);

#elif (EXT_BOARD == SENSORS_XPLAINED_LIGHT_1)

	gpio_configure_pin (SENSOR_BOARD_PIN3, PIN_INPUT_FLAGS);

#endif
    //
    // Global Interrupt Disable
    //
    cpu_irq_disable ();
    //
    // Initialize interrupt vector table support.
    //
    irq_initialize_vectors ();
    //
    // Register sensor board GPIO interrupt event dispatcher.
    //
#if UC3
    irq_register_handler (sensor_board_gpio_irq, SENSOR_PIN3_IRQ, GPIO_INT_LVL);
    irq_register_handler (sensor_board_gpio_irq, SENSOR_PIN4_IRQ, GPIO_INT_LVL);
    irq_register_handler (sensor_board_gpio_irq, SENSOR_PIN5_IRQ, GPIO_INT_LVL);
#endif
    //
    // Global Interrupt Enable
    //
    cpu_irq_enable ();
}

/*! \brief Install an Xplained Sensor board interrupt handler
 *
 * The Sensors Xplained add-on boards route sensor device I/O pins to GPIO
 * pins for the MCU installed on an Xplained platform board.  Some sensor
 * devices can be configured to generate interrupts on these pins to indicate
 * the availability of new sensor data or the occurrence of configurable
 * events related to sensor data thresholds, for example.
 *
 * This routine will enable interrupts on the GPIO pin specified by the
 * \c gpio_pin parameter and call a user-defined callback \c handler when an
 * interrupt is detected.  The \c arg parameter is used to pass the address
 * of user-defined input and output storage for the callback handler.  Calling
 * the routine with the \c handler parameter set to 0 (the NULL pointer) will
 * cause interrupts to be disabled for the specified GPIO pin.
 *
 * \param   gpio_pin    Board-specific GPIO pin interface to the MCU.
 * \param   handler     The address of a user-defined interrupt handler.
 * \param   arg         An optional address passed to the interrupt handler.
 *
 * \return  bool        \c true if the call succeeds, else \c false.
 */
bool sensor_board_irq_connect
    (uint32_t gpio_pin, GPIO_IRQ_HANDLER handler, void * arg) {
#if UC3
    if (SENSOR_BOARD_PIN3 == gpio_pin) {

        sensor_pin3_handler = handler;
        sensor_pin3_arg     = arg;

        if (handler) {
            gpio_enable_pin_interrupt (gpio_pin, GPIO_RISING_EDGE);
        } else {
            gpio_disable_pin_interrupt (gpio_pin);
        }
    } else if (SENSOR_BOARD_PIN4 == gpio_pin) {

        sensor_pin4_handler = handler;
        sensor_pin4_arg     = arg;

        if (handler) {
            gpio_enable_pin_interrupt (gpio_pin, GPIO_RISING_EDGE);
        } else {
            gpio_disable_pin_interrupt (gpio_pin);
        }
    } else if (SENSOR_BOARD_PIN5 == gpio_pin) {

        sensor_pin5_handler = handler;
        sensor_pin5_arg     = arg;

        if (handler) {
            gpio_enable_pin_interrupt (gpio_pin, GPIO_RISING_EDGE);
        } else {
            gpio_disable_pin_interrupt (gpio_pin);
        }
    } else {
        return false;
    }
#endif // UC3

    return true;
}
