/******************************************************************************
 * The MIT License
 *
 * Copyright (c) 2010 Perry Hung.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *****************************************************************************/


/**
 *  @file exti.h
 *
 *  @brief External interrupt control prototypes and defines
 */

#ifndef _EXTI_H_
#define _EXTI_H_

/* Notes:
 *
 * To generate the interrupt, the interrupt line should be configured
 * and enabled. This is done by programming the two trigger registers
 * with the desired edge detection and by enabling the interrupt
 * request by writing a '1' to the corresponding bit in the interrupt
 * mask register.  When the selected edge occurs on the external
 * interrupt line, an interrupt request is generated. The pending bit
 * corresponding to the interrupt line is also set.  This request is
 * reset by writing a '1' in the pending register.
 *
 * Hardware interrupt selection:
 *
 * To configure the 20 lines as interrupt sources, use the following
 * procedure:
 *
 * 1) Configure AFIO_EXTIICR[y] to select the source input for EXTIx
 *    external interrupt
 * 2) Configure the mask bits of the 20 interrupt lines (EXTI_IMR)
 * 3) Configure the trigger selection bits of the interrupt lines
 *    (EXTI_RTSR and EXTI_FTSR)
 * 4) Configure the enable and mask bits that control the NVIC_IRQ
 *    channel mapped to the External
 *
 * Interrupt Controller (EXTI) so that an inerrupt coming from one of
 * the 20 lines can be correctly acknowledged.
 *
 * AFIO clock must be on.
 *
 * RM0008, page 107: "PD0, PD1 cannot be used for external
 * interrupt/event generation on 36, 48, 64-bin packages."
 *
 * ----------------------------------------------------------------------------
 * Pin to EXTI Line Mappings:
 * EXTI0          EXTI1          EXTI2           EXTI3           EXTI4
 * --------------------------------------------------------------------------
 * D2/PA0         D3/PA1         D1/PA2          D0/A6/PA3       D10/A10/PA4
 * D26/EXT7/PB0   D27/EXT8/PB1   D16/A2/PC2      D17/A3/PC3      D18/A4/PC4
 * D14/A0/PC0     D15/PC1        D25/EXT5/PD2
 *
 * EXTI5          EXTI6          EXTI7           EXTI8           EXTI9
 * ----------------------------------------------------------------------------
 * D13/A13/PA5    D12/A12/PA6    D11/A11/PA7     D6/PA8          D7/PA9
 * D4/PB5         D5/PB6         D9/PB7          D38/PB8         D23/EXT4/PB9
 * D19/A5/PC5     D34/EXTI15/PC6 D35/EXT16/PC7   D36/PC8         D37/EXT18/PC9
 *
 * EXTI10         EXTI11         EXTI12          EXTI13          EXTI14
 * ----------------------------------------------------------------------------
 * D8/PA10        D29/EXT10/PB11 D30/EXTI1/PB12  D31/EXTI12/PB13 D32/EXT13/PB14
 * D28/PB10                                      D20/EXTI1/PC13  D21/EXT2/PC14
 * D25/PC10
 *
 * EXTI15
 * ----------------------------------------------------------------------------
 * D33/EXTI14/PB15
 * D22/EXT3/PC15
 *
 *
 * The 16 EXTI interrupts are mapped to 7 interrupt handlers.
 *
 * EXTI Lines to Interrupt Mapping:
 * EXTI0 -> EXTI0
 * EXTI1 -> EXTI1
 * EXTI2 -> EXTI2
 * EXTI3 -> EXTI3
 * EXTI4 -> EXTI4
 * EXTI[5-9] -> EXT9_5
 * EXTI[10-15] -> EXT15_10
 *
 * */

#define NR_EXTI_MODES             3
#define NR_EXTI_CHANNELS         16
#define NR_EXTI_PORTS            NR_GPIO_PORTS       // board specific

#define EXTI_RISING                     0
#define EXTI_FALLING                    1
#define EXTI_RISING_FALLING             2

#define EXTI_IMR        0x40010400        // Interrupt mask register
#define EXTI_EMR        (EXTI_IMR + 0x04) // Event mask register
#define EXTI_RTSR       (EXTI_IMR + 0x08) // Rising trigger selection register
#define EXTI_FTSR       (EXTI_IMR + 0x0C) // Falling trigger selection register
#define EXTI_SWIER      (EXTI_IMR + 0x10) // Software interrupt event register
#define EXTI_PR         (EXTI_IMR + 0x14) // Pending register

#define AFIO_EVCR       0x40010000
#define AFIO_EXTICR1    (AFIO_EVCR + 0x08)
#define AFIO_EXTICR2    (AFIO_EVCR + 0x0C)
#define AFIO_EXTICR3    (AFIO_EVCR + 0x10)
#define AFIO_EXTICR4    (AFIO_EVCR + 0x14)

#define EXTI0  0
#define EXTI1  1
#define EXTI2  2
#define EXTI3  3
#define EXTI4  4
#define EXTI5  5
#define EXTI6  6
#define EXTI7  7
#define EXTI8  8
#define EXTI9  9
#define EXTI10 10
#define EXTI11 11
#define EXTI12 12
#define EXTI13 13
#define EXTI14 14
#define EXTI15 15

#define EXTI_CONFIG_PORTA 0     // Maple, Maple Native, Maple Mini
#define EXTI_CONFIG_PORTB 1     // Maple, Maple Native, Maple Mini
#define EXTI_CONFIG_PORTC 2     // Maple, Maple Native, Maple Mini
#define EXTI_CONFIG_PORTD 3     // Maple and Maple Native only
#define EXTI_CONFIG_PORTE 4     // Native only
#define EXTI_CONFIG_PORTF 5     // Native only
#define EXTI_CONFIG_PORTG 6     // Native only

#ifdef __cplusplus
extern "C"{
#endif

void exti_attach_interrupt(uint32 port, uint32 pin, voidFuncPtr handler,
                           uint32 mode);
void exti_detach_interrupt(uint32 channel);

#ifdef __cplusplus
} // extern "C"
#endif


#endif