Published
Fork of TLC5940 by
TLC5955.cpp@4:ab6b451bbf40, 2018-06-09 (annotated)
- Committer:
- roysandberg
- Date:
- Sat Jun 09 23:22:13 2018 +0000
- Revision:
- 4:ab6b451bbf40
Published
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
roysandberg | 4:ab6b451bbf40 | 1 | #include "TLC5955.h" |
roysandberg | 4:ab6b451bbf40 | 2 | #include "math.h" |
roysandberg | 4:ab6b451bbf40 | 3 | |
roysandberg | 4:ab6b451bbf40 | 4 | extern void init_clock(PinName clkPin); |
roysandberg | 4:ab6b451bbf40 | 5 | |
roysandberg | 4:ab6b451bbf40 | 6 | DigitalOut led2(LED2); |
roysandberg | 4:ab6b451bbf40 | 7 | |
roysandberg | 4:ab6b451bbf40 | 8 | // gamma correction array compensates for non-linearities |
roysandberg | 4:ab6b451bbf40 | 9 | // https://learn.adafruit.com/led-tricks-gamma-correction/the-longer-fix |
roysandberg | 4:ab6b451bbf40 | 10 | uint16_t redGamma[256]; |
roysandberg | 4:ab6b451bbf40 | 11 | uint16_t greenGamma[256]; |
roysandberg | 4:ab6b451bbf40 | 12 | uint16_t blueGamma[256]; |
roysandberg | 4:ab6b451bbf40 | 13 | |
roysandberg | 4:ab6b451bbf40 | 14 | #define GAMMA_FACTOR 2.8 |
roysandberg | 4:ab6b451bbf40 | 15 | #define GAMMA_MAX_IN 255 |
roysandberg | 4:ab6b451bbf40 | 16 | #define GAMMA_RED_MAX_OUT 0xFFFF |
roysandberg | 4:ab6b451bbf40 | 17 | #define GAMMA_BLUE_MAX_OUT 0x4000 |
roysandberg | 4:ab6b451bbf40 | 18 | #define GAMMA_GREEN_MAX_OUT 0x8000 |
roysandberg | 4:ab6b451bbf40 | 19 | |
roysandberg | 4:ab6b451bbf40 | 20 | void buildGammaTable(float gammaFactor, uint16_t maxInput, uint16_t maxOutput, uint16_t* gamma) { |
roysandberg | 4:ab6b451bbf40 | 21 | for(int i=0; i<=maxInput; i++) { |
roysandberg | 4:ab6b451bbf40 | 22 | gamma[i] = (uint16_t) (pow((float)i / (float)maxInput, gammaFactor) * maxOutput + 0.5); |
roysandberg | 4:ab6b451bbf40 | 23 | //printf("Max=%x, i=%d, val=%x\n\r", maxOutput, i, gamma[i]); |
roysandberg | 4:ab6b451bbf40 | 24 | } |
roysandberg | 4:ab6b451bbf40 | 25 | } |
roysandberg | 4:ab6b451bbf40 | 26 | |
roysandberg | 4:ab6b451bbf40 | 27 | void rebuildGammaTables(uint8_t amplitude) { |
roysandberg | 4:ab6b451bbf40 | 28 | buildGammaTable (GAMMA_FACTOR, GAMMA_MAX_IN, (uint16_t)((((long) GAMMA_RED_MAX_OUT)*amplitude)/0xFFl), redGamma); |
roysandberg | 4:ab6b451bbf40 | 29 | buildGammaTable (GAMMA_FACTOR, GAMMA_MAX_IN, (uint16_t)((((long) GAMMA_GREEN_MAX_OUT)*amplitude)/0xFFl), greenGamma); |
roysandberg | 4:ab6b451bbf40 | 30 | buildGammaTable (GAMMA_FACTOR, GAMMA_MAX_IN, (uint16_t)((((long) GAMMA_BLUE_MAX_OUT)*amplitude)/0xFFl), blueGamma); |
roysandberg | 4:ab6b451bbf40 | 31 | } |
roysandberg | 4:ab6b451bbf40 | 32 | |
roysandberg | 4:ab6b451bbf40 | 33 | TLC5955::TLC5955(PinName SCLK, PinName MOSI, PinName GSCLK, |
roysandberg | 4:ab6b451bbf40 | 34 | PinName XLAT, const int number) : number(number), |
roysandberg | 4:ab6b451bbf40 | 35 | spi(MOSI, NC, SCLK), |
roysandberg | 4:ab6b451bbf40 | 36 | gsclk(GSCLK), |
roysandberg | 4:ab6b451bbf40 | 37 | xlat(XLAT), |
roysandberg | 4:ab6b451bbf40 | 38 | newGSData(false), |
roysandberg | 4:ab6b451bbf40 | 39 | newControlData(false), |
roysandberg | 4:ab6b451bbf40 | 40 | need_xlat(false) |
roysandberg | 4:ab6b451bbf40 | 41 | { |
roysandberg | 4:ab6b451bbf40 | 42 | |
roysandberg | 4:ab6b451bbf40 | 43 | rebuildGammaTables(0xFF); // oxFF is full amplitude |
roysandberg | 4:ab6b451bbf40 | 44 | |
roysandberg | 4:ab6b451bbf40 | 45 | for (int i=0; i<(SHORTS_PER_CHANNEL * CHANNELS_PER_IC * NUMBER_OF_ICS); i++) { |
roysandberg | 4:ab6b451bbf40 | 46 | internalData[i] = 0xFFFF; // invert pwm outputs because transistor will get pulled low when on |
roysandberg | 4:ab6b451bbf40 | 47 | } |
roysandberg | 4:ab6b451bbf40 | 48 | for (int i=0; i<(SHORTS_PER_CHANNEL * CHANNELS_PER_IC * NUMBER_OF_ICS)+1; i++) { |
roysandberg | 4:ab6b451bbf40 | 49 | gsBuffer[i] = 0xFFFF; |
roysandberg | 4:ab6b451bbf40 | 50 | } |
roysandberg | 4:ab6b451bbf40 | 51 | |
roysandberg | 4:ab6b451bbf40 | 52 | |
roysandberg | 4:ab6b451bbf40 | 53 | // Configure SPI to 16 bits and SPI_SPEED |
roysandberg | 4:ab6b451bbf40 | 54 | spi.format(8, 0); |
roysandberg | 4:ab6b451bbf40 | 55 | spi.frequency(SPI_SPEED); |
roysandberg | 4:ab6b451bbf40 | 56 | |
roysandberg | 4:ab6b451bbf40 | 57 | |
roysandberg | 4:ab6b451bbf40 | 58 | |
roysandberg | 4:ab6b451bbf40 | 59 | |
roysandberg | 4:ab6b451bbf40 | 60 | // Set lat pin state |
roysandberg | 4:ab6b451bbf40 | 61 | xlat = 0; |
roysandberg | 4:ab6b451bbf40 | 62 | |
roysandberg | 4:ab6b451bbf40 | 63 | // 62.5Hz should be fast enough |
roysandberg | 4:ab6b451bbf40 | 64 | reset_ticker.attach_us(this, &TLC5955::reset, 16000); |
roysandberg | 4:ab6b451bbf40 | 65 | |
roysandberg | 4:ab6b451bbf40 | 66 | // Outputs 8Mhz on pin |
roysandberg | 4:ab6b451bbf40 | 67 | init_clock(GSCLK); |
roysandberg | 4:ab6b451bbf40 | 68 | } |
roysandberg | 4:ab6b451bbf40 | 69 | // https://github.com/FastLED/FastLED/wiki/FastLED-Color-Correction |
roysandberg | 4:ab6b451bbf40 | 70 | // Red LEDs are the dimmest, so no scaling |
roysandberg | 4:ab6b451bbf40 | 71 | // Blue LEDs are a bit brighter, so scale down by 0.9 (0xE6) |
roysandberg | 4:ab6b451bbf40 | 72 | // Green LED are by far the brightest, so scale down by 0.6 (0x99) |
roysandberg | 4:ab6b451bbf40 | 73 | void TLC5955::setChannel(int channelNum, unsigned short red, unsigned short green, unsigned short blue) { |
roysandberg | 4:ab6b451bbf40 | 74 | if (red > 0xFF) red = 0xFF; |
roysandberg | 4:ab6b451bbf40 | 75 | if (green > 0xFF) green = 0xFF; |
roysandberg | 4:ab6b451bbf40 | 76 | if (blue > 0xFF) blue = 0xFF; |
roysandberg | 4:ab6b451bbf40 | 77 | |
roysandberg | 4:ab6b451bbf40 | 78 | if (channelNum < CHANNELS_PER_IC * NUMBER_OF_ICS) { |
roysandberg | 4:ab6b451bbf40 | 79 | // chip color values leave in b, r, g order, but that should map to r, g, b order |
roysandberg | 4:ab6b451bbf40 | 80 | |
roysandberg | 4:ab6b451bbf40 | 81 | if (channelNum > 31) { |
roysandberg | 4:ab6b451bbf40 | 82 | channelNum -= 32; |
roysandberg | 4:ab6b451bbf40 | 83 | } else if (channelNum < 16) { |
roysandberg | 4:ab6b451bbf40 | 84 | channelNum += 32; |
roysandberg | 4:ab6b451bbf40 | 85 | } |
roysandberg | 4:ab6b451bbf40 | 86 | |
roysandberg | 4:ab6b451bbf40 | 87 | // mappings are slightly different for first eight and last eight of each board (red and green get inverted) |
roysandberg | 4:ab6b451bbf40 | 88 | if (channelNum % 16 < 8) { |
roysandberg | 4:ab6b451bbf40 | 89 | internalData[channelNum*SHORTS_PER_CHANNEL + 1] = (0xFFFF - GAMMA_BLUE_MAX_OUT) + (GAMMA_BLUE_MAX_OUT - blueGamma[blue]); |
roysandberg | 4:ab6b451bbf40 | 90 | internalData[channelNum*SHORTS_PER_CHANNEL + 0] = (0xFFFF - GAMMA_RED_MAX_OUT) + (GAMMA_RED_MAX_OUT - redGamma[red]); |
roysandberg | 4:ab6b451bbf40 | 91 | internalData[channelNum*SHORTS_PER_CHANNEL + 2] = (0xFFFF-GAMMA_GREEN_MAX_OUT) + (GAMMA_GREEN_MAX_OUT - greenGamma[green]); |
roysandberg | 4:ab6b451bbf40 | 92 | } else { |
roysandberg | 4:ab6b451bbf40 | 93 | internalData[channelNum*SHORTS_PER_CHANNEL + 2] = (0xFFFF - GAMMA_BLUE_MAX_OUT) + (GAMMA_BLUE_MAX_OUT - blueGamma[blue]); |
roysandberg | 4:ab6b451bbf40 | 94 | internalData[channelNum*SHORTS_PER_CHANNEL + 1] = (0xFFFF - GAMMA_GREEN_MAX_OUT) +(GAMMA_GREEN_MAX_OUT - greenGamma[green]); |
roysandberg | 4:ab6b451bbf40 | 95 | internalData[channelNum*SHORTS_PER_CHANNEL + 0] = (0xFFFF - GAMMA_RED_MAX_OUT) + (GAMMA_RED_MAX_OUT - redGamma[red]); |
roysandberg | 4:ab6b451bbf40 | 96 | } |
roysandberg | 4:ab6b451bbf40 | 97 | } |
roysandberg | 4:ab6b451bbf40 | 98 | } |
roysandberg | 4:ab6b451bbf40 | 99 | |
roysandberg | 4:ab6b451bbf40 | 100 | void TLC5955::latchData() { |
roysandberg | 4:ab6b451bbf40 | 101 | newGSData = true; |
roysandberg | 4:ab6b451bbf40 | 102 | } |
roysandberg | 4:ab6b451bbf40 | 103 | |
roysandberg | 4:ab6b451bbf40 | 104 | void TLC5955::setNewControlData(unsigned short _globalBrightnessRed, unsigned short _globalBrightnessGreen, unsigned short _globalBrightnessBlue, |
roysandberg | 4:ab6b451bbf40 | 105 | led_power_t _maximumCurrentRed, led_power_t _maximumCurrentGreen, led_power_t _maximumCurrentBlue, |
roysandberg | 4:ab6b451bbf40 | 106 | unsigned short* _dotCorrect) { |
roysandberg | 4:ab6b451bbf40 | 107 | globalBrightnessRed = _globalBrightnessRed; |
roysandberg | 4:ab6b451bbf40 | 108 | globalBrightnessGreen = _globalBrightnessGreen; |
roysandberg | 4:ab6b451bbf40 | 109 | globalBrightnessBlue = _globalBrightnessBlue; |
roysandberg | 4:ab6b451bbf40 | 110 | maximumCurrentRed = _maximumCurrentRed; |
roysandberg | 4:ab6b451bbf40 | 111 | maximumCurrentGreen = _maximumCurrentGreen; |
roysandberg | 4:ab6b451bbf40 | 112 | maximumCurrentBlue = _maximumCurrentBlue; |
roysandberg | 4:ab6b451bbf40 | 113 | dotCorrect = _dotCorrect; |
roysandberg | 4:ab6b451bbf40 | 114 | |
roysandberg | 4:ab6b451bbf40 | 115 | // Tell reset function that new DC data has been given |
roysandberg | 4:ab6b451bbf40 | 116 | newControlData = true; |
roysandberg | 4:ab6b451bbf40 | 117 | } |
roysandberg | 4:ab6b451bbf40 | 118 | |
roysandberg | 4:ab6b451bbf40 | 119 | // clock out the data over spi such that the MSB is the control bit (so 769 bits total) |
roysandberg | 4:ab6b451bbf40 | 120 | void TLC5955::clockOutData() { |
roysandberg | 4:ab6b451bbf40 | 121 | // clock out buffer, where the first word contains |
roysandberg | 4:ab6b451bbf40 | 122 | // unused leading bits that will get clocked past the registers. |
roysandberg | 4:ab6b451bbf40 | 123 | |
roysandberg | 4:ab6b451bbf40 | 124 | for (int i=0; i< (SHORTS_PER_CHANNEL * CHANNELS_PER_IC * NUMBER_OF_ICS) + 1; i++) { |
roysandberg | 4:ab6b451bbf40 | 125 | spi.write(gsBuffer[i]>>8); |
roysandberg | 4:ab6b451bbf40 | 126 | spi.write(gsBuffer[i]&0xFF); |
roysandberg | 4:ab6b451bbf40 | 127 | //printf ("%d:%x:%x\n\r",i, gsBuffer[i]>>8, gsBuffer[i]&0xFF); |
roysandberg | 4:ab6b451bbf40 | 128 | } |
roysandberg | 4:ab6b451bbf40 | 129 | } |
roysandberg | 4:ab6b451bbf40 | 130 | |
roysandberg | 4:ab6b451bbf40 | 131 | // Need a way to assemble bits in random offsets, since the 769 bit sequence doesn't divide evenly. |
roysandberg | 4:ab6b451bbf40 | 132 | // So depending on how many TLC5955s are daisy chained together, there are an arbitrary number of extra bits. |
roysandberg | 4:ab6b451bbf40 | 133 | // Function that tracks next available bit location, and packs everything in is needed. |
roysandberg | 4:ab6b451bbf40 | 134 | |
roysandberg | 4:ab6b451bbf40 | 135 | |
roysandberg | 4:ab6b451bbf40 | 136 | inline void TLC5955::clearBit (unsigned short* value, int bitOffset) { |
roysandberg | 4:ab6b451bbf40 | 137 | *value = *value & ~(1<<bitOffset); |
roysandberg | 4:ab6b451bbf40 | 138 | } |
roysandberg | 4:ab6b451bbf40 | 139 | |
roysandberg | 4:ab6b451bbf40 | 140 | inline void TLC5955::setBit (unsigned short* value, int bitOffset) { |
roysandberg | 4:ab6b451bbf40 | 141 | *value = *value | (1<<bitOffset); |
roysandberg | 4:ab6b451bbf40 | 142 | } |
roysandberg | 4:ab6b451bbf40 | 143 | |
roysandberg | 4:ab6b451bbf40 | 144 | |
roysandberg | 4:ab6b451bbf40 | 145 | inline void TLC5955::packBit(unsigned int aBit) { |
roysandberg | 4:ab6b451bbf40 | 146 | // current bit location divided by 16 to get the short |
roysandberg | 4:ab6b451bbf40 | 147 | int shortOffset = currentBitLocation / 16; |
roysandberg | 4:ab6b451bbf40 | 148 | |
roysandberg | 4:ab6b451bbf40 | 149 | // current bit location mod 8 to get the bit to mask |
roysandberg | 4:ab6b451bbf40 | 150 | int bitOffset = currentBitLocation % 16; |
roysandberg | 4:ab6b451bbf40 | 151 | |
roysandberg | 4:ab6b451bbf40 | 152 | if (aBit == 0) { |
roysandberg | 4:ab6b451bbf40 | 153 | // clear |
roysandberg | 4:ab6b451bbf40 | 154 | clearBit (&(gsBuffer[shortOffset]), 15 - bitOffset); |
roysandberg | 4:ab6b451bbf40 | 155 | } else { |
roysandberg | 4:ab6b451bbf40 | 156 | // set |
roysandberg | 4:ab6b451bbf40 | 157 | setBit (&(gsBuffer[shortOffset]), 15 - bitOffset); |
roysandberg | 4:ab6b451bbf40 | 158 | } |
roysandberg | 4:ab6b451bbf40 | 159 | currentBitLocation++; |
roysandberg | 4:ab6b451bbf40 | 160 | } |
roysandberg | 4:ab6b451bbf40 | 161 | |
roysandberg | 4:ab6b451bbf40 | 162 | void TLC5955::packByte (unsigned int aByte) { |
roysandberg | 4:ab6b451bbf40 | 163 | // call packBit for 8 bits, starting at the current bit location |
roysandberg | 4:ab6b451bbf40 | 164 | for (int i = 7; i >= 0;i--) { // MSB gets packed first |
roysandberg | 4:ab6b451bbf40 | 165 | packBit( aByte & (1<<i)); |
roysandberg | 4:ab6b451bbf40 | 166 | } |
roysandberg | 4:ab6b451bbf40 | 167 | |
roysandberg | 4:ab6b451bbf40 | 168 | } |
roysandberg | 4:ab6b451bbf40 | 169 | |
roysandberg | 4:ab6b451bbf40 | 170 | void TLC5955::packShort (unsigned int aShort) { |
roysandberg | 4:ab6b451bbf40 | 171 | packByte( aShort >> 8); // MSB first |
roysandberg | 4:ab6b451bbf40 | 172 | packByte( aShort & 0xFF); |
roysandberg | 4:ab6b451bbf40 | 173 | } |
roysandberg | 4:ab6b451bbf40 | 174 | |
roysandberg | 4:ab6b451bbf40 | 175 | void TLC5955::reset() |
roysandberg | 4:ab6b451bbf40 | 176 | { |
roysandberg | 4:ab6b451bbf40 | 177 | // Do we have new control data to send? |
roysandberg | 4:ab6b451bbf40 | 178 | if (newControlData) |
roysandberg | 4:ab6b451bbf40 | 179 | { |
roysandberg | 4:ab6b451bbf40 | 180 | // printf ("Control:\n\r"); |
roysandberg | 4:ab6b451bbf40 | 181 | |
roysandberg | 4:ab6b451bbf40 | 182 | currentBitLocation = 0; |
roysandberg | 4:ab6b451bbf40 | 183 | for (int i=0; i < 16 - NUMBER_OF_ICS;i++) { |
roysandberg | 4:ab6b451bbf40 | 184 | packBit(0); // stuff leading byte |
roysandberg | 4:ab6b451bbf40 | 185 | } |
roysandberg | 4:ab6b451bbf40 | 186 | for (int icNum=0; icNum < NUMBER_OF_ICS; icNum++) { |
roysandberg | 4:ab6b451bbf40 | 187 | // TODO: For daisy-chaining, this will need to consider the number of boards when calculating how many clocked out bits to offset |
roysandberg | 4:ab6b451bbf40 | 188 | //packShort(1); // set LSB to one, will clock into LSB spot when spi serializes it to trigger control data load when latched |
roysandberg | 4:ab6b451bbf40 | 189 | packBit(1); // set LSB to one |
roysandberg | 4:ab6b451bbf40 | 190 | packByte(0x96); // 8 bit command decoder must be set to 0x96 |
roysandberg | 4:ab6b451bbf40 | 191 | |
roysandberg | 4:ab6b451bbf40 | 192 | // 390 bits skipped, so could be anything |
roysandberg | 4:ab6b451bbf40 | 193 | for (int i=0;i<389;i++) { |
roysandberg | 4:ab6b451bbf40 | 194 | packBit(0); |
roysandberg | 4:ab6b451bbf40 | 195 | } |
roysandberg | 4:ab6b451bbf40 | 196 | |
roysandberg | 4:ab6b451bbf40 | 197 | // FC 5 bits |
roysandberg | 4:ab6b451bbf40 | 198 | packBit (0); // LED short circuit detection voltage - don't care for this application |
roysandberg | 4:ab6b451bbf40 | 199 | packBit (0); // Use conventional PWM for this application; it's compatible with daisy chaining |
roysandberg | 4:ab6b451bbf40 | 200 | packBit (0); // auto data refresh disabled |
roysandberg | 4:ab6b451bbf40 | 201 | packBit (0); // display timing reset disabled |
roysandberg | 4:ab6b451bbf40 | 202 | packBit (1); // auto display repeat mode ENABLED |
roysandberg | 4:ab6b451bbf40 | 203 | |
roysandberg | 4:ab6b451bbf40 | 204 | // BC, 21 bits |
roysandberg | 4:ab6b451bbf40 | 205 | packBit (globalBrightnessRed & (1<<6)); |
roysandberg | 4:ab6b451bbf40 | 206 | packBit (globalBrightnessRed & (1<<5)); |
roysandberg | 4:ab6b451bbf40 | 207 | packBit (globalBrightnessRed & (1<<4)); |
roysandberg | 4:ab6b451bbf40 | 208 | packBit (globalBrightnessRed & (1<<3)); |
roysandberg | 4:ab6b451bbf40 | 209 | packBit (globalBrightnessRed & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 210 | packBit (globalBrightnessRed & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 211 | packBit (globalBrightnessRed & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 212 | |
roysandberg | 4:ab6b451bbf40 | 213 | packBit (globalBrightnessGreen & (1<<6)); |
roysandberg | 4:ab6b451bbf40 | 214 | packBit (globalBrightnessGreen & (1<<5)); |
roysandberg | 4:ab6b451bbf40 | 215 | packBit (globalBrightnessGreen & (1<<4)); |
roysandberg | 4:ab6b451bbf40 | 216 | packBit (globalBrightnessGreen & (1<<3)); |
roysandberg | 4:ab6b451bbf40 | 217 | packBit (globalBrightnessGreen & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 218 | packBit (globalBrightnessGreen & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 219 | packBit (globalBrightnessGreen & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 220 | |
roysandberg | 4:ab6b451bbf40 | 221 | packBit (globalBrightnessBlue & (1<<6)); |
roysandberg | 4:ab6b451bbf40 | 222 | packBit (globalBrightnessBlue & (1<<5)); |
roysandberg | 4:ab6b451bbf40 | 223 | packBit (globalBrightnessBlue & (1<<4)); |
roysandberg | 4:ab6b451bbf40 | 224 | packBit (globalBrightnessBlue & (1<<3)); |
roysandberg | 4:ab6b451bbf40 | 225 | packBit (globalBrightnessBlue & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 226 | packBit (globalBrightnessBlue & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 227 | packBit (globalBrightnessBlue & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 228 | |
roysandberg | 4:ab6b451bbf40 | 229 | // MC, 9 bits |
roysandberg | 4:ab6b451bbf40 | 230 | packBit (maximumCurrentBlue & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 231 | packBit (maximumCurrentBlue & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 232 | packBit (maximumCurrentBlue & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 233 | |
roysandberg | 4:ab6b451bbf40 | 234 | packBit (maximumCurrentGreen & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 235 | packBit (maximumCurrentGreen & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 236 | packBit (maximumCurrentGreen & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 237 | |
roysandberg | 4:ab6b451bbf40 | 238 | packBit (maximumCurrentRed & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 239 | packBit (maximumCurrentRed & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 240 | packBit (maximumCurrentRed & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 241 | |
roysandberg | 4:ab6b451bbf40 | 242 | // DC 336 bits |
roysandberg | 4:ab6b451bbf40 | 243 | // dot correct for each channel, starting with channel 48 |
roysandberg | 4:ab6b451bbf40 | 244 | for (int i=0; i<48; i++) { |
roysandberg | 4:ab6b451bbf40 | 245 | packBit (dotCorrect[i] & (1<<6)); |
roysandberg | 4:ab6b451bbf40 | 246 | packBit (dotCorrect[i] & (1<<5)); |
roysandberg | 4:ab6b451bbf40 | 247 | packBit (dotCorrect[i] & (1<<4)); |
roysandberg | 4:ab6b451bbf40 | 248 | packBit (dotCorrect[i] & (1<<3)); |
roysandberg | 4:ab6b451bbf40 | 249 | packBit (dotCorrect[i] & (1<<2)); |
roysandberg | 4:ab6b451bbf40 | 250 | packBit (dotCorrect[i] & (1<<1)); |
roysandberg | 4:ab6b451bbf40 | 251 | packBit (dotCorrect[i] & (1<<0)); |
roysandberg | 4:ab6b451bbf40 | 252 | } |
roysandberg | 4:ab6b451bbf40 | 253 | } |
roysandberg | 4:ab6b451bbf40 | 254 | clockOutData(); |
roysandberg | 4:ab6b451bbf40 | 255 | |
roysandberg | 4:ab6b451bbf40 | 256 | // Latch |
roysandberg | 4:ab6b451bbf40 | 257 | xlat = 0; |
roysandberg | 4:ab6b451bbf40 | 258 | xlat = 1; |
roysandberg | 4:ab6b451bbf40 | 259 | wait_us(10); |
roysandberg | 4:ab6b451bbf40 | 260 | xlat = 0; |
roysandberg | 4:ab6b451bbf40 | 261 | |
roysandberg | 4:ab6b451bbf40 | 262 | |
roysandberg | 4:ab6b451bbf40 | 263 | // No new data to send (we just sent it!) |
roysandberg | 4:ab6b451bbf40 | 264 | newControlData = false; |
roysandberg | 4:ab6b451bbf40 | 265 | |
roysandberg | 4:ab6b451bbf40 | 266 | } else if (newGSData) { // Do we have new GS data to send? |
roysandberg | 4:ab6b451bbf40 | 267 | //printf ("Data:\n\r"); |
roysandberg | 4:ab6b451bbf40 | 268 | |
roysandberg | 4:ab6b451bbf40 | 269 | led2 = !led2; |
roysandberg | 4:ab6b451bbf40 | 270 | |
roysandberg | 4:ab6b451bbf40 | 271 | currentBitLocation = 0; |
roysandberg | 4:ab6b451bbf40 | 272 | for (int i=0; i < 16 - NUMBER_OF_ICS;i++) { |
roysandberg | 4:ab6b451bbf40 | 273 | packBit(1); // stuff leading byte |
roysandberg | 4:ab6b451bbf40 | 274 | } |
roysandberg | 4:ab6b451bbf40 | 275 | for (int icNum=0; icNum < NUMBER_OF_ICS; icNum++) { |
roysandberg | 4:ab6b451bbf40 | 276 | // TODO: For daisy-chaining, this will need to consider the number of boards when calculating how many clocked out bits to offset |
roysandberg | 4:ab6b451bbf40 | 277 | //packShort(0); // set LSB to zero, will clock into LSB spot when spi serializes it to trigger control data load when latched |
roysandberg | 4:ab6b451bbf40 | 278 | packBit(0); // set LSB to zero |
roysandberg | 4:ab6b451bbf40 | 279 | |
roysandberg | 4:ab6b451bbf40 | 280 | // Send GS data backwards - this makes the GS_buffer[0] index correspond to OUT0 |
roysandberg | 4:ab6b451bbf40 | 281 | for (int i = (SHORTS_PER_CHANNEL * CHANNELS_PER_IC) - 1; i >= 0; i--) |
roysandberg | 4:ab6b451bbf40 | 282 | { |
roysandberg | 4:ab6b451bbf40 | 283 | packShort(internalData[i + (icNum*SHORTS_PER_CHANNEL * CHANNELS_PER_IC)]); |
roysandberg | 4:ab6b451bbf40 | 284 | } |
roysandberg | 4:ab6b451bbf40 | 285 | } |
roysandberg | 4:ab6b451bbf40 | 286 | clockOutData(); |
roysandberg | 4:ab6b451bbf40 | 287 | |
roysandberg | 4:ab6b451bbf40 | 288 | // Latch |
roysandberg | 4:ab6b451bbf40 | 289 | xlat = 0; |
roysandberg | 4:ab6b451bbf40 | 290 | xlat = 1; |
roysandberg | 4:ab6b451bbf40 | 291 | wait_us(10); |
roysandberg | 4:ab6b451bbf40 | 292 | xlat = 0; |
roysandberg | 4:ab6b451bbf40 | 293 | |
roysandberg | 4:ab6b451bbf40 | 294 | // No new data to send (we just sent it!) |
roysandberg | 4:ab6b451bbf40 | 295 | newGSData = false; |
roysandberg | 4:ab6b451bbf40 | 296 | } |
roysandberg | 4:ab6b451bbf40 | 297 | } |