Library for using the TLC5940 as a servo controller.
TLC5940Servo.cpp
- Committer:
- dudanian
- Date:
- 2014-10-21
- Revision:
- 6:b001282e967b
- Parent:
- 5:56daa8c0697d
File content as of revision 6:b001282e967b:
#include "TLC5940Servo.h" TLC5940Servo::TLC5940Servo(PinName MOSI, PinName SCLK, PinName XLAT, PinName BLANK, PinName GSCLK, const int number) : number(number), spi(MOSI, NC, SCLK), gsclk(GSCLK), blank(BLANK), xlat(XLAT), newData(false), need_xlat(false) { spi.format(12, 0); spi.frequency(SPI_SPEED); xlat = 0; blank = 1; reset_ticker.attach_us(this, &TLC5940Servo::reset, (1000000.0/GSCLK_SPEED) * 4096.0); gsclk.period_us(1000000.0/GSCLK_SPEED); gsclk.write(.5); servos = new Servo[16 * number]; } TLC5940Servo::~TLC5940Servo() { delete[] servos; } void TLC5940Servo::calibrate(float range, float degrees) { for (int i = 0; i < 16 * number; i++) servos[i].calibrate(range, degrees); } TLC5940Servo::Servo& TLC5940Servo::operator[](int index) { newData = true; return servos[index]; } // most complicated method, heavily commented void TLC5940Servo::reset() { gsclk.write(0); // turn off gsclk blank = 1; // start reset // latch data if new data was written if (need_xlat) { xlat = 1; xlat = 0; need_xlat = false; } blank = 0; // turn off reset gsclk.write(.5); // restart gsclk if (newData) { // Send data backwards - this makes servos[0] index correspond to OUT0 for (int i = (16 * number) - 1; i >= 0; i--) { // Get the lower 12 bits of the buffer and send spi.write(servos[i].pulsewidth() & 0xFFF); } // Latch after current GS data is done being displayed need_xlat = true; // No new data to send (we just sent it!) newData = false; } } /** * TLC5940 Inner Servo class * * Helps to abstract some of the details away */ static float clamp(float value, float min, float max) { if(value < min) { return min; } else if(value > max) { return max; } else { return value; } } TLC5940Servo::Servo::Servo() { calibrate(); write(0.5); } void TLC5940Servo::Servo::write(float percent) { float offset = _range * 2.0 * (percent - 0.5); _pw = (int)(4095 - ((0.0015 + clamp(offset, -_range, _range))/0.02 * 4096.0)); _p = clamp(percent, 0.0, 1.0); } void TLC5940Servo::Servo::position(float degrees) { float offset = _range * (degrees / _degrees); _pw = (int)(4095 - ((0.0015 + clamp(offset, -_range, _range))/0.02 * 4096.0)); } void TLC5940Servo::Servo::calibrate(float range, float degrees) { _range = range; _degrees = degrees; } float TLC5940Servo::Servo::read() { return _p; } int TLC5940Servo::Servo::pulsewidth() { return _pw; } TLC5940Servo::Servo& TLC5940Servo::Servo::operator= (float percent) { write(percent); return *this; } TLC5940Servo::Servo& TLC5940Servo::Servo::operator= (TLC5940Servo::Servo& rhs) { write(rhs.read()); return *this; } TLC5940Servo::Servo::operator float() { return read(); }