Andy K / Lib17_Core

include/Lib17_DIO.h

Committer:
AjK
Date:
2011-04-11
Revision:
1:2f99edb5545c
Parent:
0:127224866798
Child:
2:b77d327026af

File content as of revision 1:2f99edb5545c:

/****************************************************************************
 * Product: LIB17 Open Source Library
 *
 *                    Steller Technologies Limited
 *                    ----------------------------
 *
 * Copyright (C) 2002-2011 Steller Technologies Limited. All rights reserved.
 *
 * This software may be distributed and modified under the terms of the GNU
 * General Public License version 2 (GPL) as published by the Free Software
 * Foundation and appearing in the file GPL.TXT included in the packaging of
 * this file. Please note that GPL Section 2[b] requires that all works based
 * on this software must also be made publicly available under the terms of
 * the GPL ("Copyleft").
 *
 * Alternatively, this software may be distributed and modified under the
 * terms of Steller Technologies Limited commercial licenses, which expressly
 * supersede the GPL and are specifically designed for licensees interested in
 * retaining the proprietary status of their code.
 *
 * $Id:$
 *
 ***************************************************************************/

/**
 * @file Lib17_DIO.h
 * @see http://cornflakes.wikidot.com/lib17:core
 * @defgroup API The Lib17 Core API 
 * @defgroup Lib17_DIO Lib17_DIO functions
 */
 
#ifndef AJK_Lib17_DIO_H
#define AJK_Lib17_DIO_H

#include "Lib17_Mbed.h"
#include "Lib17_IOmacros.h"

namespace AjK {

/** Lib17_DIO - Adds pin input/output objects.
 *
 * The Mbed library supplies the DigitalIn and DigitalOut objects to allow you
 * to specify ins and outs.
 *
 * Lib17_DIO allows library objects to implement pins without the requirement
 * to link against the Mbed library. This increase portability when using
 * alternate compilers (such as the Code Red GCC C++ compiler for LPCXpresso).
 */
class Lib17_DIO {
public:
    enum Direction {
          Out = 0
        , In
    };

protected:
    PinName pin;
    uint32_t mask;
    uint32_t fiodir;
    uint32_t fiomask;
    uint32_t fiopin;
    uint32_t fioset;
    uint32_t fioclr;

    inline void setpin(PinName p)  { pin     = p; }
    inline void setmask(PinName p) { mask    = (uint32_t)(1UL << ((uint32_t)p & 0x1F)); }
    inline void setDir(PinName p)  { fiodir  = (uint32_t)(p & ~0x1F) + 0x00; }
    inline void setMask(PinName p) { fiomask = (uint32_t)(p & ~0x1F) + 0x10; }
    inline void setPin(PinName p)  { fiopin  = (uint32_t)(p & ~0x1F) + 0x14; }
    inline void setSet(PinName p)  { fioset  = (uint32_t)(p & ~0x1F) + 0x18; }
    inline void setClr(PinName p)  { fioclr  = (uint32_t)(p & ~0x1F) + 0x1C; }

    inline void pinUp() { *((volatile uint32_t *)fioset) = mask; }
    inline void pinDn() { *((volatile uint32_t *)fioclr) = mask; }
    inline uint32_t pinIs() { return *((volatile uint32_t *)(fiopin)) & mask; }

public:

    Lib17_DIO(PinName p, Direction d = Out, PinMode m = PullDown) { init(p, d, m); };

    /**
     * write
     *
     * Writes a value to the pin. 
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @param i Zero makes the pin 0v, non-zero makes the pin 1.
     */
    void write(int i)     { if (i!=0) { pinUp(); } else { pinDn(); } }
    
    /**
     * read
     *
     * Reads the value on the pin. 
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    int  read(void)       { return pinIs() ? 1 : 0; };
    
    /**
     * output
     *
     * Setup the pin to be an output.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    void output(void)    { *((volatile uint32_t *)fiodir) |=  mask; }
    
    /**
     * input
     *
     * Setup the pin to be an input.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    void input(void)    { *((volatile uint32_t *)fiodir) &= ~mask; }

    /**
     * getPin
     *
     * Get the PinName this object is operating on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    PinName getPin(void) { return pin; }
    
    /**
     * getDirection
     *
     * Get the operational direction this pin is setup for.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    int getDirection(void) { return *((volatile uint32_t *)fiomask) & mask ? 1 : 0; }

    /**
     * operator int()
     *
     * Reads the value on the pin. 
     *
     * @see read
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return int 0v returns zero, otherwise returns 1.
     */
    operator int() { return read(); }
    
    /**
     * operator= 
     *
     * Writes a value to the pin. 
     *
     * @see write
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     */
    Lib17_DIO& operator= (int value)  { write(value); return *this; }
    
    /**
     * operator= 
     *
     * Writes a value to the pin. 
     *
     * @see write
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     */
    Lib17_DIO& operator= (Lib17_DIO& rhs) { write(rhs.read()); return *this; }

