blob: 3cf630d6cdf1e6d71a695617e9902ec24a70234c [file] [log] [blame]
/**
* \file
*
* \brief Common IOPORT service main header file for AVR, UC3 and ARM
* architectures.
*
* Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \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 microcontroller 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.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef IOPORT_H
#define IOPORT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <parts.h>
#include <compiler.h>
/**
* \defgroup ioport_group Common IOPORT API
*
* See \ref ioport_quickstart.
*
* This is common IOPORT service for GPIO pin configuration and control in a
* standardized manner across the MEGA, MEGA_RF, XMEGA, UC3 and ARM devices.
*
* Port pin control code is optimized for each platform, and should produce
* both compact and fast execution times when used with constant values.
*
* \section dependencies Dependencies
* This driver depends on the following modules:
* - \ref sysclk_group for clock speed and functions.
* @{
*/
/**
* \def IOPORT_CREATE_PIN(port, pin)
* \brief Create IOPORT pin number
*
* Create a IOPORT pin number for use with the IOPORT functions.
*
* \param port IOPORT port (e.g. PORTA, PA or PIOA depending on chosen
* architecture)
* \param pin IOPORT zero-based index of the I/O pin
*/
/** \brief IOPORT pin directions */
enum ioport_direction {
IOPORT_DIR_INPUT, /*!< IOPORT input direction */
IOPORT_DIR_OUTPUT, /*!< IOPORT output direction */
};
/** \brief IOPORT levels */
enum ioport_value {
IOPORT_PIN_LEVEL_LOW, /*!< IOPORT pin value low */
IOPORT_PIN_LEVEL_HIGH, /*!< IOPORT pin value high */
};
#if MEGA_RF
/** \brief IOPORT edge sense modes */
enum ioport_sense {
IOPORT_SENSE_LEVEL, /*!< IOPORT sense low level */
IOPORT_SENSE_BOTHEDGES, /*!< IOPORT sense both rising and falling edges */
IOPORT_SENSE_FALLING, /*!< IOPORT sense falling edges */
IOPORT_SENSE_RISING, /*!< IOPORT sense rising edges */
};
#elif SAM && !SAM4L
/** \brief IOPORT edge sense modes */
enum ioport_sense {
IOPORT_SENSE_BOTHEDGES, /*!< IOPORT sense both rising and falling edges */
IOPORT_SENSE_FALLING, /*!< IOPORT sense falling edges */
IOPORT_SENSE_RISING, /*!< IOPORT sense rising edges */
IOPORT_SENSE_LEVEL_LOW, /*!< IOPORT sense low level */
IOPORT_SENSE_LEVEL_HIGH,/*!< IOPORT sense High level */
};
#else
enum ioport_sense {
IOPORT_SENSE_BOTHEDGES, /*!< IOPORT sense both rising and falling edges */
IOPORT_SENSE_RISING, /*!< IOPORT sense rising edges */
IOPORT_SENSE_FALLING, /*!< IOPORT sense falling edges */
};
#endif
#if XMEGA
# include "xmega/ioport.h"
# if defined(IOPORT_XMEGA_COMPAT)
# include "xmega/ioport_compat.h"
# endif
#elif MEGA
# include "mega/ioport.h"
#elif UC3
# include "uc3/ioport.h"
#elif SAM
# if SAM4L
# include "sam/ioport_gpio.h"
# elif (SAMD20 | SAMD21)
# include "sam0/ioport.h"
# else
# include "sam/ioport_pio.h"
# endif
#endif
/**
* \brief Initializes the IOPORT service, ready for use.
*
* This function must be called before using any other functions in the IOPORT
* service.
*/
static inline void ioport_init(void)
{
arch_ioport_init();
}
/**
* \brief Enable an IOPORT pin, based on a pin created with \ref
* IOPORT_CREATE_PIN().
*
* \param pin IOPORT pin to enable
*/
static inline void ioport_enable_pin(ioport_pin_t pin)
{
arch_ioport_enable_pin(pin);
}
/**
* \brief Enable multiple pins in a single IOPORT port.
*
* \param port IOPORT port to enable
* \param mask Mask of pins within the port to enable
*/
static inline void ioport_enable_port(ioport_port_t port,
ioport_port_mask_t mask)
{
arch_ioport_enable_port(port, mask);
}
/**
* \brief Disable IOPORT pin, based on a pin created with \ref
* IOPORT_CREATE_PIN().
*
* \param pin IOPORT pin to disable
*/
static inline void ioport_disable_pin(ioport_pin_t pin)
{
arch_ioport_disable_pin(pin);
}
/**
* \brief Disable multiple pins in a single IOPORT port.
*
* \param port IOPORT port to disable
* \param mask Pin mask of pins to disable
*/
static inline void ioport_disable_port(ioport_port_t port,
ioport_port_mask_t mask)
{
arch_ioport_disable_port(port, mask);
}
/**
* \brief Set multiple pin modes in a single IOPORT port, such as pull-up,
* pull-down, etc. configuration.
*
* \param port IOPORT port to configure
* \param mask Pin mask of pins to configure
* \param mode Mode masks to configure for the specified pins (\ref
* ioport_modes)
*/
static inline void ioport_set_port_mode(ioport_port_t port,
ioport_port_mask_t mask, ioport_mode_t mode)
{
arch_ioport_set_port_mode(port, mask, mode);
}
/**
* \brief Set pin mode for one single IOPORT pin.
*
* \param pin IOPORT pin to configure
* \param mode Mode masks to configure for the specified pin (\ref ioport_modes)
*/
static inline void ioport_set_pin_mode(ioport_pin_t pin, ioport_mode_t mode)
{
arch_ioport_set_pin_mode(pin, mode);
}
/**
* \brief Reset multiple pin modes in a specified IOPORT port to defaults.
*
* \param port IOPORT port to configure
* \param mask Mask of pins whose mode configuration is to be reset
*/
static inline void ioport_reset_port_mode(ioport_port_t port,
ioport_port_mask_t mask)
{
arch_ioport_set_port_mode(port, mask, 0);
}
/**
* \brief Reset pin mode configuration for a single IOPORT pin
*
* \param pin IOPORT pin to configure
*/
static inline void ioport_reset_pin_mode(ioport_pin_t pin)
{
arch_ioport_set_pin_mode(pin, 0);
}
/**
* \brief Set I/O direction for a group of pins in a single IOPORT.
*
* \param port IOPORT port to configure
* \param mask Pin mask of pins to configure
* \param dir Direction to set for the specified pins (\ref ioport_direction)
*/
static inline void ioport_set_port_dir(ioport_port_t port,
ioport_port_mask_t mask, enum ioport_direction dir)
{
arch_ioport_set_port_dir(port, mask, dir);
}
/**
* \brief Set direction for a single IOPORT pin.
*
* \param pin IOPORT pin to configure
* \param dir Direction to set for the specified pin (\ref ioport_direction)
*/
static inline void ioport_set_pin_dir(ioport_pin_t pin,
enum ioport_direction dir)
{
arch_ioport_set_pin_dir(pin, dir);
}
/**
* \brief Set an IOPORT pin to a specified logical value.
*
* \param pin IOPORT pin to configure
* \param level Logical value of the pin
*/
static inline void ioport_set_pin_level(ioport_pin_t pin, bool level)
{
arch_ioport_set_pin_level(pin, level);
}
/**
* \brief Set a group of IOPORT pins in a single port to a specified logical
* value.
*
* \param port IOPORT port to write to
* \param mask Pin mask of pins to modify
* \param level Level of the pins to be modified
*/
static inline void ioport_set_port_level(ioport_port_t port,
ioport_port_mask_t mask, ioport_port_mask_t level)
{
arch_ioport_set_port_level(port, mask, level);
}
/**
* \brief Get current value of an IOPORT pin, which has been configured as an
* input.
*
* \param pin IOPORT pin to read
* \return Current logical value of the specified pin
*/
static inline bool ioport_get_pin_level(ioport_pin_t pin)
{
return arch_ioport_get_pin_level(pin);
}
/**
* \brief Get current value of several IOPORT pins in a single port, which have
* been configured as an inputs.
*
* \param port IOPORT port to read
* \param mask Pin mask of pins to read
* \return Logical levels of the specified pins from the read port, returned as
* a mask.
*/
static inline ioport_port_mask_t ioport_get_port_level(ioport_pin_t port,
ioport_port_mask_t mask)
{
return arch_ioport_get_port_level(port, mask);
}
/**
* \brief Toggle the value of an IOPORT pin, which has previously configured as
* an output.
*
* \param pin IOPORT pin to toggle
*/
static inline void ioport_toggle_pin_level(ioport_pin_t pin)
{
arch_ioport_toggle_pin_level(pin);
}
/**
* \brief Toggle the values of several IOPORT pins located in a single port.
*
* \param port IOPORT port to modify
* \param mask Pin mask of pins to toggle
*/
static inline void ioport_toggle_port_level(ioport_port_t port,
ioport_port_mask_t mask)
{
arch_ioport_toggle_port_level(port, mask);
}
/**
* \brief Set the pin sense mode of a single IOPORT pin.
*
* \param pin IOPORT pin to configure
* \param pin_sense Edge to sense for the pin (\ref ioport_sense)
*/
static inline void ioport_set_pin_sense_mode(ioport_pin_t pin,
enum ioport_sense pin_sense)
{
arch_ioport_set_pin_sense_mode(pin, pin_sense);
}
/**
* \brief Set the pin sense mode of a multiple IOPORT pins on a single port.
*
* \param port IOPORT port to configure
* \param mask Bitmask if pins whose edge sense is to be configured
* \param pin_sense Edge to sense for the pins (\ref ioport_sense)
*/
static inline void ioport_set_port_sense_mode(ioport_port_t port,
ioport_port_mask_t mask,
enum ioport_sense pin_sense)
{
arch_ioport_set_port_sense_mode(port, mask, pin_sense);
}
/**
* \brief Convert a pin ID into a its port ID.
*
* \param pin IOPORT pin ID to convert
* \retval Port ID for the given pin ID
*/
static inline ioport_port_t ioport_pin_to_port_id(ioport_pin_t pin)
{
return arch_ioport_pin_to_port_id(pin);
}
/**
* \brief Convert a pin ID into a bitmask mask for the given pin on its port.
*
* \param pin IOPORT pin ID to convert
* \retval Bitmask with a bit set that corresponds to the given pin ID in its port
*/
static inline ioport_port_mask_t ioport_pin_to_mask(ioport_pin_t pin)
{
return arch_ioport_pin_to_mask(pin);
}
/** @} */
/**
* \page ioport_quickstart Quick start guide for the common IOPORT service
*
* This is the quick start guide for the \ref ioport_group, with
* step-by-step instructions on how to configure and use the service in a
* selection of use cases.
*
* The use cases contain several code fragments. The code fragments in the
* steps for setup can be copied into a custom initialization function, while
* the steps for usage can be copied into, e.g., the main application function.
*
* \section ioport_quickstart_basic Basic use case
* In this use case we will configure one IO pin for button input and one for
* LED control. Then it will read the button state and output it on the LED.
*
* \section ioport_quickstart_basic_setup Setup steps
*
* \subsection ioport_quickstart_basic_setup_code Example code
* \code
#define MY_LED IOPORT_CREATE_PIN(PORTA, 5)
#define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6)
ioport_init();
ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT);
ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT);
ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP);
\endcode
*
* \subsection ioport_quickstart_basic_setup_flow Workflow
* -# It's useful to give the GPIOs symbolic names and this can be done with
* the \ref IOPORT_CREATE_PIN macro. We define one for a LED and one for a
* button.
* - \code
#define MY_LED IOPORT_CREATE_PIN(PORTA, 5)
#define MY_BUTTON IOPORT_CREATE_PIN(PORTA, 6)
\endcode
* - \note The usefulness of the \ref IOPORT_CREATE_PIN macro and port names
* differ between architectures:
* - MEGA, MEGA_RF and XMEGA: Use \ref IOPORT_CREATE_PIN macro with port definitions
* PORTA, PORTB ...
* - UC3: Most convenient to pick up the device header file pin definition
* and us it directly. E.g.: AVR32_PIN_PB06
* - SAM: Most convenient to pick up the device header file pin definition
* and us it directly. E.g.: PIO_PA5_IDX<br>
* \ref IOPORT_CREATE_PIN can also be used with port definitions
* PIOA, PIOB ...
* -# Initialize the ioport service. This typically enables the IO module if
* needed.
* - \code ioport_init(); \endcode
* -# Set the LED GPIO as output:
* - \code ioport_set_pin_dir(MY_LED, IOPORT_DIR_OUTPUT); \endcode
* -# Set the button GPIO as input:
* - \code ioport_set_pin_dir(MY_BUTTON, IOPORT_DIR_INPUT); \endcode
* -# Enable pull-up for the button GPIO:
* - \code ioport_set_pin_mode(MY_BUTTON, IOPORT_MODE_PULLUP); \endcode
*
* \section ioport_quickstart_basic_usage Usage steps
*
* \subsection ioport_quickstart_basic_usage_code Example code
* \code
bool value;
value = ioport_get_pin_level(MY_BUTTON);
ioport_set_pin_level(MY_LED, value);
\endcode
*
* \subsection ioport_quickstart_basic_usage_flow Workflow
* -# Define a boolean variable for state storage:
* - \code bool value; \endcode
* -# Read out the button level into variable value:
* - \code value = ioport_get_pin_level(MY_BUTTON); \endcode
* -# Set the LED to read out value from the button:
* - \code ioport_set_pin_level(MY_LED, value); \endcode
*
* \section ioport_quickstart_advanced Advanced use cases
* - \subpage ioport_quickstart_use_case_1 : Port access
*/
/**
* \page ioport_quickstart_use_case_1 Advanced use case doing port access
*
* In this case we will read out the pins from one whole port and write the
* read value to another port.
*
* \section ioport_quickstart_use_case_1_setup Setup steps
*
* \subsection ioport_quickstart_use_case_1_setup_code Example code
* \code
#define IN_PORT IOPORT_PORTA
#define OUT_PORT IOPORT_PORTB
#define MASK 0x00000060
ioport_init();
ioport_set_port_dir(IN_PORT, MASK, IOPORT_DIR_INPUT);
ioport_set_port_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT);
\endcode
*
* \subsection ioport_quickstart_basic_setup_flow Workflow
* -# It's useful to give the ports symbolic names:
* - \code
#define IN_PORT IOPORT_PORTA
#define OUT_PORT IOPORT_PORTB
\endcode
* - \note The port names differ between architectures:
* - MEGA_RF, MEGA and XMEGA: There are predefined names for ports: IOPORT_PORTA,
* IOPORT_PORTB ...
* - UC3: Use the index value of the different IO blocks: 0, 1 ...
* - SAM: There are predefined names for ports: IOPORT_PIOA, IOPORT_PIOB
* ...
* -# Also useful to define a mask for the bits to work with:
* - \code #define MASK 0x00000060 \endcode
* -# Initialize the ioport service. This typically enables the IO module if
* needed.
* - \code ioport_init(); \endcode
* -# Set one of the ports as input:
* - \code ioport_set_pin_dir(IN_PORT, MASK, IOPORT_DIR_INPUT); \endcode
* -# Set the other port as output:
* - \code ioport_set_pin_dir(OUT_PORT, MASK, IOPORT_DIR_OUTPUT); \endcode
*
* \section ioport_quickstart_basic_usage Usage steps
*
* \subsection ioport_quickstart_basic_usage_code Example code
* \code
ioport_port_mask_t value;
value = ioport_get_port_level(IN_PORT, MASK);
ioport_set_port_level(OUT_PORT, MASK, value);
\endcode
*
* \subsection ioport_quickstart_basic_usage_flow Workflow
* -# Define a variable for port date storage:
* - \code ioport_port_mask_t value; \endcode
* -# Read out from one port:
* - \code value = ioport_get_port_level(IN_PORT, MASK); \endcode
* -# Put the read data out on the other port:
* - \code ioport_set_port_level(OUT_PORT, MASK, value); \endcode
*/
#ifdef __cplusplus
}
#endif
#endif /* IOPORT_H */