Tripple Controller for the TLE5206 H Bridge motor controller

inc/SimpleTLE5206Output.h

Committer:
AjK
Date:
2011-07-05
Revision:
5:bfc5c5cc161e
Parent:
0:e2433ca2ce59

File content as of revision 5:bfc5c5cc161e:

/*
    Copyright (c) 2011 Andy Kirkham
    
    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.
*/

#ifndef AJK_SIMPLETLE5206OUTPUT_H
#define AJK_SIMPLETLE5206OUTPUT_H

#ifndef __ARMCC_VERSION
#include "SimpleTLE5206Mbed.h"
#define error(...)
#else
#include "mbed.h"
#endif


namespace AjK {

/** SimpleTLE5206Output - Adds pin output objects.
 *
 * The Mbed library supplies the DigitalIn and DigitalOut objects to allow you
 * to specify ins and outs.
 *
 * SimpleTLE5206Output 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).
 *
 * Additionally, this class allows the pin to be configured as a GPIO output or swapped
 * to PWM output mode.
 *
 * Note, this class can only be used for pins p21 through p26 as these are used for PWM pins.
 * Trying to set this to any other pin will result in a fatal error() call.
 *
 * @ingroup SimpleTLE5206Output
 */
class SimpleTLE5206Output {
public:
    enum Direction {
          Out = 0
        , In
    };
    
    enum PinType {
          IsGPIO = 0
        , IsPWM
    };

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

    PinType pin_type;
    
    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:

    /** Constructor
     * @ingroup SimpleTLE5206Output
     */
    SimpleTLE5206Output(PinName p, Direction d = Out, PinMode m = PullDown) { 
    
        if (p == p21 || p == p22 || p == p23 || p == p24 || p == p25 || p == p26 || p == LED1 || p == LED2 || p == LED3 || p == LED4) {
            init(p, d, m); 
        }
        else {
            error("Invalid pin supplied.\n");
        }
    };

    /** write
     *
     * Writes a value to the pin.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     */
    SimpleTLE5206Output& 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 SimpleTLE5206Output
     */
    SimpleTLE5206Output& operator= (SimpleTLE5206Output& rhs) { write(rhs.read()); return *this; }

