/*                                             -*- mode:C++; fill-column:100 -*-
  SFBWiring.h - The 'Arduinoesque API' provided by the SFB.
  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 SFBWiring.h SFB versions of the basic Arduino/Wiring functions
  \author David H. Ackley.  
  \date (C) 2008 All rights reserved.
  \lgpl
 */
#ifndef SFBWIRING_H
#define SFBWIRING_H

#include "SFBTypes.h"
#include "SFBConstants.h"
#include "SFBPins.h"

/**
  \ingroup basica

  Set a pin's value.  Following the Arduino approach, this method can also be used to set the pullup
  resistors on input pins: If the pin is configured as an INPUT, writing a #HIGH value with
  digitalWrite() will enable an internal pullup resistor, and writing a #LOW value will disable the
  internal pullup resistor.  (As an SFB extension, it is also possible to set an internal pulldown
  resistor, see #setPinResistor.)
  
 */
extern void digitalWrite(int sfbPin, int value);

/**
  \ingroup basica

  Read a pin's value.  
 */
extern int digitalRead(int sfbPin);

/**
  \ingroup basics

  Turn on one of the SFB built-in LEDs.
 */
inline void ledOn(int sfbPin) { digitalWrite(sfbPin,LOW); }

/**
  \ingroup basics
  Turn off one of the SFB built-in LEDs.
 */
inline void ledOff(int sfbPin) { digitalWrite(sfbPin,HIGH); }
/**
  \ingroup basics
  Turn on or off one of the SFB built-in LEDs.
 */
inline void ledSet(int sfbPin,bool on) { digitalWrite(sfbPin,on?LOW:HIGH); }

/**
  \ingroup basics
  Check if one of the SFB built-in LEDs is on or off.
  \returns \c true if the \a sfbPin is on, \c false otherwise
 */
inline bool ledIsOn(int sfbPin) { return digitalRead(sfbPin)==LOW; }

/**
  \ingroup basics
  Toggle one of the SFB built-in LEDs.
 */
void ledToggle(int sfbPin) ;

/**
  \ingroup basics
  Check if the SFB built-in button is currently down.
 Watch out!  This is not debounced!
 */
static inline bool buttonDown() { return digitalRead(BODY_SWITCH0_PIN)==LOW; }
extern bool buttonDown();

/**
  \ingroup basica
  Set a pin's function to input or output.  SFB extension: Set to 'reflex mode'.
 */
extern void pinMode(int sfbPin, int mode);

/**
  \ingroup basica
  SFB extension: Check if a pin is currently an input or an output (or under reflex control).

  \param mode Either #INPUT or #OUTPUT for basic usage.  Can also be #REFLEX_MODE to check if a pin
  is in reflex mode (rather than checking if it's an input or an output).

  \return Non-zero if \a mode is #INPUT and \a sfbPin is currently an input pin, or if \a mode is
  #OUTPUT and \a sfbPin is currently an output pin, or if \a mode is #REFLEX_MODE and \a sfbPin is
  currently under reflex control; and returns 0 otherwise.

  \blinks #E_API_ARGUMENT if \a mode is not #INPUT, #OUTPUT, or #REFLEX_MODE

  \blinks #E_API_BAD_PIN if \a sfbPin is not a valid pin

  \since 0.9.11
 */
extern u32 isPinMode(int sfbPin, int mode);

#ifdef HOST_MODE

#include "SFBHWPinsHost.h"

#else

#include "lpc/timer.h"

#endif

/** Delay for some number of microseconds.  
  \ingroup basica
 */
extern void delayMicroseconds(u32 usecondsToWait);

extern void delayMicrosecondsApproximate(u32 usecondsToWait);

/** Delay for some number of milliseconds.  If this function is called from #loop(), dispatching
  (i.e., running packet and alarm handlers) will occur, but if called from a packet or alarm
  handler, no further (recursive) dispatching will take place, and instead just the delay will
  happen.

 \ingroup basica
 */
extern void delay(u32 millissecondToWait) ;

/** 
  \ingroup basica
 */
extern void shiftOut(int dataPin, int clockPin, int bitOrder, u8 val);

/** 
  \ingroup basica
 */
extern u32 pulseIn(int pin, int state, u32 timeoutUsec = 1000000);

#endif  /* SFBWIRING_H */
