/*---------------------------------------------------------------------------*
  Project:  NitroSDK - PAD - include
  File:     pad.h

  Copyright 2003-2004 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: pad.h,v $
  Revision 1.8  2004/08/06 12:43:20  yada
  change key interrupt logic enum

  Revision 1.7  2004/08/06 05:13:20  yada
  PAD_SetIrq -> PADi_SetIrq, PAD_ClearIrq -> PADi_ClearIrq

  Revision 1.6  2004/06/11 11:21:57  terui
  Reversed bit logic of open/close detection function.

  Revision 1.5  2004/06/11 11:04:59  terui
  Added definition and function regarding open/close determination.

  Revision 1.4  2004/04/13 07:45:56  yada
  Corrected mask value in interrupt key setting

  Revision 1.3  2004/04/07 02:03:17  yada
  fix header comment

  Revision 1.2  2004/03/16 13:03:42  takano_makoto
  Add DEBUG button.

  Revision 1.1  2004/02/18 01:23:28  yada
  Moved pad region to shared region that is divided between ARM7/9

  Revision 1.16  2004/02/17 09:22:03  yada
  Support ARM7

  Revision 1.15  2004/02/12 10:56:04  yasu
  new location of include files ARM9/ARM7

  Revision 1.14  2004/02/05 07:09:03  yasu
  change SDK prefix iris -> nitro

  Revision 1.13  2004/01/17 02:28:38  nishida_kenji
  convert 'inline' to 'static inline' in header files

  Revision 1.12  2004/01/08 12:03:21  yada
  Revised key interrupt definition.

  Revision 1.11  2003/12/26 05:52:02  yada
  Changed to unify type rules.

  Revision 1.10  2003/12/25 10:55:08  yada
  Changed to unify type rules.

  Revision 1.9  2003/12/25 00:19:29  nishida_kenji
  convert INLINE to inline

  Revision 1.8  2003/12/11 08:00:31  yada
  Revised enum definition. Made enable flag BOOL type.

  Revision 1.7  2003/12/01 10:39:04  yada
  Changed PAD_SetInterrupt() to PAD_SetIRQ(), and changed PAD_ClearInterrupt() to PAD_ClearIRQ().

  Revision 1.6  2003/11/14 04:56:01  yada
  Changed register access macro from REG_XXX to reg_XXX.

  Revision 1.5  2003/11/12 12:02:09  yada
  Comment revision. Revised included files.

  Revision 1.4  2003/11/10 07:59:47  yada
  Inverted input from the pad.

  Revision 1.3  2003/11/05 01:03:31  yada
  Be strict with cast. At least make it so no warnings appear.

  Revision 1.2  2003/10/30 11:42:57  yada
  Made to use REGTypexx in register type.

  Revision 1.1  2003/10/30 07:41:13  yada
  Initial build

  $NoKeywords: $
 *---------------------------------------------------------------------------*/

#ifndef NITRO_PAD_PAD_H_
#define NITRO_PAD_PAD_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <nitro/misc.h>
#include <nitro/types.h>
#ifdef SDK_ARM9
#include <nitro/hw/ARM9/ioreg_PAD.h>
#else // SDK_ARM9
#include <nitro/hw/ARM7/ioreg_PAD.h>
#endif // SDK_ARM9

/*----------------------------------------------------------------
 *      Button definition
 */

//---- Mask values
#define PAD_PLUS_KEY_MASK       0x00f0      // Mask: +Control Pad
#define PAD_BUTTON_MASK         0x2f0f      // Mask: button
#define PAD_DEBUG_BUTTON_MASK   0x2000      // Mask: Debug button
#define PAD_ALL_MASK            0x2fff      // Mask: All buttons, keys
#define PAD_RCNTPORT_MASK       0x2c00      // Mask: What ARM7 can read from the RCNT register.
#define PAD_KEYPORT_MASK        0x03ff      // Mask: What ARM7/9 can read from the KEY register.