    /** getMask
     *
     * Get the mask value for this pin.
     *
     * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio
     * @ingroup SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 SimpleTLE5206Output
     * @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 );
        
        pin_type = IsGPIO; // GPIO.
    }

public:
    void as_gpio(void)
    {
        pin_type = IsGPIO;
        
                switch(pin) {
        case P2_0:    
            LPC_PINCON->PINSEL4 &= ~(3UL << 0); // Mbed p26 P2.0 clr bits
            return;
        case P1_18: // Mbed LED1
            LPC_PINCON->PINSEL3 &= ~(3UL << 4); // Mbed LED2 P1.18 clr bits
            return;
        }
        
        switch(pin) {
        case P2_1:
            LPC_PINCON->PINSEL4 &= ~(3UL << 2); // Mbed p25 P2.1 clr bits
            return;
        case P1_20: // Mbed LED2
            LPC_PINCON->PINSEL3 &= ~(3UL << 8); // Mbed LED2 P1.20 clr bits
            return;
        }

        switch(pin) {
        case P2_2:
            LPC_PINCON->PINSEL4 &= ~(3UL << 4); // Mbed p24 P2.2 clr bits
            return;
        case P1_21: // Mbed LED3
            LPC_PINCON->PINSEL3 &= ~(3UL << 10); // Mbed LED3 P1.21 clr bits
            return;
        }   
    
        switch(pin) {
        case P2_3:
            LPC_PINCON->PINSEL4 &= ~(3UL << 6); // Mbed p23 P2.3 clr bits
            return;
        case P1_23: // Mbed LED4
            LPC_PINCON->PINSEL3 &= ~(3UL << 14); // Mbed LED4 P1.23 clr bits
            return;
        }
    
        switch(pin) {
        case P2_4: // Mbed p22
            LPC_PINCON->PINSEL4 &= ~(3UL << 8); // Mbed p22 P2.4 clr bits
            return;
        case P1_24:            
            LPC_PINCON->PINSEL3 &= ~(3UL << 16); // P1.24 clr bits
            return;
        }
    
        switch(pin) {
        case P2_5: // Mbed p21
            LPC_PINCON->PINSEL4 &= ~(3UL << 10); // Mbed p21 P2.5 clr bits
            return;
        case P1_26:
            LPC_PINCON->PINSEL3 &= ~(3UL << 20); // P1.26 clr bits
            return;
        }
    }

    void as_pwm(void)
    {
        pin_type = IsPWM;    
        
        switch(pin) {
        case P2_0:    
            LPC_PINCON->PINSEL4 &= ~(3UL << 0); // Mbed p26 P2.0 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 0); // Mbed p26 P2.0 set bits
            LPC_PWM1->PCR |= (1UL << 9);
            return;
        case P1_18: // Mbed LED1
            LPC_PINCON->PINSEL3 &= ~(3UL << 4); // Mbed LED2 P1.18 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 4); // Mbed LED2 P1.18 set bits
            LPC_PWM1->PCR |= (1UL << 9);
            return;
        }
        
        switch(pin) {
        case P2_1:
            LPC_PINCON->PINSEL4 &= ~(3UL << 2); // Mbed p25 P2.1 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 2); // Mbed p25 P2.1 set bits
            LPC_PWM1->PCR |= (1UL << 10);
            return;
        case P1_20: // Mbed LED2
            LPC_PINCON->PINSEL3 &= ~(3UL << 8); // Mbed LED2 P1.20 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 8); // Mbed LED2 P1.20 set bits
            LPC_PWM1->PCR |= (1UL << 10);
            return;
        }

        switch(pin) {
        case P2_2:
            LPC_PINCON->PINSEL4 &= ~(3UL << 4); // Mbed p24 P2.2 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 4); // Mbed p24 P2.2 set bits
            LPC_PWM1->PCR |= (1UL << 11);
            return;
        case P1_21: // Mbed LED3
            LPC_PINCON->PINSEL3 &= ~(3UL << 10); // Mbed LED3 P1.21 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 10); // Mbed LED3 P1.21 set bits
            LPC_PWM1->PCR |= (1UL << 11);
            return;
        }   
    
        switch(pin) {
        case P2_3:
            LPC_PINCON->PINSEL4 &= ~(3UL << 6); // Mbed p23 P2.3 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 6); // Mbed p23 P2.3 set bits
            LPC_PWM1->PCR |= (1UL << 12);
            return;
        case P1_23: // Mbed LED4
            LPC_PINCON->PINSEL3 &= ~(3UL << 14); // Mbed LED4 P1.23 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 14); // Mbed LED4 P1.23 set bits
            LPC_PWM1->PCR |= (1UL << 12);
            return;
        }
    
        switch(pin) {
        case P2_4: // Mbed p22
            LPC_PINCON->PINSEL4 &= ~(3UL << 8); // Mbed p22 P2.4 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 8); // Mbed p22 P2.4 set bits
            LPC_PWM1->PCR |= (1UL << 13);
            return;
        case P1_24:            
            LPC_PINCON->PINSEL3 &= ~(3UL << 16); // P1.24 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 16); // P1.24 set bits
            LPC_PWM1->PCR |= (1UL << 13);
            return;
        }
    
        switch(pin) {
        case P2_5: // Mbed p21
            LPC_PINCON->PINSEL4 &= ~(3UL << 10); // Mbed p21 P2.5 clr bits
            LPC_PINCON->PINSEL4 |=  (1UL << 10); // Mbed p21 P2.5 set bits
            LPC_PWM1->PCR |= (1UL << 14);
            return;
        case P1_26:
            LPC_PINCON->PINSEL3 &= ~(3UL << 20); // P1.26 clr bits
            LPC_PINCON->PINSEL3 |=  (2UL << 20); // P1.26 set bits
            LPC_PWM1->PCR |= (1UL << 14);
            return;
        }

/*    
        uint32_t ppsel, pumask;

        if (pin >= P2_0 && pin <= P2_5) {
            ppsel = (uint32_t)(&LPC_PINCON->PINSEL4);
            pumask = ~(3UL << ((pin & 0x1F)>>1));
            *((volatile uint32_t *)ppsel) &= pumask;
            pumask = (1UL << ((pin & 0x1F)>>1));
            *((volatile uint32_t *)ppsel) |= pumask;
        }
        else if (pin >= LED1 && pin <= LED4) {
            ppsel = (uint32_t)(&LPC_PINCON->PINSEL3);                
            pumask = ~(3UL << ((pin & 0x1F)>>1));
            *((volatile uint32_t *)ppsel) &= pumask;
            pumask = (2UL << ((pin & 0x1F)>>1));
            *((volatile uint32_t *)ppsel) |= pumask;
        }
        else return;    
*/        
        
    }

    PinType get_pin_type(void) { return pin_type; }
    
    void mode(PinMode m)
    {
        uint32_t ppmod, pumask;

        if (m == OpenDrain) {
            openDrain(1);
        }
        else {            
            if (pin >= P2_0 && pin <= P2_5) {
                ppmod = (uint32_t)(&LPC_PINCON->PINMODE4);
                pumask = ((m & 0x3) << ( ((pin & 0x1F)-0)*2) );
            }
            else return;

            *((volatile uint32_t *)ppmod) |= pumask;
        }
    }

public:
    void openDrain(int i = 1)
    {
        if (pin >= P2_0 && pin <= P2_5)      { if (i) LPC_PINCON->PINMODE_OD2 |= mask; else LPC_PINCON->PINMODE_OD2 &= ~mask; }        
    }

};

}; /* namespace AjK ends. */

using namespace AjK;

#endif /* AJK_SIMPLETLE5206OUTPUT_H */