    /**
     * getMask
     *
     * Get the mask value for this pin.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The mask value used by this pin.
     */ 
    uint32_t getMask(void)    { return mask;    }
    
    /**
     * getFiodir
     *
     * Get the FIODIR register for the port the pin is on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The register value.
     */ 
    uint32_t getFiodir(void)  { return fiodir;  }
    
    /**
     * getFiomask
     *
     * Get the FIOMASK register for the port the pin is on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The register value.
     */ 
    uint32_t getFiomask(void) { return fiomask; }
    
    /**
     * getFiopin
     *
     * Get the FIOPIN register for the port the pin is on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The register value.
     */ 
    uint32_t getFiopin(void)  { return fiopin;  }
    
    /**
     * getFioset
     *
     * Get the FIOSET register for the port the pin is on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The register value.
     */ 
    uint32_t getFioset(void)  { return fioset;  }
    
    /**
     * getFioclr
     *
     * Get the FIOCLR register for the port the pin is on.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup Lib17_DIO
     * @ingroup API 
     * @return uint32_t The register value.
     */ 
    uint32_t getFioclr(void)  { return fioclr;  }


protected:
    void init(PinName p, Direction d, PinMode m)
    {
        // We rely on the fact that by default the LPC1768
        // sets all pins to be GPIO. The user will change
        // that if they need to. So we don't bother trying
        // to setup PINSELx
    
        // psel(); // Not used, see above.
    
        setpin(p);
        setmask(p);
        setDir(p);
        setMask(p);
        setPin(p);
        setSet(p);
        setClr(p);
    
        if (d == Out) output();
        else mode( m );
    }

protected:
    void psel(void)
    {
        uint32_t ppsel, pumask;
    
        if (pin >= P0_0 && pin <= P0_15)         ppsel = (uint32_t)(&LPC_PINCON->PINSEL0);
        else if (pin >= P0_16 && pin <= P0_31)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL1);
        else if (pin >= P1_0 && pin <= P1_15)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL2);
        else if (pin >= P1_16 && pin <= P1_31)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL3);
        else if (pin >= P2_0 && pin <= P2_15)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL4);
        else if (pin >= P3_16 && pin <= P3_31)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL7);
        else if (pin >= P4_16 && pin <= P4_31)     ppsel = (uint32_t)(&LPC_PINCON->PINSEL9);
        else return;
    
        pumask = ~(3UL << ((pin & 0x1F)>>1));
        *((volatile uint32_t *)ppsel) &= pumask;
    }

public:
    void mode(PinMode m) 
    {
        uint32_t ppmod, pumask;
    
        if (m == OpenDrain) {
            openDrain(1);
        }
        else {
            if (pin >= P0_0 && pin <= P0_15) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE0);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-0)*2) );
            }
            else if (pin >= P0_16 && pin <= P0_31) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE1);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-16)*2) );
            }
            else if (pin >= P1_0 && pin <= P1_15) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE2);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-0)*2) );
            }
            else if (pin >= P1_16 && pin <= P1_31) {
                 ppmod = (uint32_t)(&LPC_PINCON->PINMODE3);
                 pumask = ((m & 0x3) << ( ((pin & 0x1F)-16)*2) );
            }
            else if (pin >= P2_0 && pin <= P2_15) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE4);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-0)*2) );
            }
            else if (pin >= P3_16 && pin <= P3_31) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE7);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-16)*2) );
            }
            else if (pin >= P4_16 && pin <= P4_31) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE9);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-16)*2) );
            }
            else return;
    
            *((volatile uint32_t *)ppmod) |= pumask;
        }
    }

public:
    void openDrain(int i = 1) 
    {
        if (pin >= P0_0 && pin <= P0_31)           { if (i) LPC_PINCON->PINMODE_OD0 |= mask; else LPC_PINCON->PINMODE_OD0 &= ~mask; }
        else if (pin >= P1_0 && pin <= P1_31)      { if (i) LPC_PINCON->PINMODE_OD1 |= mask; else LPC_PINCON->PINMODE_OD1 &= ~mask; }
        else if (pin >= P2_0 && pin <= P2_31)      { if (i) LPC_PINCON->PINMODE_OD2 |= mask; else LPC_PINCON->PINMODE_OD2 &= ~mask; }
        else if (pin >= P3_16 && pin <= P3_31)     { if (i) LPC_PINCON->PINMODE_OD3 |= mask; else LPC_PINCON->PINMODE_OD3 &= ~mask; }
        else if (pin >= P4_16 && pin <= P4_31)     { if (i) LPC_PINCON->PINMODE_OD4 |= mask; else LPC_PINCON->PINMODE_OD4 &= ~mask; }
    }

};

}; /* namespace AjK ends. */

using namespace AjK;

#endif /* AJK_Lib17_DIO_H */