/*                                              -*- mode:C++; fill-column:100 -*-
  SFBHWPinsBoard.h Board-specific pin function definitions
  Copyright (C) 2008 The Regents of the University of New Mexico.  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
  USA

  $Id$
*/

/**
  \file SFBHWPinsBoard.h Board-specific pin function definitions
  \author David H. Ackley.  
  \date (C) 2008 All rights reserved.
  \lgpl
 */

#ifdef SFBHWPINSHOST_H
#error SFBHWPinsBoard.h and SFBHWPinsHost.h must not be #included together!
#endif

#ifndef SFBHWPINSBOARD_H
#define SFBHWPINSBOARD_H

#include "lpc/fio.h"
#include "timer.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Fast pin access macros. \cond */

#define SFB_PORT_IN_MAP(offset, port) (*((volatile u32 *)(((FIO_BASE_ADDR)+(offset))+(port)*0x20)))
#define SFB_PORT_DIR_REGISTER(port)  SFB_PORT_IN_MAP(0x00,port)
#define SFB_PORT_MASK_REGISTER(port) SFB_PORT_IN_MAP(0x10,port)
#define SFB_PORT_PIN_REGISTER(port)  SFB_PORT_IN_MAP(0x14,port)
#define SFB_PORT_SET_REGISTER(port)  SFB_PORT_IN_MAP(0x18,port)
#define SFB_PORT_CLR_REGISTER(port)  SFB_PORT_IN_MAP(0x1C,port)

#define SFB_PORT_PINMODE_REGISTER(offset) \
  (*((volatile u32 *)((PINMODE_BASE_ADDR)+(offset))))

#define SFB_PINSEL_REGISTER(port,pinNumber) \
  (*((volatile u32 *)((PINSEL_BASE_ADDR)+((port)*8)+((pinNumber)>15?4:0))))

#define SFB_PORT_GET_BIT_MASK(port,mask) (SFB_PORT_PIN_REGISTER(port)&(mask))

#define SFB_PORT_SET_BIT_MASK(port,mask) (SFB_PORT_SET_REGISTER(port) = (mask))
#define SFB_PORT_CLR_BIT_MASK(port,mask) (SFB_PORT_CLR_REGISTER(port) = (mask))
#define SFB_PORT_WRITE_BIT_MASK(port,mask,value) \
  (((value)==LOW)?SFB_PORT_CLR_BIT_MASK(port,mask):SFB_PORT_SET_BIT_MASK(port,mask))

#define LED_GREEN_MASK    (1UL<<0)
#define LED_RED_MASK      (1UL<<1)
#define LED_BLUE_MASK     (1UL<<2)

#define REFLEX_RGB_RED_ON (FIO2CLR = LED_RED_MASK)
#define REFLEX_RGB_RED_OFF (FIO2SET = LED_RED_MASK)
#define REFLEX_RGB_GREEN_ON (FIO2CLR = LED_GREEN_MASK)
#define REFLEX_RGB_GREEN_OFF (FIO2SET = LED_GREEN_MASK)
#define REFLEX_RGB_BLUE_ON (FIO2CLR = LED_BLUE_MASK)
#define REFLEX_RGB_BLUE_OFF (FIO2SET = LED_BLUE_MASK)

extern void setPinSelFunction(u32 port,u32 pinNumber,u32 function);

/** \endcond */

/** Attempt to reenter the secondary bootloader.  Normally this is performed by branching to address
    0, but if the watchdog timer has been enabled that won't work, so this method defers to
    #watchdogSuicide in that case. */
extern void reenterBootloader() __attribute__ ((noreturn));

/** Attempt to reenter the tertiary bootloader.  Normally this is performed by branching to address
    0x2200, where the tertiary bootloader starts, but if the watchdog timer has been enabled that
    won't work, so this method turns into #reenterBootloader in that case. */
extern void reenterBrainstem() __attribute__ ((noreturn));

/** \cond */
extern void hwpins_startup_initialization();

/* Low-level last ditch routine to set the rbg leds, bypassing (and
   thereby breaking) all the normal pin management stuff.  So don't
   use this unless the situation is dire enough that you don't case
   about that. */
extern void debugRGB(int rgbBits, int wait);
/** \endcond */

/** Internal method called during failed assertions and other fatal events */
extern void _dieOnBoard_(u32 blinkCode, const char * file, int lineno) __attribute__ ((noreturn));

#ifdef __cplusplus
}
#endif

#endif  /* SFBHWPINSBOARD_H */
