Library for using the TLC5940 as a servo controller.

Dependencies:   FastPWM

Dependents:   TLC5940ServoTest

TLC5940Servo.h

Committer:
dudanian
Date:
2014-10-21
Revision:
6:b001282e967b
Parent:
5:56daa8c0697d

File content as of revision 6:b001282e967b:

#ifndef TLC5940Servo_H
#define TLC5940Servo_H

#include "FastPWM.h"

/**
  * SPI speed used by the mbed to communicate with the TLC5940
  * The TLC5940 supports up to 30Mhz. This should be kept as high
  * as possible to ensure that data has time to be sent each reset cycle.
  */
#define SPI_SPEED 30000000

/**
  * The rate at which the GSCLK pin is pulsed
  * This also controls how often the reset function is called
  * The rate at which the reset function is called can be calculated by: (1/GSCLK_SPEED) * 4096
  *
  * Since the Servo period is 20ms (50Hz), we set this clock to 50*4096 = 204,800Hz according to the equation above
  * Also, since this clock is so slow, there is almost no limit to the number of TLC5940s you can chain
  */
#define GSCLK_SPEED 204800

/**
  *  This class controls a TLC5940 PWM driver to control Servo motors. It supports sending grayscale PWM data calibrated for Servos,
  *  but it does not support error checking or writing the EEPROM. After 4096 pulses, the private member funciton reset is called by
  *  the ticker. It resets the driver by pulsing the BLANK pin. If new data has been set to be sent by the function setNewData, it
  *  is sent here.
  *  
  *  This class is a heavily modified versoin of the TLC5940 library created by Spencer Davis. This class also uses the FastPWM
  *  library by Erik Olieman to continuously pulse the GSLCK pin without CPU intervention. 
  */
class TLC5940Servo {
public:
    /* 
     * Servo inner class to abstract some of the details. Based off of the mbed official Servo class
     */
    class Servo {
    public:
        /**
         * Creat a servo object NOT connected to a specific PwmOut pin
         */
        Servo();

        /** 
         * Set the servo position, normalised to it's full range
         *
         * @param percent A normalised number 0.0-1.0 to represent the full range.
         */
        void write(float percent);

        /**  
         * Read the servo motors current position
         *
         * @param returns A normalised number 0.0-1.0  representing the full range.
         */
        float read();
        
        /** 
         * Set the servo position
         *
         * @param degrees Servo position in degrees
         */
        void position(float degrees);
    
        /**
         * Allows calibration of the range and angles for a particular servo
         *
         * @param range Pulsewidth range from center (1.5ms) to maximum/minimum position in seconds
         * @param degrees Angle from centre to maximum/minimum position in degrees
         */
        void calibrate(float range=0.0005, float degrees=45.0);
        
        /**
         * Read the servo motors current TLC5940 pw value
         */
        int pulsewidth();
        
        /**  Shorthand for the write and read functions */
        Servo& operator= (float percent);
        Servo& operator= (Servo& rhs);
        operator float();
    private:
        float _range;
        float _degrees;
        float _p;
        int _pw;
    };

    /**
      * Set up the TLC5940
      *
      * @param MOSI - The MOSI pin of the SPI bus
      * @param SCLK - The SCK pin of the SPI bus
      * @param XLAT - The XLAT pin of the TLC5940(s)
      * @param BLANK - The BLANK pin of the TLC5940(s)
      * @param GSCLK - The GSCLK pin of the TLC5940(s)
      * @param number - The number of TLC5940s (optional)
      */
    TLC5940Servo(PinName MOSI, PinName SCLK, PinName XLAT, PinName BLANK,
                 PinName GSCLK, const int number = 1);

    /**
     * Destructor used to delete memory
     */
    ~TLC5940Servo();

    /**
     * Allows calibration of the range and angles for all servos
     *
     * @param range Pulsewidth range from center (1.5ms) to maximum/minimum position in seconds
     * @param degrees Angle from centre to maximum/minimum position in degrees
     */
    void calibrate(float range, float degrees);

    /**
      * Array index operator for reading and writing from servos
      *
      * @param index Index of Servo in array
      */
    Servo& operator[](int index);

private:
    // SPI port - only MOSI and SCK are used
    SPI spi;

    // PWM output using the FastPWM library by Erik Olieman
    FastPWM gsclk;

    // Digital out pins used for the TLC5940
    DigitalOut blank;
    DigitalOut xlat;

    // Number of TLC5940s in series
    const int number;

    // Call a reset function to manage sending data and GSCLK updating
    Ticker reset_ticker;

    // Has new data been loaded?
    volatile bool newData;

    // Do we need to send an XLAT pulse? (Was GS data clocked in last reset?)
    volatile bool need_xlat;

    // Buffers to store data until it is sent
    Servo* servos;

    // Function to reset the display and send the next chunks of data
    void reset();
};

#endif