/** | |
* \file | |
* | |
* \brief Common IOPORT service main header file for AVR, UC3 and ARM | |
* architectures. | |
* | |
* Copyright (c) 2012 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 | |
* | |
*/ | |
#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 | |
# 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 */ |