From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- peripherals/pio/pio.c | 382 +++++++++++++++++++++++++++++++++++ peripherals/pio/pio.dir | 50 +++++ peripherals/pio/pio.h | 225 +++++++++++++++++++++ peripherals/pio/pio_it.c | 461 +++++++++++++++++++++++++++++++++++++++++++ peripherals/pio/pio_it.h | 85 ++++++++ peripherals/pio/pio_keypad.c | 147 ++++++++++++++ peripherals/pio/pio_keypad.h | 153 ++++++++++++++ 7 files changed, 1503 insertions(+) create mode 100644 peripherals/pio/pio.c create mode 100644 peripherals/pio/pio.dir create mode 100644 peripherals/pio/pio.h create mode 100644 peripherals/pio/pio_it.c create mode 100644 peripherals/pio/pio_it.h create mode 100644 peripherals/pio/pio_keypad.c create mode 100644 peripherals/pio/pio_keypad.h (limited to 'peripherals/pio') diff --git a/peripherals/pio/pio.c b/peripherals/pio/pio.c new file mode 100644 index 0000000..288e6bb --- /dev/null +++ b/peripherals/pio/pio.c @@ -0,0 +1,382 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "pio.h" +#include + +//------------------------------------------------------------------------------ +// Local Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Configures one or more pin(s) of a PIO controller as being controlled by +/// peripheral A. Optionally, the corresponding internal pull-up(s) can be +/// enabled. +/// \param pio Pointer to a PIO controller. +/// \param mask Bitmask of one or more pin(s) to configure. +/// \param enablePullUp Indicates if the pin(s) internal pull-up shall be +/// configured. +//------------------------------------------------------------------------------ +static void PIO_SetPeripheralA( + AT91S_PIO *pio, + unsigned int mask, + unsigned char enablePullUp) +{ +#if !defined(AT91C_PIOA_ASR) + unsigned int abmr; +#endif + + // Disable interrupts on the pin(s) + pio->PIO_IDR = mask; + + // Enable the pull-up(s) if necessary + if (enablePullUp) { + + pio->PIO_PPUER = mask; + } + else { + + pio->PIO_PPUDR = mask; + } + + // Configure pin +#if defined(AT91C_PIOA_ASR) + pio->PIO_ASR = mask; +#else + abmr = pio->PIO_ABSR; + pio->PIO_ABSR &= (~mask & abmr); +#endif + pio->PIO_PDR = mask; +} + +//------------------------------------------------------------------------------ +/// Configures one or more pin(s) of a PIO controller as being controlled by +/// peripheral B. Optionally, the corresponding internal pull-up(s) can be +/// enabled. +/// \param pio Pointer to a PIO controller. +/// \param mask Bitmask of one or more pin(s) to configure. +/// \param enablePullUp Indicates if the pin(s) internal pull-up shall be +/// configured. +//------------------------------------------------------------------------------ +static void PIO_SetPeripheralB( + AT91S_PIO *pio, + unsigned int mask, + unsigned char enablePullUp) +{ +#if !defined(AT91C_PIOA_BSR) + unsigned int abmr; +#endif + + // Disable interrupts on the pin(s) + pio->PIO_IDR = mask; + + // Enable the pull-up(s) if necessary + if (enablePullUp) { + + pio->PIO_PPUER = mask; + } + else { + + pio->PIO_PPUDR = mask; + } + + // Configure pin +#if defined(AT91C_PIOA_BSR) + pio->PIO_BSR = mask; +#else + abmr = pio->PIO_ABSR; + pio->PIO_ABSR = mask | abmr; +#endif + pio->PIO_PDR = mask; +} + +#if defined(AT91C_PIOA_IFDGSR) //Glitch or Debouncing filter selection supported +//------------------------------------------------------------------------------ +/// Configures Glitch or Debouncing filter for input +/// \param pio Pointer to a PIO controller. +/// \param mask Bitmask for filter selection. +/// each of 32 bit field, 0 is Glitch, 1 is Debouncing +/// \param clkDiv Clock divider if Debouncing select, using the lowest 14 bits +/// common for all PIO line of selecting deboucing filter +//------------------------------------------------------------------------------ +static void PIO_SetFilter( + AT91S_PIO *pio, + unsigned int filterSel, + unsigned int clkDiv) +{ + pio->PIO_DIFSR = filterSel;//set Debouncing, 0 bit field no effect + pio->PIO_SCIFSR = ~filterSel;//set Glitch, 0 bit field no effect + + pio->PIO_SCDR = clkDiv & 0x3FFF;//the lowest 14 bits work +} +#endif + +//------------------------------------------------------------------------------ +/// Configures one or more pin(s) or a PIO controller as inputs. Optionally, +/// the corresponding internal pull-up(s) and glitch filter(s) can be +/// enabled. +/// \param pio Pointer to a PIO controller. +/// \param mask Bitmask indicating which pin(s) to configure as input(s). +/// \param enablePullUp Indicates if the internal pull-up(s) must be enabled. +/// \param enableFilter Indicates if the glitch filter(s) must be enabled. +//------------------------------------------------------------------------------ +static void PIO_SetInput( + AT91S_PIO *pio, + unsigned int mask, + unsigned char enablePullUp, + unsigned char enableFilter) +{ + // Disable interrupts + pio->PIO_IDR = mask; + + // Enable pull-up(s) if necessary + if (enablePullUp) { + + pio->PIO_PPUER = mask; + } + else { + + pio->PIO_PPUDR = mask; + } + + // Enable filter(s) if necessary + if (enableFilter) { + + pio->PIO_IFER = mask; + } + else { + + pio->PIO_IFDR = mask; + } + + // Configure pin as input + pio->PIO_ODR = mask; + pio->PIO_PER = mask; +} + +//------------------------------------------------------------------------------ +/// Configures one or more pin(s) of a PIO controller as outputs, with the +/// given default value. Optionally, the multi-drive feature can be enabled +/// on the pin(s). +/// \param pio Pointer to a PIO controller. +/// \param mask Bitmask indicating which pin(s) to configure. +/// \param defaultValue Default level on the pin(s). +/// \param enableMultiDrive Indicates if the pin(s) shall be configured as +/// open-drain. +/// \param enablePullUp Indicates if the pin shall have its pull-up activated. +//------------------------------------------------------------------------------ +static void PIO_SetOutput( + AT91S_PIO *pio, + unsigned int mask, + unsigned char defaultValue, + unsigned char enableMultiDrive, + unsigned char enablePullUp) +{ + // Disable interrupts + pio->PIO_IDR = mask; + + // Enable pull-up(s) if necessary + if (enablePullUp) { + + pio->PIO_PPUER = mask; + } + else { + + pio->PIO_PPUDR = mask; + } + + // Enable multi-drive if necessary + if (enableMultiDrive) { + + pio->PIO_MDER = mask; + } + else { + + pio->PIO_MDDR = mask; + } + + // Set default value + if (defaultValue) { + + pio->PIO_SODR = mask; + } + else { + + pio->PIO_CODR = mask; + } + + // Configure pin(s) as output(s) + pio->PIO_OER = mask; + pio->PIO_PER = mask; +} + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Configures a list of Pin instances, each of which can either hold a single +/// pin or a group of pins, depending on the mask value; all pins are configured +/// by this function. The size of the array must also be provided and is easily +/// computed using PIO_LISTSIZE whenever its length is not known in advance. +/// \param list Pointer to a list of Pin instances. +/// \param size Size of the Pin list (calculated using PIO_LISTSIZE). +/// \return 1 if the pins have been configured properly; otherwise 0. +//------------------------------------------------------------------------------ +unsigned char PIO_Configure(const Pin *list, unsigned int size) +{ + // Configure pins + while (size > 0) { + + switch (list->type) { + + case PIO_PERIPH_A: + PIO_SetPeripheralA(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_PERIPH_B: + PIO_SetPeripheralB(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + case PIO_INPUT: + AT91C_BASE_PMC->PMC_PCER = 1 << list->id; + PIO_SetInput(list->pio, + list->mask, + (list->attribute & PIO_PULLUP) ? 1 : 0, + (list->attribute & PIO_DEGLITCH)? 1 : 0); + + #if defined(AT91C_PIOA_IFDGSR) //PIO3 with Glitch or Debouncing selection + //if glitch input filter enabled, set it + if(list->attribute & PIO_DEGLITCH)//Glitch input filter enabled + PIO_SetFilter(list->pio, + list->inFilter.filterSel, + list->inFilter.clkDivider); + #endif + break; + + case PIO_OUTPUT_0: + case PIO_OUTPUT_1: + PIO_SetOutput(list->pio, + list->mask, + (list->type == PIO_OUTPUT_1), + (list->attribute & PIO_OPENDRAIN) ? 1 : 0, + (list->attribute & PIO_PULLUP) ? 1 : 0); + break; + + default: return 0; + } + + list++; + size--; + } + + return 1; +} + +//------------------------------------------------------------------------------ +/// Sets a high output level on all the PIOs defined in the given Pin instance. +/// This has no immediate effects on PIOs that are not output, but the PIO +/// controller will memorize the value they are changed to outputs. +/// \param pin Pointer to a Pin instance describing one or more pins. +//------------------------------------------------------------------------------ +void PIO_Set(const Pin *pin) +{ + pin->pio->PIO_SODR = pin->mask; +} + +//------------------------------------------------------------------------------ +/// Sets a low output level on all the PIOs defined in the given Pin instance. +/// This has no immediate effects on PIOs that are not output, but the PIO +/// controller will memorize the value they are changed to outputs. +/// \param pin Pointer to a Pin instance describing one or more pins. +//------------------------------------------------------------------------------ +void PIO_Clear(const Pin *pin) +{ + pin->pio->PIO_CODR = pin->mask; +} + +//------------------------------------------------------------------------------ +/// Returns 1 if one or more PIO of the given Pin instance currently have a high +/// level; otherwise returns 0. This method returns the actual value that is +/// being read on the pin. To return the supposed output value of a pin, use +/// PIO_GetOutputDataStatus() instead. +/// \param pin Pointer to a Pin instance describing one or more pins. +/// \return 1 if the Pin instance contains at least one PIO that currently has +/// a high level; otherwise 0. +//------------------------------------------------------------------------------ +unsigned char PIO_Get(const Pin *pin) +{ + unsigned int reg; + if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) { + + reg = pin->pio->PIO_ODSR; + } + else { + + reg = pin->pio->PIO_PDSR; + } + + if ((reg & pin->mask) == 0) { + + return 0; + } + else { + + return 1; + } +} + + +//------------------------------------------------------------------------------ +/// Returns 1 if one or more PIO of the given Pin are configured to output a +/// high level (even if they are not output). +/// To get the actual value of the pin, use PIO_Get() instead. +/// \param pin Pointer to a Pin instance describing one or more pins. +/// \return 1 if the Pin instance contains at least one PIO that is configured +/// to output a high level; otherwise 0. +//------------------------------------------------------------------------------ +unsigned char PIO_GetOutputDataStatus(const Pin *pin) +{ + if ((pin->pio->PIO_ODSR & pin->mask) == 0) { + + return 0; + } + else { + + return 1; + } +} diff --git a/peripherals/pio/pio.dir b/peripherals/pio/pio.dir new file mode 100644 index 0000000..9496672 --- /dev/null +++ b/peripherals/pio/pio.dir @@ -0,0 +1,50 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \dir +/// +/// !!!Purpose +/// +/// This directory contains an API for configuring the Peripheral Input/Output +/// (PIO) controllers. +/// +/// !!!Contents +/// +/// The code is separated into two components: +/// - pio.c contains code for PIO initialisation, as well as set/clear/get +/// methods that can be used with user-controlled pins. +/// - pio_it.h provides a convenient interface for configuring, enabling or +/// disabling interrupts on one pin or a group of pins. +/// +/// The reasoning behing this division is that pio_it.c requires the aic +/// peripheral, which generates useless includes for project which do not use +/// PIO interrupts. +//------------------------------------------------------------------------------ + diff --git a/peripherals/pio/pio.h b/peripherals/pio/pio.h new file mode 100644 index 0000000..2c78d73 --- /dev/null +++ b/peripherals/pio/pio.h @@ -0,0 +1,225 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// This file provides a basic API for PIO configuration and usage of +/// user-controlled pins. Please refer to the board.h file for a list of +/// available pin definitions. +/// +/// !!!Usage +/// +/// -# Define a constant pin description array such as the following one, using +/// the existing definitions provided by the board.h file if possible: +/// \code +/// const Pin pPins[] = {PIN_USART0_TXD, PIN_USART0_RXD}; +/// \endcode +/// Alternatively, it is possible to add new pins by provided the full Pin +/// structure: +/// \code +/// // Pin instance to configure PA10 & PA11 as inputs with the internal +/// // pull-up enabled. +/// const Pin pPins = { +/// (1 << 10) | (1 << 11), +/// AT91C_BASE_PIOA, +/// AT91C_ID_PIOA, +/// PIO_INPUT, +/// PIO_PULLUP +/// }; +/// \endcode +/// -# Configure a pin array by calling PIO_Configure() with a pointer to the +/// array and its size (which is computed using the PIO_LISTSIZE macro). +/// -# Change and get the value of a user-controlled pin using the PIO_Set, +/// PIO_Clear and PIO_Get methods. +/// -# Get the level being currently output by a user-controlled pin configured +/// as an output using PIO_GetOutputDataStatus(). +//------------------------------------------------------------------------------ + +#ifndef PIO_H +#define PIO_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include + +//------------------------------------------------------------------------------ +// Global Definitions +//------------------------------------------------------------------------------ + +/// The pin is controlled by the associated signal of peripheral A. +#define PIO_PERIPH_A 0 +/// The pin is controlled by the associated signal of peripheral B. +#define PIO_PERIPH_B 1 +/// The pin is an input. +#define PIO_INPUT 2 +/// The pin is an output and has a default level of 0. +#define PIO_OUTPUT_0 3 +/// The pin is an output and has a default level of 1. +#define PIO_OUTPUT_1 4 + +/// Default pin configuration (no attribute). +#define PIO_DEFAULT (0 << 0) +/// The internal pin pull-up is active. +#define PIO_PULLUP (1 << 0) +/// The internal glitch filter is active. +#define PIO_DEGLITCH (1 << 1) +/// The pin is open-drain. +#define PIO_OPENDRAIN (1 << 2) + +//------------------------------------------------------------------------------ +// Global Macros +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Calculates the size of an array of Pin instances. The array must be defined +/// locally (i.e. not a pointer), otherwise the computation will not be correct. +/// \param pPins Local array of Pin instances. +/// \return Number of elements in array. +//------------------------------------------------------------------------------ +#define PIO_LISTSIZE(pPins) (sizeof(pPins) / sizeof(Pin)) + +//------------------------------------------------------------------------------ +// Global Types +//------------------------------------------------------------------------------ +typedef struct _ExtIntMode { + ///indicate which pin to enable/disable additional Interrupt mode + ///each of 32 bit field represents one PIO line. + unsigned int itMask; + ///select Edge or level interrupt detection source + ///each of 32 bit field represents one PIO line, 0 is Edge, 1 is Level + unsigned int edgeLvlSel; + ///select rising/high or falling/low detection event + ///each of 32 bit field represents one PIO line: + ///0 is Falling Edge detection event (if selected Edge interrupt + /// detection source, or Low Level detection (if selected + /// Level interrupt detection source; + ///1 is Rising Edge detection(if selected Edge interrupt + /// source, or Low Level detection event(if selected Level + /// interrupt detection source. + unsigned int lowFallOrRiseHighSel; + +} ExtIntMode; + +typedef struct _GlitchDeBounceFilter { + ///Select Glitch/Debounce filtering for PIO input + ///each of 32 bit field represents one PIO line + ///0 is Glitch, 1 is Debouncing + unsigned int filterSel; + ///slow clock divider selection for Debouncing filter + unsigned int clkDivider:14; + +} GlitchDebounceFilter; + +//------------------------------------------------------------------------------ +/// Describes the type and attribute of one PIO pin or a group of similar pins. +/// The #type# field can have the following values: +/// - PIO_PERIPH_A +/// - PIO_PERIPH_B +/// - PIO_OUTPUT_0 +/// - PIO_OUTPUT_1 +/// - PIO_INPUT +/// +/// The #attribute# field is a bitmask that can either be set to PIO_DEFAULt, +/// or combine (using bitwise OR '|') any number of the following constants: +/// - PIO_PULLUP +/// - PIO_DEGLITCH +/// - PIO_OPENDRAIN +//------------------------------------------------------------------------------ +typedef struct { + + /// Bitmask indicating which pin(s) to configure. + unsigned int mask; + /// Pointer to the PIO controller which has the pin(s). + AT91S_PIO *pio; + /// Peripheral ID of the PIO controller which has the pin(s). + unsigned char id; + /// Pin type. + unsigned char type; + /// Pin attribute. + unsigned char attribute; +#if defined(AT91C_PIOA_AIMMR) + ///Additional Interrupt Mode + ExtIntMode itMode; +#endif + +#if defined(AT91C_PIOA_IFDGSR) + ///Glitch/Debouncing filter + GlitchDebounceFilter inFilter; +#endif + +} Pin; + +//------------------------------------------------------------------------------ +// Global Access Macros +//------------------------------------------------------------------------------ + +//Get Glitch input filter enable/disable status +#define PIO_GetIFSR(pPin) ((pPin)->pio->PIO_IFSR) + +//Get Glitch/Deboucing selection status +#define PIO_GetIFDGSR(pPin) ((pPin)->pio->PIO_IFDGSR) + +//Get Additional PIO interrupt mode mask status +#define PIO_GetAIMMR(pPin) ((pPin)->pio->PIO_AIMMR) + +//Get Interrupt status +#define PIO_GetISR(pPin) ((pPin)->pio->PIO_ISR) + +//Get Edge or Level selection status +#define PIO_GetELSR(pPin) ((pPin)->pio->PIO_ELSR) + +//Get Fall/Rise or Low/High selection status +#define PIO_GetFRLHSR(pPin) ((pPin)->pio->PIO_FRLHSR) + +//Get PIO Lock Status +#define PIO_GetLockStatus(pPin) ((pPin)->pio->PIO_LOCKSR) + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +extern unsigned char PIO_Configure(const Pin *list, unsigned int size); + +extern void PIO_Set(const Pin *pin); + +extern void PIO_Clear(const Pin *pin); + +extern unsigned char PIO_Get(const Pin *pin); + +//extern unsigned int PIO_GetISR(const Pin *pin); + +extern unsigned char PIO_GetOutputDataStatus(const Pin *pin); + +#endif //#ifndef PIO_H + diff --git a/peripherals/pio/pio_it.c b/peripherals/pio/pio_it.c new file mode 100644 index 0000000..cdd8a0b --- /dev/null +++ b/peripherals/pio/pio_it.c @@ -0,0 +1,461 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +/// Disable traces for this file +#undef TRACE_LEVEL +#define TRACE_LEVEL 0 + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "pio_it.h" +#include "pio.h" +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Local definitions +//------------------------------------------------------------------------------ + +/// \exclude +/// Maximum number of interrupt sources that can be defined. This +/// constant can be increased, but the current value is the smallest possible +/// that will be compatible with all existing projects. +#define MAX_INTERRUPT_SOURCES 7 + +//------------------------------------------------------------------------------ +// Local types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// \exclude +/// Describes a PIO interrupt source, including the PIO instance triggering the +/// interrupt and the associated interrupt handler. +//------------------------------------------------------------------------------ +typedef struct { + + /// Pointer to the source pin instance. + const Pin *pPin; + + /// Interrupt handler. + void (*handler)(const Pin *); + +} InterruptSource; + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// List of interrupt sources. +static InterruptSource pSources[MAX_INTERRUPT_SOURCES]; + +/// Number of currently defined interrupt sources. +static unsigned int numSources; + +//------------------------------------------------------------------------------ +// Local functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Handles all interrupts on the given PIO controller. +/// \param id PIO controller ID. +/// \param pPio PIO controller base address. +//------------------------------------------------------------------------------ +static void PioInterruptHandler(unsigned int id, AT91S_PIO *pPio) +{ + unsigned int status; + unsigned int i; + + // Read PIO controller status + status = pPio->PIO_ISR; + status &= pPio->PIO_IMR; + + // Check pending events + if (status != 0) { + + TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id); + + // Find triggering source + i = 0; + while (status != 0) { + + // There cannot be an unconfigured source enabled. + SANITY_CHECK(i < numSources); + + // Source is configured on the same controller + if (pSources[i].pPin->id == id) { + + // Source has PIOs whose statuses have changed + if ((status & pSources[i].pPin->mask) != 0) { + + TRACE_DEBUG("Interrupt source #%d triggered\n\r", i); + + pSources[i].handler(pSources[i].pPin); + status &= ~(pSources[i].pPin->mask); + } + } + i++; + } + } +} + +//------------------------------------------------------------------------------ +/// Generic PIO interrupt handler. Single entry point for interrupts coming +/// from any PIO controller (PIO A, B, C ...). Dispatches the interrupt to +/// the user-configured handlers. +//------------------------------------------------------------------------------ +void PIO_IT_InterruptHandler(void) +{ +#if defined(AT91C_ID_PIOA) + // Treat PIOA interrupts + PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA); +#endif + +#if defined(AT91C_ID_PIOB) + // Treat PIOB interrupts + PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB); +#endif + +#if defined(AT91C_ID_PIOC) + // Treat PIOC interrupts + PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC); +#endif + +#if defined(AT91C_ID_PIOD) + // Treat PIOD interrupts + PioInterruptHandler(AT91C_ID_PIOD, AT91C_BASE_PIOD); +#endif + +#if defined(AT91C_ID_PIOE) + // Treat PIOE interrupts + PioInterruptHandler(AT91C_ID_PIOE, AT91C_BASE_PIOE); +#endif + +#if defined(AT91C_ID_PIOABCD) + // Treat PIOABCD interrupts + #if !defined(AT91C_ID_PIOA) + PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOA); + #endif + #if !defined(AT91C_ID_PIOB) + PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOB); + #endif + #if !defined(AT91C_ID_PIOC) + PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOC); + #endif + #if !defined(AT91C_ID_PIOD) + PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOD); + #endif +#endif + +#if defined(AT91C_ID_PIOABCDE) + // Treat PIOABCDE interrupts + #if !defined(AT91C_ID_PIOA) + PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOA); + #endif + #if !defined(AT91C_ID_PIOB) + PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOB); + #endif + #if !defined(AT91C_ID_PIOC) + PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOC); + #endif + #if !defined(AT91C_ID_PIOD) + PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOD); + #endif + #if !defined(AT91C_ID_PIOE) + PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOE); + #endif +#endif + +#if defined(AT91C_ID_PIOCDE) + // Treat PIOCDE interrupts + #if !defined(AT91C_ID_PIOC) + PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOC); + #endif + #if !defined(AT91C_ID_PIOD) + PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOD); + #endif + #if !defined(AT91C_ID_PIOE) + PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOE); + #endif +#endif +} + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the PIO interrupt management logic. The desired priority of PIO +/// interrupts must be provided. Calling this function multiple times result in +/// the reset of currently configured interrupts. +/// \param priority PIO controller interrupts priority. +//------------------------------------------------------------------------------ +void PIO_InitializeInterrupts(unsigned int priority) +{ + TRACE_DEBUG("PIO_Initialize()\n\r"); + +// SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0); + + // Reset sources + numSources = 0; + +#ifdef AT91C_ID_PIOA + // Configure PIO interrupt sources + TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA; + AT91C_BASE_PIOA->PIO_ISR; + AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOA, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOA); +#endif + +#ifdef AT91C_ID_PIOB + TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB; + AT91C_BASE_PIOB->PIO_ISR; + AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOB, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOB); +#endif + +#ifdef AT91C_ID_PIOC + TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOC; + AT91C_BASE_PIOC->PIO_ISR; + AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOC, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOC); +#endif + +#ifdef AT91C_ID_PIOD + TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOD; + AT91C_BASE_PIOC->PIO_ISR; + AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOD, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOD); +#endif + +#ifdef AT91C_ID_PIOE + TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOE; + AT91C_BASE_PIOC->PIO_ISR; + AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOE, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOE); +#endif + +#if defined(AT91C_ID_PIOABCD) + // Treat PIOABCD interrupts + #if !defined(AT91C_ID_PIOA) \ + && !defined(AT91C_ID_PIOB) \ + && !defined(AT91C_ID_PIOC) \ + && !defined(AT91C_ID_PIOD) + + TRACE_DEBUG("PIO_Initialize: Configuring PIOABCD\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCD; + AT91C_BASE_PIOA->PIO_ISR; + AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOABCD, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOABCD); + #endif +#endif + +#if defined(AT91C_ID_PIOABCDE) + // Treat PIOABCDE interrupts + #if !defined(AT91C_ID_PIOA) \ + && !defined(AT91C_ID_PIOB) \ + && !defined(AT91C_ID_PIOC) \ + && !defined(AT91C_ID_PIOD) \ + && !defined(AT91C_ID_PIOE) + + TRACE_DEBUG("PIO_Initialize: Configuring PIOABCDE\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCDE; + AT91C_BASE_PIOA->PIO_ISR; + AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOABCDE, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOABCDE); + #endif +#endif + +#if defined(AT91C_ID_PIOCDE) + // Treat PIOCDE interrupts + #if !defined(AT91C_ID_PIOC) \ + && !defined(AT91C_ID_PIOD) \ + && !defined(AT91C_ID_PIOE) + + TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r"); + AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOCDE; + AT91C_BASE_PIOC->PIO_ISR; + AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF; + IRQ_ConfigureIT(AT91C_ID_PIOCDE, priority, PIO_IT_InterruptHandler); + IRQ_EnableIT(AT91C_ID_PIOCDE); + #endif +#endif +} + +//------------------------------------------------------------------------------ +/// Configures a PIO or a group of PIO to generate an interrupt on status +/// change. The provided interrupt handler will be called with the triggering +/// pin as its parameter (enabling different pin instances to share the same +/// handler). +/// \param pPin Pointer to a Pin instance. +/// \param handler Interrupt handler function pointer. +//------------------------------------------------------------------------------ +void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *)) +{ + InterruptSource *pSource; + + TRACE_DEBUG("PIO_ConfigureIt()\n\r"); + + SANITY_CHECK(pPin); + ASSERT(numSources < MAX_INTERRUPT_SOURCES, + "-F- PIO_ConfigureIt: Increase MAX_INTERRUPT_SOURCES\n\r"); + + // Define new source + TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", numSources); + + pSource = &(pSources[numSources]); + pSource->pPin = pPin; + pSource->handler = handler; + numSources++; +} + +//------------------------------------------------------------------------------ +/// Enables the given interrupt source if it has been configured. The status +/// register of the corresponding PIO controller is cleared prior to enabling +/// the interrupt. +/// \param pPin Interrupt source to enable. +//------------------------------------------------------------------------------ +void PIO_EnableIt(const Pin *pPin) +{ + TRACE_DEBUG("PIO_EnableIt()\n\r"); + + SANITY_CHECK(pPin); + +#ifndef NOASSERT + unsigned int i = 0; + unsigned char found = 0; + while ((i < numSources) && !found) { + + if (pSources[i].pPin == pPin) { + + found = 1; + } + i++; + } + ASSERT(found, "-F- PIO_EnableIt: Interrupt source has not been configured\n\r"); +#endif + + pPin->pio->PIO_ISR; + pPin->pio->PIO_IER = pPin->mask; + + +#if defined(AT91C_PIOA_AIMMR) + //PIO3 with additional interrupt support + //configure additional interrupt mode registers + if(pPin->mask&pPin->itMode.itMask) { + + //enable additional interrupt mode + pPin->pio->PIO_AIMER = pPin->itMode.itMask; + + if(pPin->mask&pPin->itMode.edgeLvlSel) + //if bit field of selected pin is 1, set as Level detection source + pPin->pio->PIO_LSR = pPin->itMode.edgeLvlSel; + else + //if bit field of selected pin is 0, set as Edge detection source + pPin->pio->PIO_ESR = ~(pPin->itMode.edgeLvlSel); + + if(pPin->mask&pPin->itMode.lowFallOrRiseHighSel) + //if bit field of selected pin is 1, set as Rising Edge/High level detection event + pPin->pio->PIO_REHLSR = pPin->itMode.lowFallOrRiseHighSel; + else + //if bit field of selected pin is 0, set as Falling Edge/Low level detection event + pPin->pio->PIO_FELLSR = ~(pPin->itMode.lowFallOrRiseHighSel); + } + +#endif +} + +//------------------------------------------------------------------------------ +/// Disables a given interrupt source, with no added side effects. +/// \param pPin Interrupt source to disable. +//------------------------------------------------------------------------------ +void PIO_DisableIt(const Pin *pPin) +{ + SANITY_CHECK(pPin); + + TRACE_DEBUG("PIO_DisableIt()\n\r"); + + pPin->pio->PIO_IDR = pPin->mask; +#if defined(AT91C_PIOA_AIMMR) + if(pPin->mask & pPin->itMode.itMask) + //disable additional interrupt mode + pPin->pio->PIO_AIMDR = pPin->mask & pPin->itMode.itMask; +#endif + +} + +#if defined(cortexm3) +//------------------------------------------------------------------------------ +/// Override cortex-m3's default PIOA irq handler +//------------------------------------------------------------------------------ +void PIOA_IrqHandler(void) +{ + #if defined(AT91C_ID_PIOA) + // Treat PIOA interrupts + PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA); + #endif +} + +//------------------------------------------------------------------------------ +/// Override cortex-m3's default PIOB irq handler +//------------------------------------------------------------------------------ +void PIOB_IrqHandler(void) +{ + #if defined(AT91C_ID_PIOB) + // Treat PIOA interrupts + PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB); + #endif +} + +//------------------------------------------------------------------------------ +/// Override cortex-m3's default PIOC irq handler +//------------------------------------------------------------------------------ +void PIOC_IrqHandler(void) +{ + #if defined(AT91C_ID_PIOC) + // Treat PIOA interrupts + PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC); + #endif +} +#endif diff --git a/peripherals/pio/pio_it.h b/peripherals/pio/pio_it.h new file mode 100644 index 0000000..782e911 --- /dev/null +++ b/peripherals/pio/pio_it.h @@ -0,0 +1,85 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !!!Purpose +/// +/// Configuration and handling of interrupts on PIO status changes. The API +/// provided here have several advantages over the traditional PIO interrupt +/// configuration approach: +/// - It is highly portable +/// - It automatically demultiplexes interrupts when multiples pins have been +/// configured on a single PIO controller +/// - It allows a group of pins to share the same interrupt +/// +/// However, it also has several minor drawbacks that may prevent from using it +/// in particular applications: +/// - It enables the clocks of all PIO controllers +/// - PIO controllers all share the same interrupt handler, which does the +/// demultiplexing and can be slower than direct configuration +/// - It reserves space for a fixed number of interrupts, which can be +/// increased by modifying the appropriate constant in pio_it.c. +/// +/// !!!Usage +/// +/// -# Initialize the PIO interrupt mechanism using PIO_InitializeInterrupts() +/// with the desired priority (0 ... 7). +/// -# Configure a status change interrupt on one or more pin(s) with +/// PIO_ConfigureIt(). +/// -# Enable & disable interrupts on pins using PIO_EnableIt() and +/// PIO_DisableIt(). +//------------------------------------------------------------------------------ + +#ifndef PIO_IT_H +#define PIO_IT_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "pio.h" + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +extern void PIO_InitializeInterrupts(unsigned int priority); + +extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *)); + +extern void PIO_EnableIt(const Pin *pPin); + +extern void PIO_DisableIt(const Pin *pPin); + +extern void PIO_IT_InterruptHandler(void); + +#endif //#ifndef PIO_IT_H + diff --git a/peripherals/pio/pio_keypad.c b/peripherals/pio/pio_keypad.c new file mode 100644 index 0000000..e617289 --- /dev/null +++ b/peripherals/pio/pio_keypad.c @@ -0,0 +1,147 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include +#include "pio.h" +#include "pio_keypad.h" + + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Configures keypad controller +/// \param pPIO Pointer to a PIO instance +/// \param config Configuration data for given pin,see head file for detail +//------------------------------------------------------------------------------ +void PIO_KeyPadConfig(AT91S_PIO *pPIO, KeyPadConfig *config) +{ + //enable/disable keypad controller + pPIO->PIO_KER = config->enable; + + //if enable, set keypad matrix and debouncing + if(config->enable == TRUE) { + //set key matrix + pPIO->PIO_KRCR = (config->row | config->col<<8) ; + + //set debouncing + pPIO->PIO_KDR = config->debouncing; + + } +} + + +//------------------------------------------------------------------------------ +/// Get Key Press/Release status +/// \param pPIO Pointer to a PIO instance +/// \param event Pointer to a instance of KeyEvent for storing keypad status +//------------------------------------------------------------------------------ +void PIO_GetKeyStatus(AT91S_PIO *pPIO, KeyEvent *event) +{ + int i,j; + + //get key press event + event->kdEvent.press = (pPIO->KSR&0x1)?TRUE:FALSE; + event->kdEvent.keyPressNum = (pPIO->KSR>>8)&0x3; + j=event->kdEvent.keyPressNum+1; + for(i=0; ikdEvent.preKeyMatrix[i].row = ((pPIO->KKPR) >> (8*i)) & 0x7; + event->kdEvent.preKeyMatrix[i].col = ((pPIO->KKPR) >> (8*i+4)) & 0x7; + } + + //get key release event + event->kuEvent.release = ((pPIO->KSR>>1) & 0x1)?TRUE:FALSE; + event->kuEvent.keyRelNum = (pPIO->KSR>>16)&0x3; + j=event->kdEvent.keyPressNum+1; + for(i=0;ikuEvent.relKeyMatrix[i].row = ((pPIO->KKRR) >> (8*i)) & 0x7; + event->kuEvent.relKeyMatrix[i].col = ((pPIO->KKRR) >> (8*i+4)) & 0x7; + } + +} + + +//------------------------------------------------------------------------------ +/// Enable keypad interrupt as Key Press Interrupt or Key Release Interrupt or both +/// \param pPIO Pointer to a PIO instance +/// \param mode Select key interrupt mode to enable, +/// 0x1 Key Press Interrupt +/// 0x2 Key Release Interrupt +/// 0x3 both of two type +//------------------------------------------------------------------------------ +void PIO_KeypadEnableIt(AT91S_PIO *pPIO, unsigned int mode) +{ + switch(mode){ + case 1:PIO_KeyPadEnableKPIt(pPIO); + break; + + case 2:PIO_KeyPadEnableKRIt(pPIO); + break; + + case 3:PIO_KeyPadEnableKPIt(pPIO); + PIO_KeyPadEnableKRIt(pPIO); + break; + + default:break; + } + +} + +//------------------------------------------------------------------------------ +/// Disable Key Press Interrupt or Key Release Interrupt or both of them +/// \param pPIO Pointer to a PIO instance +/// \param mode Select key interrupt mode to disable, +/// 0x1 Key Press Interrupt +/// 0x2 Key Release Interrupt +/// 0x3 both of two type +//------------------------------------------------------------------------------ +void PIO_KeypadDisableIt(AT91S_PIO *pPIO, unsigned int mode) +{ + switch(mode){ + case 1:PIO_KeyPadDisableKPIt(pPIO); + break; + + case 2:PIO_KeyPadDisableKRIt(pPIO); + break; + + case 3:PIO_KeyPadDisableKPIt(pPIO); + PIO_KeyPadDisableKRIt(pPIO); + break; + + default:break; + } + +} + + diff --git a/peripherals/pio/pio_keypad.h b/peripherals/pio/pio_keypad.h new file mode 100644 index 0000000..166f066 --- /dev/null +++ b/peripherals/pio/pio_keypad.h @@ -0,0 +1,153 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: 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 + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef PIO_KEYPAD_H +#define PIO_KEYPAD_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include + +//------------------------------------------------------------------------------ +// Global Definitions +//------------------------------------------------------------------------------ + + + + +//------------------------------------------------------------------------------ +// Global Macros +//------------------------------------------------------------------------------ +//enable keypad press interrupt +#define PIO_KeyPadEnableKPIt(pPIO) ((pPIO)->KIER = 1<<0) + +//enable keypad release interrupt +#define PIO_KeyPadEnableKRIt(pPIO) ((pPIO)->KIER = 1<<1) + +//disable keypad press interrupt +#define PIO_KeyPadDisableKPIt(pPIO) ((pPIO)->KIDR = 1<<0) + +//disable keypad release interrupt +#define PIO_KeyPadDisableKRIt(pPIO) ((pPIO)->KIDR = 1<<1) + +//enable keypad controller interrupt +#define PIO_KeyPadEnableIt(pPIO, mode) {switch(mode):\ + case 1:PIO_KeyPadEnableKPIt(pPIO);break;\ + case 2:PIO_KeyPadEnableKRIt(pPIO);break;\ + case 3:PIO_KeyPadEnableKPIt(pPIO);\ + PIO_KeyPadEnableKRIt(pPIO);break;\ + default:break;\ + } + +//disable keypad controller interrupt +#define PIO_KeyPadDisableIt(pPIO, mode) {switch(mode):\ + case 1:PIO_KeyPadDisableKPIt(pPIO);break;\ + case 2:PIO_KeyPadDisableKRIt(pPIO);break;\ + case 3:PIO_KeyPadDisableKPIt(pPIO);\ + PIO_KeyPadDisableKRIt(pPIO);break;\ + default:break;\ + } + +//get keypad controller interrupt mask +#define PIO_KeyPadGetItMask(pPIO) ((pPIO)->PIO_KIMR) + + +//------------------------------------------------------------------------------ +/// Calculates the size of an array of Pin instances. The array must be defined +/// locally (i.e. not a pointer), otherwise the computation will not be correct. +/// \param pPins Local array of Pin instances. +/// \return Number of elements in array. +//------------------------------------------------------------------------------ +#define PIO_LISTSIZE(pPins) (sizeof(pPins) / sizeof(Pin)) + +//------------------------------------------------------------------------------ +// Global Types +//------------------------------------------------------------------------------ +typedef enum { + FALSE, + TRUE +} bool; + +typedef struct _KeyPadConfig { + bool enable;//keypad controller enable or disable + unsigned char col:3;//config column size + unsigned char row:3;//config row size + unsigned int debouncing;//config debouncing +} KeyPadConfig; + + +typedef struct _KeyColRow { + unsigned char row:3; + unsigned char col:3; +} KeyColRow; + + +typedef struct _KeyDownEvent { + bool press;//at least 1 pressed key detected, or 0 + unsigned char keyPressNum;//simultaneously pressed key number + KeyColRow preKeyMatrix[4];//pressed key matrix +} KeyDownEvent; + + + +typedef struct _KeyUpEvent { + bool release;//at least 1 released key detected, or 0 + unsigned char keyRelNum;//simultaneously released key number + KeyColRow relKeyMatrix[4];//released key matrix +} KeyUpEvent; + + + +typedef struct _KeyEvent { + KeyDownEvent kdEvent; + KeyUpEvent kuEvent; +} KeyEvent; + +//------------------------------------------------------------------------------ +// Global Access Macros +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Global Functions +//------------------------------------------------------------------------------ + +void PIO_KeyPadConfig(AT91S_PIO *pPIO, KeyPadConfig *config); + +void PIO_GetKeyStatus(AT91S_PIO *pPIO, KeyEvent *event); + +void PIO_KeypadEnableIt(AT91S_PIO *pio, unsigned int mode); + +void PIO_KeypadDisableIt(AT91S_PIO *pio, unsigned int mode); + + +#endif //#ifndef PIO_KEYPAD_H + -- cgit v1.2.3