Pinscape Controller version 1 fork. This is a fork to allow for ongoing bug fixes to the original controller version, from before the major changes for the expansion board project.

Dependencies:   FastIO FastPWM SimpleDMA mbed

Fork of Pinscape_Controller by Mike R

Committer:
mjr
Date:
Mon Feb 15 23:03:55 2016 +0000
Revision:
68:edfecf67a931
Parent:
33:d832bcab089e
Child:
38:091e511ce8a0
Finalize USB library updates to fix compatibility problems introduced in USBHAL_KL25Z overhaul.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 26:cb71c4af2912 1 // Pinscape Controller TLC5940 interface
mjr 26:cb71c4af2912 2 //
mjr 26:cb71c4af2912 3 // Based on Spencer Davis's mbed TLC5940 library. Adapted for the
mjr 26:cb71c4af2912 4 // KL25Z, and simplified to just the functions needed for this
mjr 26:cb71c4af2912 5 // application. In particular, this version doesn't include support
mjr 26:cb71c4af2912 6 // for dot correction programming or status input. This version also
mjr 26:cb71c4af2912 7 // uses a different approach for sending the grayscale data updates,
mjr 26:cb71c4af2912 8 // sending updates during the blanking interval rather than overlapping
mjr 26:cb71c4af2912 9 // them with the PWM cycle. This results in very slightly longer
mjr 26:cb71c4af2912 10 // blanking intervals when updates are pending, effectively reducing
mjr 26:cb71c4af2912 11 // the PWM "on" duty cycle (and thus the output brightness) by about
mjr 26:cb71c4af2912 12 // 0.3%. This shouldn't be perceptible to users, so it's a small
mjr 26:cb71c4af2912 13 // trade-off for the advantage gained, which is much better signal
mjr 26:cb71c4af2912 14 // stability when using multiple TLC5940s daisy-chained together.
mjr 26:cb71c4af2912 15 // I saw a lot of instability when using the overlapped approach,
mjr 26:cb71c4af2912 16 // which seems to be eliminated entirely when sending updates during
mjr 26:cb71c4af2912 17 // the blanking interval.
mjr 26:cb71c4af2912 18
mjr 26:cb71c4af2912 19
mjr 26:cb71c4af2912 20 #ifndef TLC5940_H
mjr 26:cb71c4af2912 21 #define TLC5940_H
mjr 26:cb71c4af2912 22
mjr 33:d832bcab089e 23 // Should we do the grayscale update within the blanking interval?
mjr 33:d832bcab089e 24 // If this is set to 1, we'll send grayscale data during the blanking
mjr 33:d832bcab089e 25 // interval; if 0, we'll send grayscale during the PWM cycle.
mjr 33:d832bcab089e 26 // Mode 0 is the *intended* way of using these chips, but mode 1
mjr 33:d832bcab089e 27 // produces a more stable signal in my test setup.
mjr 33:d832bcab089e 28 //
mjr 33:d832bcab089e 29 // In my breadboard testing, using the standard data-during-PWM
mjr 33:d832bcab089e 30 // mode causes some amount of signal instability with multiple
mjr 33:d832bcab089e 31 // daisy-chained TLC5940's. It appears that there's some signal
mjr 33:d832bcab089e 32 // interference (maybe RF or electrical ringing in the wires) that
mjr 33:d832bcab089e 33 // can make the bit data and/or clock prone to noise that causes
mjr 33:d832bcab089e 34 // random bits to propagate down the daisy chain. This happens
mjr 33:d832bcab089e 35 // frequently enough in my breadboard setup to be visible as
mjr 33:d832bcab089e 36 // regular flicker. Careful wiring, short wire runs, and decoupling
mjr 33:d832bcab089e 37 // capacitors noticeably improve it, but I haven't been able to
mjr 33:d832bcab089e 38 // eliminate it entirely in my test setup. Using the data-during-
mjr 33:d832bcab089e 39 // blanking mode, however, *does* eliminate it entirely.
mjr 33:d832bcab089e 40 //
mjr 33:d832bcab089e 41 // It clearly should be possible to eliminate the signal problems
mjr 33:d832bcab089e 42 // in a well-designed PCB layout, but for the time being, I'm
mjr 33:d832bcab089e 43 // making data-during-blanking the default, since it provides
mjr 33:d832bcab089e 44 // such a noticeable improvement in my test setup, and the cost
mjr 33:d832bcab089e 45 // is minimal. The cost is that it lengthens the blanking interval
mjr 33:d832bcab089e 46 // slightly. With four chips and the SPI clock at 28MHz, the
mjr 33:d832bcab089e 47 // full data update takes 27us; with the PWM clock at 500kHz, the
mjr 33:d832bcab089e 48 // grayscale cycle is 8192us. This means that the 27us data send
mjr 33:d832bcab089e 49 // keeps the BLANK asserted for an additional 0.3% of the cycle
mjr 33:d832bcab089e 50 // time, which in term reduces output brightness by the same amount.
mjr 33:d832bcab089e 51 // This brightness reduction isn't noticeable on its own, but it
mjr 33:d832bcab089e 52 // can be seen as a flicker on data cycles if we send data on
mjr 33:d832bcab089e 53 // some blanking cycles but not on others. To eliminate the
mjr 33:d832bcab089e 54 // flicker, the code sends a data update on *every* cycle when
mjr 33:d832bcab089e 55 // using this mode to ensure that the 0.3% brightness reduction
mjr 33:d832bcab089e 56 // is uniform across time.
mjr 33:d832bcab089e 57 //
mjr 33:d832bcab089e 58 // When using this code with TLC5940 chips on a PCB, I recommend
mjr 33:d832bcab089e 59 // doing a test: set this to 0, run the board, turn on all outputs
mjr 33:d832bcab089e 60 // (connected to LEDs), and observe the results. If you don't
mjr 33:d832bcab089e 61 // see any randomness or flicker in a minute or two of observation,
mjr 33:d832bcab089e 62 // you're getting a good clean signal throughout the daisy chain
mjr 33:d832bcab089e 63 // and don't need the workaround. If you do see any instability,
mjr 33:d832bcab089e 64 // set this back to 1.
mjr 33:d832bcab089e 65 #define DATA_UPDATE_INSIDE_BLANKING 1
mjr 33:d832bcab089e 66
mjr 26:cb71c4af2912 67 #include "mbed.h"
mjr 26:cb71c4af2912 68 #include "FastPWM.h"
mjr 30:6e9902f06f48 69 #include "SimpleDMA.h"
mjr 26:cb71c4af2912 70
mjr 26:cb71c4af2912 71 /**
mjr 26:cb71c4af2912 72 * SPI speed used by the mbed to communicate with the TLC5940
mjr 26:cb71c4af2912 73 * The TLC5940 supports up to 30Mhz. It's best to keep this as
mjr 33:d832bcab089e 74 * high as possible, since a higher SPI speed yields a faster
mjr 33:d832bcab089e 75 * grayscale data update. However, I've seen some slight
mjr 33:d832bcab089e 76 * instability in the signal in my breadboard setup using the
mjr 33:d832bcab089e 77 * full 30MHz, so I've reduced this slightly, which seems to
mjr 33:d832bcab089e 78 * yield a solid signal. The limit will vary according to how
mjr 33:d832bcab089e 79 * clean the signal path is to the chips; you can probably crank
mjr 33:d832bcab089e 80 * this up to full speed if you have a well-designed PCB, good
mjr 33:d832bcab089e 81 * decoupling capacitors near the 5940 VCC/GND pins, and short
mjr 33:d832bcab089e 82 * wires between the KL25Z and the PCB. A short, clean path to
mjr 33:d832bcab089e 83 * KL25Z ground seems especially important.
mjr 26:cb71c4af2912 84 *
mjr 26:cb71c4af2912 85 * The SPI clock must be fast enough that the data transmission
mjr 26:cb71c4af2912 86 * time for a full update is comfortably less than the blanking
mjr 26:cb71c4af2912 87 * cycle time. The grayscale refresh requires 192 bits per TLC5940
mjr 26:cb71c4af2912 88 * in the daisy chain, and each bit takes one SPI clock to send.
mjr 26:cb71c4af2912 89 * Our reference setup in the Pinscape controller allows for up to
mjr 26:cb71c4af2912 90 * 4 TLC5940s, so a full refresh cycle on a fully populated system
mjr 26:cb71c4af2912 91 * would be 768 SPI clocks. The blanking cycle is 4096 GSCLK cycles.
mjr 26:cb71c4af2912 92 *
mjr 26:cb71c4af2912 93 * t(blank) = 4096 * 1/GSCLK_SPEED
mjr 26:cb71c4af2912 94 * t(refresh) = 768 * 1/SPI_SPEED
mjr 26:cb71c4af2912 95 * Therefore: SPI_SPEED must be > 768/4096 * GSCLK_SPEED
mjr 26:cb71c4af2912 96 *
mjr 26:cb71c4af2912 97 * Since the SPI speed can be so high, and since we want to keep
mjr 26:cb71c4af2912 98 * the GSCLK speed relatively low, the constraint above simply
mjr 26:cb71c4af2912 99 * isn't a factor. E.g., at SPI=30MHz and GSCLK=500kHz,
mjr 26:cb71c4af2912 100 * t(blank) is 8192us and t(refresh) is 25us.
mjr 26:cb71c4af2912 101 */
mjr 33:d832bcab089e 102 #define SPI_SPEED 2800000
mjr 26:cb71c4af2912 103
mjr 26:cb71c4af2912 104 /**
mjr 26:cb71c4af2912 105 * The rate at which the GSCLK pin is pulsed. This also controls
mjr 26:cb71c4af2912 106 * how often the reset function is called. The reset function call
mjr 26:cb71c4af2912 107 * rate is (1/GSCLK_SPEED) * 4096. The maximum reliable rate is
mjr 26:cb71c4af2912 108 * around 32Mhz. It's best to keep this rate as low as possible:
mjr 26:cb71c4af2912 109 * the higher the rate, the higher the refresh() call frequency,
mjr 26:cb71c4af2912 110 * so the higher the CPU load.
mjr 26:cb71c4af2912 111 *
mjr 26:cb71c4af2912 112 * The lower bound is probably dependent on the application. For
mjr 26:cb71c4af2912 113 * driving LEDs, the limiting factor is that lower rates will increase
mjr 26:cb71c4af2912 114 * visible flicker. 200 kHz seems to be a good lower bound for LEDs.
mjr 26:cb71c4af2912 115 * That provides about 48 cycles per second - that's about the same as
mjr 26:cb71c4af2912 116 * the 50 Hz A/C cycle rate in many countries, which was itself chosen
mjr 26:cb71c4af2912 117 * so that incandescent lights don't flicker. (This rate is a function
mjr 26:cb71c4af2912 118 * of human eye physiology, which has its own refresh cycle of sorts
mjr 26:cb71c4af2912 119 * that runs at about 50 Hz. If you're designing an LED system for
mjr 26:cb71c4af2912 120 * viewing by cats or drosophila, you might want to look into your
mjr 26:cb71c4af2912 121 * target species' eye physiology, since the persistence of vision
mjr 26:cb71c4af2912 122 * rate varies quite a bit from species to species.) Flicker tends to
mjr 26:cb71c4af2912 123 * be more noticeable in LEDs than in incandescents, since LEDs don't
mjr 26:cb71c4af2912 124 * have the thermal inertia of incandescents, so we use a slightly
mjr 26:cb71c4af2912 125 * higher default here. 500 kHz = 122 full grayscale cycles per
mjr 26:cb71c4af2912 126 * second = 122 reset calls per second (call every 8ms).
mjr 26:cb71c4af2912 127 */
mjr 26:cb71c4af2912 128 #define GSCLK_SPEED 500000
mjr 26:cb71c4af2912 129
mjr 26:cb71c4af2912 130 /**
mjr 26:cb71c4af2912 131 * This class controls a TLC5940 PWM driver IC.
mjr 26:cb71c4af2912 132 *
mjr 26:cb71c4af2912 133 * Using the TLC5940 class to control an LED:
mjr 26:cb71c4af2912 134 * @code
mjr 26:cb71c4af2912 135 * #include "mbed.h"
mjr 26:cb71c4af2912 136 * #include "TLC5940.h"
mjr 26:cb71c4af2912 137 *
mjr 26:cb71c4af2912 138 * // Create the TLC5940 instance
mjr 26:cb71c4af2912 139 * TLC5940 tlc(p7, p5, p21, p9, p10, p11, p12, 1);
mjr 26:cb71c4af2912 140 *
mjr 26:cb71c4af2912 141 * int main()
mjr 26:cb71c4af2912 142 * {
mjr 26:cb71c4af2912 143 * // Enable the first LED
mjr 26:cb71c4af2912 144 * tlc.set(0, 0xfff);
mjr 26:cb71c4af2912 145 *
mjr 26:cb71c4af2912 146 * while(1)
mjr 26:cb71c4af2912 147 * {
mjr 26:cb71c4af2912 148 * }
mjr 26:cb71c4af2912 149 * }
mjr 26:cb71c4af2912 150 * @endcode
mjr 26:cb71c4af2912 151 */
mjr 26:cb71c4af2912 152 class TLC5940
mjr 26:cb71c4af2912 153 {
mjr 26:cb71c4af2912 154 public:
mjr 26:cb71c4af2912 155 /**
mjr 26:cb71c4af2912 156 * Set up the TLC5940
mjr 26:cb71c4af2912 157 * @param SCLK - The SCK pin of the SPI bus
mjr 26:cb71c4af2912 158 * @param MOSI - The MOSI pin of the SPI bus
mjr 26:cb71c4af2912 159 * @param GSCLK - The GSCLK pin of the TLC5940(s)
mjr 26:cb71c4af2912 160 * @param BLANK - The BLANK pin of the TLC5940(s)
mjr 26:cb71c4af2912 161 * @param XLAT - The XLAT pin of the TLC5940(s)
mjr 26:cb71c4af2912 162 * @param nchips - The number of TLC5940s (if you are daisy chaining)
mjr 26:cb71c4af2912 163 */
mjr 26:cb71c4af2912 164 TLC5940(PinName SCLK, PinName MOSI, PinName GSCLK, PinName BLANK, PinName XLAT, int nchips)
mjr 26:cb71c4af2912 165 : spi(MOSI, NC, SCLK),
mjr 26:cb71c4af2912 166 gsclk(GSCLK),
mjr 26:cb71c4af2912 167 blank(BLANK),
mjr 26:cb71c4af2912 168 xlat(XLAT),
mjr 33:d832bcab089e 169 nchips(nchips)
mjr 26:cb71c4af2912 170 {
mjr 33:d832bcab089e 171 // set XLAT to initially off
mjr 30:6e9902f06f48 172 xlat = 0;
mjr 33:d832bcab089e 173
mjr 33:d832bcab089e 174 // Assert BLANK while starting up, to keep the outputs turned off until
mjr 33:d832bcab089e 175 // everything is stable. This helps prevent spurious flashes during startup.
mjr 33:d832bcab089e 176 // (That's not particularly important for lights, but it matters more for
mjr 33:d832bcab089e 177 // tactile devices. It's a bit alarming to fire a replay knocker on every
mjr 33:d832bcab089e 178 // power-on, for example.)
mjr 30:6e9902f06f48 179 blank = 1;
mjr 30:6e9902f06f48 180
mjr 33:d832bcab089e 181 // allocate the grayscale buffer, and set all outputs to fully off
mjr 26:cb71c4af2912 182 gs = new unsigned short[nchips*16];
mjr 28:2097c6f8f2db 183 memset(gs, 0, nchips*16*sizeof(gs[0]));
mjr 26:cb71c4af2912 184
mjr 26:cb71c4af2912 185 // Configure SPI format and speed. Note that KL25Z ONLY supports 8-bit
mjr 26:cb71c4af2912 186 // mode. The TLC5940 nominally requires 12-bit data blocks for the
mjr 26:cb71c4af2912 187 // grayscale levels, but SPI is ultimately just a bit-level serial format,
mjr 26:cb71c4af2912 188 // so we can reformat the 12-bit blocks into 8-bit bytes to fit the
mjr 26:cb71c4af2912 189 // KL25Z's limits. This should work equally well on other microcontrollers
mjr 26:cb71c4af2912 190 // that are more flexible. The TLC5940 appears to require polarity/phase
mjr 26:cb71c4af2912 191 // format 0.
mjr 26:cb71c4af2912 192 spi.format(8, 0);
mjr 26:cb71c4af2912 193 spi.frequency(SPI_SPEED);
mjr 33:d832bcab089e 194
mjr 33:d832bcab089e 195 // Send out a full data set to the chips, to clear out any random
mjr 33:d832bcab089e 196 // startup data from the registers. Include some extra bits - there
mjr 33:d832bcab089e 197 // are some cases (such as after sending dot correct commands) where
mjr 33:d832bcab089e 198 // an extra bit per chip is required, and the initial state is
mjr 33:d832bcab089e 199 // somewhat unpredictable, so send extra just to make sure we cover
mjr 33:d832bcab089e 200 // all bases. This does no harm; extra bits just fall off the end of
mjr 33:d832bcab089e 201 // the daisy chain, and since we want all registers set to 0, we can
mjr 33:d832bcab089e 202 // send arbitrarily many extra 0's.
mjr 33:d832bcab089e 203 for (int i = 0 ; i < nchips*25 ; ++i)
mjr 33:d832bcab089e 204 spi.write(0);
mjr 33:d832bcab089e 205
mjr 33:d832bcab089e 206 // do an initial XLAT to latch all of these "0" values into the
mjr 33:d832bcab089e 207 // grayscale registers
mjr 33:d832bcab089e 208 xlat = 1;
mjr 33:d832bcab089e 209 xlat = 0;
mjr 29:582472d0bc57 210
mjr 30:6e9902f06f48 211 // Allocate a DMA buffer. The transfer on each cycle is 192 bits per
mjr 30:6e9902f06f48 212 // chip = 24 bytes per chip.
mjr 30:6e9902f06f48 213 dmabuf = new char[nchips*24];
mjr 26:cb71c4af2912 214
mjr 30:6e9902f06f48 215 // Set up the Simple DMA interface object. We use the DMA controller to
mjr 30:6e9902f06f48 216 // send grayscale data updates to the TLC5940 chips. This lets the CPU
mjr 30:6e9902f06f48 217 // keep running other tasks while we send gs updates, and importantly
mjr 30:6e9902f06f48 218 // allows our blanking interrupt handler return almost immediately.
mjr 30:6e9902f06f48 219 // The DMA transfer is from our internal DMA buffer to SPI0, which is
mjr 30:6e9902f06f48 220 // the SPI controller physically connected to the TLC5940s.
mjr 30:6e9902f06f48 221 sdma.source(dmabuf, 1);
mjr 30:6e9902f06f48 222 sdma.destination(&(SPI0->D), 0, 8);
mjr 30:6e9902f06f48 223 sdma.trigger(Trigger_SPI0_TX);
mjr 30:6e9902f06f48 224 sdma.attach(this, &TLC5940::dmaDone);
mjr 30:6e9902f06f48 225
mjr 30:6e9902f06f48 226 // Enable DMA on SPI0. SimpleDMA doesn't do this for us; we have to
mjr 30:6e9902f06f48 227 // do it explicitly. This is just a matter of setting bit 5 (TXDMAE)
mjr 30:6e9902f06f48 228 // in the SPI controllers Control Register 2 (C2).
mjr 30:6e9902f06f48 229 SPI0->C2 |= 0x20; // set bit 5 = 0x20 = TXDMAE in SPI0 control register 2
mjr 30:6e9902f06f48 230
mjr 30:6e9902f06f48 231 // Configure the GSCLK output's frequency
mjr 26:cb71c4af2912 232 gsclk.period(1.0/GSCLK_SPEED);
mjr 33:d832bcab089e 233
mjr 33:d832bcab089e 234 // mark that we need an initial update
mjr 33:d832bcab089e 235 newGSData = true;
mjr 33:d832bcab089e 236 needXlat = false;
mjr 30:6e9902f06f48 237 }
mjr 29:582472d0bc57 238
mjr 30:6e9902f06f48 239 // Start the clock running
mjr 29:582472d0bc57 240 void start()
mjr 29:582472d0bc57 241 {
mjr 26:cb71c4af2912 242 // Set up the first call to the reset function, which asserts BLANK to
mjr 26:cb71c4af2912 243 // end the PWM cycle and handles new grayscale data output and latching.
mjr 26:cb71c4af2912 244 // The original version of this library uses a timer to call reset
mjr 26:cb71c4af2912 245 // periodically, but that approach is somewhat problematic because the
mjr 26:cb71c4af2912 246 // reset function itself takes a small amount of time to run, so the
mjr 26:cb71c4af2912 247 // *actual* cycle is slightly longer than what we get from counting
mjr 26:cb71c4af2912 248 // GS clocks. Running reset on a timer therefore causes the calls to
mjr 26:cb71c4af2912 249 // slip out of phase with the actual full cycles, which causes
mjr 26:cb71c4af2912 250 // premature blanking that shows up as visible flicker. To get the
mjr 26:cb71c4af2912 251 // reset cycle to line up exactly with a full PWM cycle, it works
mjr 26:cb71c4af2912 252 // better to set up a new timer on each cycle, *after* we've finished
mjr 26:cb71c4af2912 253 // with the somewhat unpredictable overhead of the interrupt handler.
mjr 26:cb71c4af2912 254 // This ensures that we'll get much closer to exact alignment of the
mjr 26:cb71c4af2912 255 // cycle phase, and in any case the worst that happens is that some
mjr 26:cb71c4af2912 256 // cycles are very slightly too long or short (due to imperfections
mjr 26:cb71c4af2912 257 // in the timer clock vs the PWM clock that determines the GSCLCK
mjr 26:cb71c4af2912 258 // output to the TLC5940), which is far less noticeable than a
mjr 26:cb71c4af2912 259 // constantly rotating phase misalignment.
mjr 26:cb71c4af2912 260 reset_timer.attach(this, &TLC5940::reset, (1.0/GSCLK_SPEED)*4096.0);
mjr 26:cb71c4af2912 261 }
mjr 26:cb71c4af2912 262
mjr 26:cb71c4af2912 263 ~TLC5940()
mjr 26:cb71c4af2912 264 {
mjr 26:cb71c4af2912 265 delete [] gs;
mjr 30:6e9902f06f48 266 delete [] dmabuf;
mjr 26:cb71c4af2912 267 }
mjr 26:cb71c4af2912 268
mjr 26:cb71c4af2912 269 /**
mjr 26:cb71c4af2912 270 * Set the next chunk of grayscale data to be sent
mjr 26:cb71c4af2912 271 * @param data - Array of 16 bit shorts containing 16 12 bit grayscale data chunks per TLC5940
mjr 26:cb71c4af2912 272 * @note These must be in intervals of at least (1/GSCLK_SPEED) * 4096 to be sent
mjr 26:cb71c4af2912 273 */
mjr 26:cb71c4af2912 274 void set(int idx, unsigned short data)
mjr 26:cb71c4af2912 275 {
mjr 26:cb71c4af2912 276 // store the data, and flag the pending update for the interrupt handler to carry out
mjr 26:cb71c4af2912 277 gs[idx] = data;
mjr 30:6e9902f06f48 278 newGSData = true;
mjr 26:cb71c4af2912 279 }
mjr 26:cb71c4af2912 280
mjr 26:cb71c4af2912 281 private:
mjr 26:cb71c4af2912 282 // current level for each output
mjr 26:cb71c4af2912 283 unsigned short *gs;
mjr 26:cb71c4af2912 284
mjr 30:6e9902f06f48 285 // Simple DMA interface object
mjr 30:6e9902f06f48 286 SimpleDMA sdma;
mjr 30:6e9902f06f48 287
mjr 30:6e9902f06f48 288 // DMA transfer buffer. Each time we have data to transmit to the TLC5940 chips,
mjr 30:6e9902f06f48 289 // we format the data into this buffer exactly as it will go across the wire, then
mjr 30:6e9902f06f48 290 // hand the buffer to the DMA controller to move through the SPI port.
mjr 30:6e9902f06f48 291 char *dmabuf;
mjr 30:6e9902f06f48 292
mjr 26:cb71c4af2912 293 // SPI port - only MOSI and SCK are used
mjr 26:cb71c4af2912 294 SPI spi;
mjr 26:cb71c4af2912 295
mjr 26:cb71c4af2912 296 // use a PWM out for the grayscale clock - this provides a stable
mjr 26:cb71c4af2912 297 // square wave signal without consuming CPU
mjr 26:cb71c4af2912 298 FastPWM gsclk;
mjr 26:cb71c4af2912 299
mjr 26:cb71c4af2912 300 // Digital out pins used for the TLC5940
mjr 26:cb71c4af2912 301 DigitalOut blank;
mjr 26:cb71c4af2912 302 DigitalOut xlat;
mjr 26:cb71c4af2912 303
mjr 26:cb71c4af2912 304 // number of daisy-chained TLC5940s we're controlling
mjr 26:cb71c4af2912 305 int nchips;
mjr 26:cb71c4af2912 306
mjr 26:cb71c4af2912 307 // Timeout to end each PWM cycle. This is a one-shot timer that we reset
mjr 26:cb71c4af2912 308 // on each cycle.
mjr 26:cb71c4af2912 309 Timeout reset_timer;
mjr 26:cb71c4af2912 310
mjr 26:cb71c4af2912 311 // Has new GS/DC data been loaded?
mjr 26:cb71c4af2912 312 volatile bool newGSData;
mjr 33:d832bcab089e 313
mjr 33:d832bcab089e 314 // Do we need an XLAT signal on the next blanking interval?
mjr 33:d832bcab089e 315 volatile bool needXlat;
mjr 26:cb71c4af2912 316
mjr 26:cb71c4af2912 317 // Function to reset the display and send the next chunks of data
mjr 26:cb71c4af2912 318 void reset()
mjr 26:cb71c4af2912 319 {
mjr 30:6e9902f06f48 320 // start the blanking cycle
mjr 30:6e9902f06f48 321 startBlank();
mjr 33:d832bcab089e 322
mjr 33:d832bcab089e 323 #if DATA_UPDATE_INSIDE_BLANKING
mjr 33:d832bcab089e 324 // We're configured to send the new GS data entirely within
mjr 33:d832bcab089e 325 // the blanking interval. Start the DMA transfer now, and
mjr 33:d832bcab089e 326 // return without ending the blanking interval. The DMA
mjr 33:d832bcab089e 327 // completion interrupt handler will do that when the data
mjr 33:d832bcab089e 328 // update has completed.
mjr 33:d832bcab089e 329 //
mjr 33:d832bcab089e 330 // Note that we do the data update/ unconditionally in the
mjr 33:d832bcab089e 331 // send-during-blanking case, whether or not we have new GS
mjr 33:d832bcab089e 332 // data. This is because the update causes a 0.3% reduction
mjr 33:d832bcab089e 333 // in brightness because of the elongated BLANK interval.
mjr 33:d832bcab089e 334 // That would be visible as a flicker on each update if we
mjr 33:d832bcab089e 335 // did updates on some cycles and not others. By doing an
mjr 33:d832bcab089e 336 // update on every cycle, we make the brightness reduction
mjr 33:d832bcab089e 337 // uniform across time, which makes it less perceptible.
mjr 33:d832bcab089e 338 update();
mjr 33:d832bcab089e 339
mjr 33:d832bcab089e 340 #else // DATA_UPDATE_INSIDE_BLANKING
mjr 33:d832bcab089e 341
mjr 33:d832bcab089e 342 // end the blanking interval
mjr 33:d832bcab089e 343 endBlank();
mjr 33:d832bcab089e 344
mjr 33:d832bcab089e 345 // if we have pending grayscale data, start sending it
mjr 33:d832bcab089e 346 if (newGSData)
mjr 26:cb71c4af2912 347 update();
mjr 26:cb71c4af2912 348
mjr 33:d832bcab089e 349 #endif // DATA_UPDATE_INSIDE_BLANKING
mjr 30:6e9902f06f48 350 }
mjr 30:6e9902f06f48 351
mjr 30:6e9902f06f48 352 void startBlank()
mjr 30:6e9902f06f48 353 {
mjr 30:6e9902f06f48 354 // turn off the grayscale clock, and assert BLANK to end the grayscale cycle
mjr 30:6e9902f06f48 355 gsclk.write(0);
mjr 30:6e9902f06f48 356 blank = 1;
mjr 30:6e9902f06f48 357 }
mjr 26:cb71c4af2912 358
mjr 33:d832bcab089e 359 void endBlank()
mjr 30:6e9902f06f48 360 {
mjr 33:d832bcab089e 361 // if we've sent new grayscale data since the last blanking
mjr 33:d832bcab089e 362 // interval, latch it by asserting XLAT
mjr 33:d832bcab089e 363 if (needXlat)
mjr 30:6e9902f06f48 364 {
mjr 26:cb71c4af2912 365 // latch the new data while we're still blanked
mjr 26:cb71c4af2912 366 xlat = 1;
mjr 26:cb71c4af2912 367 xlat = 0;
mjr 33:d832bcab089e 368 needXlat = false;
mjr 26:cb71c4af2912 369 }
mjr 26:cb71c4af2912 370
mjr 26:cb71c4af2912 371 // end the blanking interval and restart the grayscale clock
mjr 26:cb71c4af2912 372 blank = 0;
mjr 26:cb71c4af2912 373 gsclk.write(.5);
mjr 26:cb71c4af2912 374
mjr 26:cb71c4af2912 375 // set up the next blanking interrupt
mjr 26:cb71c4af2912 376 reset_timer.attach(this, &TLC5940::reset, (1.0/GSCLK_SPEED)*4096.0);
mjr 26:cb71c4af2912 377 }
mjr 26:cb71c4af2912 378
mjr 26:cb71c4af2912 379 void update()
mjr 26:cb71c4af2912 380 {
mjr 30:6e9902f06f48 381 // Send new grayscale data to the TLC5940 chips.
mjr 30:6e9902f06f48 382 //
mjr 30:6e9902f06f48 383 // To do this, we set up our DMA buffer with the bytes formatted exactly
mjr 30:6e9902f06f48 384 // as they will go across the wire, then kick off the transfer request with
mjr 30:6e9902f06f48 385 // the DMA controller. We can then return from the interrupt and continue
mjr 30:6e9902f06f48 386 // with other tasks while the DMA hardware handles the transfer for us.
mjr 30:6e9902f06f48 387 // When the transfer is completed, the DMA controller will fire an
mjr 30:6e9902f06f48 388 // interrupt, which will call our interrupt handler, which will finish
mjr 30:6e9902f06f48 389 // the blanking cycle.
mjr 30:6e9902f06f48 390 //
mjr 30:6e9902f06f48 391 // The serial format orders the outputs from last to first (output #15 on
mjr 30:6e9902f06f48 392 // the last chip in the daisy-chain to output #0 on the first chip). For
mjr 30:6e9902f06f48 393 // each output, we send 12 bits containing the grayscale level (0 = fully
mjr 30:6e9902f06f48 394 // off, 0xFFF = fully on). Bit order is most significant bit first.
mjr 26:cb71c4af2912 395 //
mjr 26:cb71c4af2912 396 // The KL25Z SPI can only send in 8-bit increments, so we need to divvy up
mjr 26:cb71c4af2912 397 // the 12-bit outputs into 8-bit bytes. Each pair of 12-bit outputs adds up
mjr 26:cb71c4af2912 398 // to 24 bits, which divides evenly into 3 bytes, so send each pairs of
mjr 26:cb71c4af2912 399 // outputs as three bytes:
mjr 26:cb71c4af2912 400 //
mjr 26:cb71c4af2912 401 // [ element i+1 bits ] [ element i bits ]
mjr 26:cb71c4af2912 402 // 11 10 9 8 7 6 5 4 3 2 1 0 11 10 9 8 7 6 5 4 3 2 1 0
mjr 26:cb71c4af2912 403 // [ first byte ] [ second byte ] [ third byte ]
mjr 30:6e9902f06f48 404 for (int i = (16 * nchips) - 2, dst = 0 ; i >= 0 ; i -= 2)
mjr 26:cb71c4af2912 405 {
mjr 26:cb71c4af2912 406 // first byte - element i+1 bits 4-11
mjr 30:6e9902f06f48 407 dmabuf[dst++] = (((gs[i+1] & 0xFF0) >> 4) & 0xff);
mjr 26:cb71c4af2912 408
mjr 26:cb71c4af2912 409 // second byte - element i+1 bits 0-3, then element i bits 8-11
mjr 30:6e9902f06f48 410 dmabuf[dst++] = ((((gs[i+1] & 0x00F) << 4) | ((gs[i] & 0xF00) >> 8)) & 0xFF);
mjr 26:cb71c4af2912 411
mjr 26:cb71c4af2912 412 // third byte - element i bits 0-7
mjr 30:6e9902f06f48 413 dmabuf[dst++] = (gs[i] & 0x0FF);
mjr 26:cb71c4af2912 414 }
mjr 30:6e9902f06f48 415
mjr 30:6e9902f06f48 416 // Start the DMA transfer
mjr 30:6e9902f06f48 417 sdma.start(nchips*24);
mjr 33:d832bcab089e 418
mjr 33:d832bcab089e 419 // we've now cleared the new GS data
mjr 33:d832bcab089e 420 newGSData = false;
mjr 26:cb71c4af2912 421 }
mjr 30:6e9902f06f48 422
mjr 30:6e9902f06f48 423 // Interrupt handler for DMA completion. The DMA controller calls this
mjr 30:6e9902f06f48 424 // when it finishes with the transfer request we set up above. When the
mjr 30:6e9902f06f48 425 // transfer is done, we simply end the blanking cycle and start a new
mjr 30:6e9902f06f48 426 // grayscale cycle.
mjr 30:6e9902f06f48 427 void dmaDone()
mjr 30:6e9902f06f48 428 {
mjr 33:d832bcab089e 429 // mark that we need to assert XLAT to latch the new
mjr 33:d832bcab089e 430 // grayscale data during the next blanking interval
mjr 33:d832bcab089e 431 needXlat = true;
mjr 33:d832bcab089e 432
mjr 33:d832bcab089e 433 #if DATA_UPDATE_INSIDE_BLANKING
mjr 33:d832bcab089e 434 // we're doing the gs update within the blanking cycle, so end
mjr 33:d832bcab089e 435 // the blanking cycle now that the transfer has completed
mjr 33:d832bcab089e 436 endBlank();
mjr 33:d832bcab089e 437 #endif
mjr 30:6e9902f06f48 438 }
mjr 30:6e9902f06f48 439
mjr 26:cb71c4af2912 440 };
mjr 26:cb71c4af2912 441
mjr 26:cb71c4af2912 442 #endif