This library allows control of the TLC5940 PWM driver IC. It supports both normal operation and controlling multiplexed displays.
TLC5940.cpp@0:be9399a34b15, 2013-05-20 (annotated)
- Committer:
- Spencer
- Date:
- Mon May 20 19:07:01 2013 +0000
- Revision:
- 0:be9399a34b15
- Child:
- 2:69e40ccf506f
This library allows control of the TLC5940 PWM driver IC.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Spencer | 0:be9399a34b15 | 1 | #include "TLC5940.h" |
Spencer | 0:be9399a34b15 | 2 | |
Spencer | 0:be9399a34b15 | 3 | TLC5940::TLC5940(PinName SCLK, PinName MOSI, PinName GSCLK, PinName BLANK, |
Spencer | 0:be9399a34b15 | 4 | PinName XLAT, PinName DCPRG, PinName VPRG, const int number) : number(number), |
Spencer | 0:be9399a34b15 | 5 | spi(MOSI, NC, SCLK), |
Spencer | 0:be9399a34b15 | 6 | gsclk(GSCLK), |
Spencer | 0:be9399a34b15 | 7 | blank(BLANK), |
Spencer | 0:be9399a34b15 | 8 | xlat(XLAT), |
Spencer | 0:be9399a34b15 | 9 | dcprg(DCPRG), |
Spencer | 0:be9399a34b15 | 10 | vprg(VPRG), |
Spencer | 0:be9399a34b15 | 11 | newGSData(false), |
Spencer | 0:be9399a34b15 | 12 | newDCData(false), |
Spencer | 0:be9399a34b15 | 13 | need_xlat(false) |
Spencer | 0:be9399a34b15 | 14 | { |
Spencer | 0:be9399a34b15 | 15 | // Configure SPI to 12 bits and SPI_SPEED |
Spencer | 0:be9399a34b15 | 16 | spi.format(12, 0); |
Spencer | 0:be9399a34b15 | 17 | spi.frequency(SPI_SPEED); |
Spencer | 0:be9399a34b15 | 18 | |
Spencer | 0:be9399a34b15 | 19 | // Set output pin states |
Spencer | 0:be9399a34b15 | 20 | dcprg = 0; |
Spencer | 0:be9399a34b15 | 21 | vprg = 0; |
Spencer | 0:be9399a34b15 | 22 | xlat = 0; |
Spencer | 0:be9399a34b15 | 23 | blank = 1; |
Spencer | 0:be9399a34b15 | 24 | |
Spencer | 0:be9399a34b15 | 25 | // Call the reset function every 4096 PWM outputs |
Spencer | 0:be9399a34b15 | 26 | reset_ticker.attach_us(this, &TLC5940::reset, (1000000.0/GSCLK_SPEED) * 4096.0); |
Spencer | 0:be9399a34b15 | 27 | |
Spencer | 0:be9399a34b15 | 28 | // Configure FastPWM output for GSCLK frequency at 50% duty cycle |
Spencer | 0:be9399a34b15 | 29 | gsclk.period_us(1000000.0/GSCLK_SPEED); |
Spencer | 0:be9399a34b15 | 30 | gsclk.write(.5); |
Spencer | 0:be9399a34b15 | 31 | } |
Spencer | 0:be9399a34b15 | 32 | |
Spencer | 0:be9399a34b15 | 33 | void TLC5940::setNewGSData(unsigned short* data) |
Spencer | 0:be9399a34b15 | 34 | { |
Spencer | 0:be9399a34b15 | 35 | gsBuffer = data; |
Spencer | 0:be9399a34b15 | 36 | |
Spencer | 0:be9399a34b15 | 37 | // Tell reset function that new GS data has been given |
Spencer | 0:be9399a34b15 | 38 | newGSData = true; |
Spencer | 0:be9399a34b15 | 39 | } |
Spencer | 0:be9399a34b15 | 40 | |
Spencer | 0:be9399a34b15 | 41 | void TLC5940::setNewDCData(unsigned char* data) |
Spencer | 0:be9399a34b15 | 42 | { |
Spencer | 0:be9399a34b15 | 43 | dcBuffer = data; |
Spencer | 0:be9399a34b15 | 44 | |
Spencer | 0:be9399a34b15 | 45 | // Tell reset function that new DC data has been given |
Spencer | 0:be9399a34b15 | 46 | newDCData = true; |
Spencer | 0:be9399a34b15 | 47 | } |
Spencer | 0:be9399a34b15 | 48 | |
Spencer | 0:be9399a34b15 | 49 | void TLC5940::reset() |
Spencer | 0:be9399a34b15 | 50 | { |
Spencer | 0:be9399a34b15 | 51 | // Turn off LEDs |
Spencer | 0:be9399a34b15 | 52 | blank = 1; |
Spencer | 0:be9399a34b15 | 53 | |
Spencer | 0:be9399a34b15 | 54 | // Latch in data from previous cycle if needed |
Spencer | 0:be9399a34b15 | 55 | if (need_xlat) |
Spencer | 0:be9399a34b15 | 56 | { |
Spencer | 0:be9399a34b15 | 57 | // Latch |
Spencer | 0:be9399a34b15 | 58 | xlat = 1; |
Spencer | 0:be9399a34b15 | 59 | xlat = 0; |
Spencer | 0:be9399a34b15 | 60 | |
Spencer | 0:be9399a34b15 | 61 | // Don't need to latch again |
Spencer | 0:be9399a34b15 | 62 | need_xlat = false; |
Spencer | 0:be9399a34b15 | 63 | } |
Spencer | 0:be9399a34b15 | 64 | |
Spencer | 0:be9399a34b15 | 65 | // Virtual function that allows the next data chunk to be set after every GSCLK cycle |
Spencer | 0:be9399a34b15 | 66 | // Useful for setting the next frame when multiplexing (e.g. LED matrices) |
Spencer | 0:be9399a34b15 | 67 | setNextData(); |
Spencer | 0:be9399a34b15 | 68 | |
Spencer | 0:be9399a34b15 | 69 | // Reset the screen so that it is updating while data is being sent |
Spencer | 0:be9399a34b15 | 70 | blank = 0; |
Spencer | 0:be9399a34b15 | 71 | |
Spencer | 0:be9399a34b15 | 72 | |
Spencer | 0:be9399a34b15 | 73 | // Do we have new DC data to send? |
Spencer | 0:be9399a34b15 | 74 | if (newDCData) |
Spencer | 0:be9399a34b15 | 75 | { |
Spencer | 0:be9399a34b15 | 76 | // Set TLC5940 to accpet DC data |
Spencer | 0:be9399a34b15 | 77 | vprg = 1; |
Spencer | 0:be9399a34b15 | 78 | |
Spencer | 0:be9399a34b15 | 79 | // Get DC data from registers instead of EEPROM (since we are sending data to the registers now) |
Spencer | 0:be9399a34b15 | 80 | dcprg = 1; |
Spencer | 0:be9399a34b15 | 81 | |
Spencer | 0:be9399a34b15 | 82 | // Send DC data backwards - this makes the DC_buffer[0] index correspond to OUT0 |
Spencer | 0:be9399a34b15 | 83 | for (int i = (16 * number) - 1; i >= 0; i--) |
Spencer | 0:be9399a34b15 | 84 | { |
Spencer | 0:be9399a34b15 | 85 | // Assemble a 12 bit packet from two 6 bit chunks |
Spencer | 0:be9399a34b15 | 86 | spi.write(((dcBuffer[i] & 0x3F) << 6) | (dcBuffer[i-1] & 0x3F)); |
Spencer | 0:be9399a34b15 | 87 | i--; |
Spencer | 0:be9399a34b15 | 88 | } |
Spencer | 0:be9399a34b15 | 89 | |
Spencer | 0:be9399a34b15 | 90 | // Latch |
Spencer | 0:be9399a34b15 | 91 | xlat = 1; |
Spencer | 0:be9399a34b15 | 92 | xlat = 0; |
Spencer | 0:be9399a34b15 | 93 | |
Spencer | 0:be9399a34b15 | 94 | // No new data to send (we just sent it!) |
Spencer | 0:be9399a34b15 | 95 | newDCData = false; |
Spencer | 0:be9399a34b15 | 96 | } |
Spencer | 0:be9399a34b15 | 97 | |
Spencer | 0:be9399a34b15 | 98 | // Do we have new GS data to send? |
Spencer | 0:be9399a34b15 | 99 | if (newGSData) |
Spencer | 0:be9399a34b15 | 100 | { |
Spencer | 0:be9399a34b15 | 101 | // Set TLC5940 to accept GS data |
Spencer | 0:be9399a34b15 | 102 | vprg = 0; |
Spencer | 0:be9399a34b15 | 103 | |
Spencer | 0:be9399a34b15 | 104 | // Send GS data backwards - this makes the GS_buffer[0] index correspond to OUT0 |
Spencer | 0:be9399a34b15 | 105 | for (int i = (16 * number) - 1; i >= 0; i--) |
Spencer | 0:be9399a34b15 | 106 | { |
Spencer | 0:be9399a34b15 | 107 | // Get the lower 12 bits of the buffer and send |
Spencer | 0:be9399a34b15 | 108 | spi.write(gsBuffer[i] & 0xFFF); |
Spencer | 0:be9399a34b15 | 109 | } |
Spencer | 0:be9399a34b15 | 110 | |
Spencer | 0:be9399a34b15 | 111 | // Latch after current GS data is done being displayed |
Spencer | 0:be9399a34b15 | 112 | need_xlat = true; |
Spencer | 0:be9399a34b15 | 113 | |
Spencer | 0:be9399a34b15 | 114 | // No new data to send (we just sent it!) |
Spencer | 0:be9399a34b15 | 115 | newGSData = false; |
Spencer | 0:be9399a34b15 | 116 | } |
Spencer | 0:be9399a34b15 | 117 | } |