Tripple Controller for the TLE5206 H Bridge motor controller

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Tue Jul 05 07:43:28 2011 +0000
Child:
1:e6f43157c7db
Commit message:
0.2 Beta

Changed in this revision

inc/SimpleTLE5206.h Show annotated file Show diff for this revision Revisions of this file
inc/SimpleTLE5206Mbed.h Show annotated file Show diff for this revision Revisions of this file
inc/SimpleTLE5206Output.h Show annotated file Show diff for this revision Revisions of this file
inc/example1.h Show annotated file Show diff for this revision Revisions of this file
src/SimpleTLE5206.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/SimpleTLE5206.h	Tue Jul 05 07:43:28 2011 +0000
@@ -0,0 +1,62 @@
+/*
+    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_SIMPLETLE5206_H
+#define AJK_SIMPLETLE5206_H
+
+#include "LPC17xx.h"
+#include "SimpleTLE5206Output.h"
+
+namespace AjK {
+
+class SimpleTLE5206 {
+
+public:
+    enum PwmCh { NoPwm0, Pwm1, Pwm2, Pwm3, Pwm4, Pwm5, Pwm6, NumOfPwms  };
+
+protected:
+    uint32_t _duty;
+    
+    SimpleTLE5206Output *_in1;
+    SimpleTLE5206Output *_in2;
+    
+    void setDuty(uint32_t u);
+    
+    void setMRx(PwmCh ch, uint32_t value);
+    
+    void init(void);
+    
+public:
+
+    SimpleTLE5206() { error("We require two pins!\n"); }
+        
+    SimpleTLE5206(SimpleTLE5206Output *in1, SimpleTLE5206Output *in2);
+
+    void setSpeed(double d);
+    
+}; /* class SimpleTLE5206 ends. */
+
+}; /* namespace AjK ends. */
+
+using namespace AjK;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/SimpleTLE5206Mbed.h	Tue Jul 05 07:43:28 2011 +0000
@@ -0,0 +1,85 @@
+/*
+    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_SIMPLETLE5206MBED_H
+#define AJK_SIMPLETLE5206MBED_H
+
+#ifndef MBED_PINNAMES_H
+#define MBED_PINNAMES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    P0_0 = LPC_GPIO0_BASE, P0_1, P0_2, P0_3, P0_4, P0_5, P0_6, P0_7
+    , P0_8, P0_9, P0_10, P0_11, P0_12, P0_13, P0_14, P0_15
+    , P0_16, P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23
+    , P0_24, P0_25, P0_26, P0_27, P0_28, P0_29, P0_30, P0_31
+    , P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7
+    , P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15
+    , P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23
+    , P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31
+    , P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7
+    , P2_8, P2_9, P2_10, P2_11, P2_12, P2_13, P2_14, P2_15
+    , P2_16, P2_17, P2_18, P2_19, P2_20, P2_21, P2_22, P2_23
+    , P2_24, P2_25, P2_26, P2_27, P2_28, P2_29, P2_30, P2_31
+    , P3_0, P3_1, P3_2, P3_3, P3_4, P3_5, P3_6, P3_7
+    , P3_8, P3_9, P3_10, P3_11, P3_12, P3_13, P3_14, P3_15
+    , P3_16, P3_17, P3_18, P3_19, P3_20, P3_21, P3_22, P3_23
+    , P3_24, P3_25, P3_26, P3_27, P3_28, P3_29, P3_30, P3_31
+    , P4_0, P4_1, P4_2, P4_3, P4_4, P4_5, P4_6, P4_7
+    , P4_8, P4_9, P4_10, P4_11, P4_12, P4_13, P4_14, P4_15
+    , P4_16, P4_17, P4_18, P4_19, P4_20, P4_21, P4_22, P4_23
+    , P4_24, P4_25, P4_26, P4_27, P4_28, P4_29, P4_30, P4_31
+
+    // Mbed DIP Pin Names
+    , p5 = P0_9, p6 = P0_8, p7 = P0_7, p8 = P0_6, p9 = P0_0, p10 = P0_1
+    , p11 = P0_18, p12 = P0_17, p13 = P0_15, p14 = P0_16, p15 = P0_23
+    , p16 = P0_24, p17 = P0_25, p18 = P0_26, p19 = P1_30, p20 = P1_31
+    , p21 = P2_5, p22 = P2_4, p23 = P2_3, p24 = P2_2, p25 = P2_1
+    , p26 = P2_0, p27 = P0_11, p28 = P0_10, p29 = P0_5, p30 = P0_4
+
+    // Other Mbed Pin Names
+    , LED1 = P1_18, LED2 = P1_20, LED3 = P1_21, LED4 = P1_23
+    , USBTX = P0_2, USBRX = P0_3
+
+    // Not connected
+    , NC = (int)0xFFFFFFFF
+
+} PinName;
+
+typedef enum {
+    PullUp = 0
+    , Repeater = 1
+    , PullNone = 2
+    , PullDown = 3
+    , OpenDrain = 4
+} PinMode;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBED_PINNAMES_H */
+
+#endif /* AJK_SIMPLETLE5206MBED_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/SimpleTLE5206Output.h	Tue Jul 05 07:43:28 2011 +0000
@@ -0,0 +1,476 @@
+/*
+    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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/example1.h	Tue Jul 05 07:43:28 2011 +0000
@@ -0,0 +1,107 @@
+
+#include "mbed.h"
+#include "SimpleTLE5206.h"
+
+Serial pc(USBTX, USBRX);
+
+/* NOTE! The SimpleTLE5206 library supports the TLE5206 in 
+ * Mode 2 Sign/Magnitude Control using two PWM outputs to
+ * control speed and direction. 
+ *
+ * Pins that be be used are p21, p22, p23, p24, p25 and/or p26
+ * in pairs. So the library supports upto 3 TLE5206 devices/motors.
+ *
+ * All PWM outputs use a common duty cycle which defaults to 100Hz/10ms.
+ * There is no way to have differing duty cycles for different output
+ * pin pairs as the hardware only supports a common duty cycle in single
+ * ended mode. It may be possible to refactor the library to use a different
+ * duty cycle system (paired outputs). But single/common duty cycle was the
+ * easiest and simplest way to get the library done in a short period of time.
+ *
+ * Additionally you can use LED1, LED2, LED3 and.or LED4 as mimics.
+ * However, if using:-
+ *  LED1 you cannot use p26 to drive an in to TLE5206
+ *  LED2 you cannot use p25 to drive an in to TLE5206
+ *  LED3 you cannot use p24 to drive an in to TLE5206
+ *  LED4 you cannot use p23 to drive an in to TLE5206
+ *
+ * The function SimpleTLE5206::setSpeed() takes a single arg, a double,
+ * and should be in the range +1.0 to -1.0 where +1.0 is full speed in
+ * a CW direction, -1.0 is full speed in a CCW direction and 0 is stopped.
+ */
+
+// Create a motor "A" driven by a TLE5206 on pins 21 and 22.
+SimpleTLE5206Output Ain1(p21);      // TLE5206 In1 is connected to p21
+SimpleTLE5206Output Ain2(p22);      // TLE5206 In2 is connected to p22
+SimpleTLE5206 motorA(&Ain1, &Ain2); // Create the TLE5206 controller using these pins.
+
+// Create a motor "B" driven by a TLE5206 but on LEDs as a mimic.
+SimpleTLE5206Output Bin1(LED3);     // TLE5206 In1 is connected to LED3
+SimpleTLE5206Output Bin2(LED4);     // TLE5206 In2 is connected to LED4
+SimpleTLE5206 motorB(&Bin1, &Bin2); // Create the TLE5206 controller using these pins.
+
+DigitalOut myled(LED1);
+
+Ticker myLedFlasher;
+
+void myLedFlasherCallback(void) {
+    myled = !myled;
+}
+
+int main() {
+    double speed;
+    
+    pc.baud(115200);
+
+    // Just flashes LED1 similar to a normal initial Mbed program.
+    myLedFlasher.attach(myLedFlasherCallback, 0.2);
+
+    // The main loop just demos a linear ramp up/ramp down repeatedly.
+    while(1) {    
+        motorA.setSpeed(0);
+        motorB.setSpeed(0);
+    
+        wait(2);
+        
+        // Go from zero to +1.0 (+1.0 is full speed)
+        pc.printf("Going from zero to full CW speed...");
+        for(speed = 0.0; speed <= 1.0; speed += 0.005) {
+            if (speed > 1.0)  speed =  1.0; // Never let the speed go over 1!
+            if (speed < -1.0) speed = -1.0; // Never let the speed go below -1!
+            motorA.setSpeed(speed);
+            motorB.setSpeed(speed);
+            wait(0.05);
+        }
+        pc.printf(" done.\n");
+    
+        // Hold the motor at full speed for 5seconds.
+        wait(2);
+        
+        // Now slow the motor down to zero and then reverse direction to -1.0 
+        pc.printf("Going from full CW speed to full CCW speed...");
+        for( ; speed >= -1.0; speed -= 0.005) {
+            if (speed > 1.0)  speed =  1.0; // Never let the speed go over 1!
+            if (speed < -1.0) speed = -1.0; // Never let the speed go below -1!
+            motorA.setSpeed(speed);
+            motorB.setSpeed(speed);
+            wait(0.05);
+        }
+        pc.printf(" done.\n");
+    
+        // Hold the motor at full speed in ccw for 5seconds.
+        wait(2);
+        
+        // Now bring the motor to a stop.
+        pc.printf("Bringing the motor to a halt...");
+        for( ; speed <= 0.0; speed += 0.005) {
+            if (speed > 1.0)  speed =  1.0; // Never let the speed go over 1!
+            if (speed < -1.0) speed = -1.0; // Never let the speed go below -1!
+            motorA.setSpeed(speed);
+            motorB.setSpeed(speed);
+            wait(0.05);
+        }
+        pc.printf(" done.\n");
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/SimpleTLE5206.cpp	Tue Jul 05 07:43:28 2011 +0000
@@ -0,0 +1,139 @@
+/*
+    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.
+*/
+
+
+#include "mbed.h"
+#include "SimpleTLE5206.h"
+
+namespace AjK {
+
+SimpleTLE5206::SimpleTLE5206(SimpleTLE5206Output *in1, SimpleTLE5206Output *in2)
+{
+    // Start initially as GPIO and both on (no drive, no speed).
+    _in1 = in1;
+    _in2 = in2;
+    init();
+}
+
+void
+SimpleTLE5206::init()
+{
+    setDuty(240000UL);
+    setSpeed(0.0);
+}
+
+void
+SimpleTLE5206::setDuty(uint32_t duty)
+{
+    // Ensure powered up (default is 1)  
+    LPC_SC->PCONP |= (1UL << 6);  
+        
+    // CCLK/4 = 24MHz
+    LPC_SC->PCLKSEL0 &= ~(3UL << 12);
+    
+    // Reset.
+    LPC_PWM1->TCR   = 2; 
+    
+    _duty = duty;
+    
+    LPC_PWM1->PR    = 0;
+    LPC_PWM1->MR0   = _duty;
+    LPC_PWM1->MR1   = 0;
+    LPC_PWM1->MR2   = 0;
+    LPC_PWM1->MR3   = 0;
+    LPC_PWM1->MR4   = 0;
+    LPC_PWM1->MR5   = 0;
+    LPC_PWM1->MR6   = 0;
+        
+    LPC_PWM1->MCR   = 2; // MR0 resets TC.
+        
+    LPC_PWM1->TCR   = 9; // Enable.        
+}
+
+void
+SimpleTLE5206::setSpeed(double speed)
+{
+    uint32_t value;
+
+    // Ensure we cap the speed to +/-1.0
+    if (speed > +1.0) speed = +1.0;
+    if (speed < -1.0) speed = -1.0;
+        
+    if (speed == 0) {
+        _in1->as_gpio();
+        _in2->as_gpio();
+        _in1->write(1);    
+        _in2->write(1);    
+    }
+    else {
+        if (speed > 0.0) {
+            // Check the outputs are configured for the direction requested. 
+            if (_in1->get_pin_type() != SimpleTLE5206Output::IsGPIO) _in1->as_gpio();                
+            if (_in2->get_pin_type() != SimpleTLE5206Output::IsPWM)  _in2->as_pwm();                
+        }
+        
+        if (speed < 0.0) {
+            // Check the outputs are configured for the direction requested. 
+            if (_in1->get_pin_type() != SimpleTLE5206Output::IsPWM)  _in1->as_pwm();                
+            if (_in2->get_pin_type() != SimpleTLE5206Output::IsGPIO) _in2->as_gpio();  
+            speed *= -1; // invert sign.              
+        }
+    
+        value = (uint32_t)(speed * _duty);      // Scale for requested speed.
+        if (value >= _duty) value = _duty - 1;  // Don't allow the value to overrun the duty.
+        value = _duty - value;                  // Invert logic sense.
+        
+        switch(_in1->getPin()) {
+            case p21:            setMRx(Pwm6, value); break;
+            case p22:            setMRx(Pwm5, value); break;
+            case p23: case LED4: setMRx(Pwm4, value); break;
+            case p24: case LED3: setMRx(Pwm3, value); break;
+            case p25: case LED2: setMRx(Pwm2, value); break;
+            case p26: case LED1: setMRx(Pwm1, value); break;                          
+        }
+        
+        switch(_in2->getPin()) {
+            case p21:            setMRx(Pwm6, value); break;
+            case p22:            setMRx(Pwm5, value); break;
+            case p23: case LED4: setMRx(Pwm4, value); break;
+            case p24: case LED3: setMRx(Pwm3, value); break;
+            case p25: case LED2: setMRx(Pwm2, value); break;
+            case p26: case LED1: setMRx(Pwm1, value); break;                          
+        }
+    }
+}
+
+void 
+SimpleTLE5206::setMRx(PwmCh ch, uint32_t value) 
+{
+    switch(ch) {
+        case Pwm1: LPC_PWM1->MR1 = value; break;
+        case Pwm2: LPC_PWM1->MR2 = value; break;
+        case Pwm3: LPC_PWM1->MR3 = value; break;
+        case Pwm4: LPC_PWM1->MR4 = value; break;
+        case Pwm5: LPC_PWM1->MR5 = value; break;
+        case Pwm6: LPC_PWM1->MR6 = value; break;        
+    }
+    LPC_PWM1->LER |= (1UL << ch);
+}
+
+}; // namespace AjK ends.