#define PAD_DETECT_FOLD_MASK    0x8000      // Mask: folding

//---- Button keys
#define PAD_BUTTON_A            0x0001      // A button
#define PAD_BUTTON_B            0x0002      // B button
#define PAD_BUTTON_SELECT       0x0004      // Select button
#define PAD_BUTTON_START        0x0008      // Start button
#define PAD_KEY_RIGHT           0x0010      // Right button
#define PAD_KEY_LEFT            0x0020      // Left button
#define PAD_KEY_UP              0x0040      // Up button
#define PAD_KEY_DOWN            0x0080      // Down button
#define PAD_BUTTON_R            0x0100      // R button
#define PAD_BUTTON_L            0x0200      // L button
#define PAD_BUTTON_X            0x0400      // X button
#define PAD_BUTTON_Y            0x0800      // Y button
#define PAD_BUTTON_DEBUG        0x2000      // DEBUG button

/*---------------------------------------------------------------------------*
  Name:         PAD_Read

  Description:  read pad data.
                Xand Y button data from ARM7 are added.

  Arguments:    None.

  Returns:      pad data.
                See above defines to know the meaning of each bit.
 *---------------------------------------------------------------------------*/
static inline u16
PAD_Read( void )
{
    return (u16)(
        (
            ( reg_PAD_KEYINPUT | *(vu16*)HW_BUTTON_XY_BUF ) ^
            ( PAD_PLUS_KEY_MASK | PAD_BUTTON_MASK )
        ) & ( PAD_PLUS_KEY_MASK | PAD_BUTTON_MASK )
    );
}

/*---------------------------------------------------------------------------*
  Name:         PAD_DetectFold

  Description:  detect folding Nitro.

  Arguments:    None.

  Returns:      TRUE if fold, FALSE if not.
 *---------------------------------------------------------------------------*/
static inline BOOL
PAD_DetectFold( void )
{
    return (BOOL)(
        (
            *(vu16*)HW_BUTTON_XY_BUF & PAD_DETECT_FOLD_MASK
        ) >> 15
    );
}


//================================================================================
//         INTERNAL FUNCTIONS
//================================================================================
//   Don't use PADi_ internal functions as you can.
//   Using key interrupt may cause some bugs
//   because there is the problem about key chattering

//---------------- interrupt key logic
typedef enum {
                                                       // condition for occurring interrupt
    PAD_LOGIC_OR  = (0 << REG_PAD_KEYCNT_LOGIC_SHIFT),  //   Push ONE of keys you specified
    PAD_LOGIC_AND = (1 << REG_PAD_KEYCNT_LOGIC_SHIFT),  //   Push ALL of keys at a time you specified

	//---- for compatibility to old description
    PAD_OR_INTR  = PAD_LOGIC_OR,
    PAD_AND_INTR = PAD_LOGIC_AND
} PADLogic;

/*---------------------------------------------------------------------------*
  Name:         PADi_SetIrq

  Description:  set key interrupt

  Arguments:    logic   : key logic
                          PAD_OR_INTR / PAD_AND_INTR
                enable  : TRUE if enable interrupt, FALSE if not
                padMask : buttons to occur interrupt

  Returns:      None.
 *---------------------------------------------------------------------------*/
static inline void
PADi_SetIrq( PADLogic logic, BOOL enable, u16 padMask )
{
    SDK_ASSERT(!(padMask & (~PAD_KEYPORT_MASK)));   // Check XY, Debug button
    reg_PAD_KEYCNT = (u16)( ((u16)logic
                                                    | ( enable? REG_PAD_KEYCNT_INTR_MASK : 0 ) 
                                                    | (PAD_KEYPORT_MASK & padMask) ) );
}

/*---------------------------------------------------------------------------*
  Name:         PADi_ClearIrq

  Description:  unset key interrupt

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
static inline void
PADi_ClearIrq(void)
{
    reg_PAD_KEYCNT = 0;
}

//================================================================================

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

/* NITRO_PAD_PAD_H_ */
#endif
