39 uint8_t registerAddr = PCA9685_LED0;
48 static constexpr uint16_t size = 16 * 4 + 1;
51 using DmaBuffer = PCA9685TransmitBuffer[numDrivers];
66 const uint8_t (&addresses)[numDrivers],
72 draw_buffer_ = dma_buffer_a;
73 transmit_buffer_ = dma_buffer_b;
75 for(
int d = 0; d < numDrivers; d++)
76 addresses_[d] = addresses[d];
77 current_driver_idx_ = -1;
84 constexpr int GetNumLeds()
const {
return numDrivers * 16; }
89 const uint8_t intBrightness
90 = (uint8_t)(clamp(brightness * 255.0f, 0.0f, 255.0f));
97 const uint16_t cycles = gamma_table_[brightness];
109 void SetLed(
int ledIndex,
float brightness)
111 const uint8_t intBrightness
112 = (uint8_t)(clamp(brightness * 255.0f, 0.0f, 255.0f));
113 SetLed(ledIndex, intBrightness);
117 void SetLed(
int ledIndex, uint8_t brightness)
119 const uint16_t cycles = gamma_table_[brightness];
126 const auto d = GetDriverForLed(ledIndex);
127 const auto ch = GetDriverChannelForLed(ledIndex);
129 const auto on = draw_buffer_[d].leds[ch].on & (0x0FFF);
130 draw_buffer_[d].leds[ch].off = (on + rawBrightness) & (0x0FFF);
132 if(rawBrightness >= 0x0FFF)
133 draw_buffer_[d].leds[ch].on = 0x1000 | on;
135 draw_buffer_[d].leds[ch].on = on;
144 while(current_driver_idx_ >= 0) {};
147 auto tmp = transmit_buffer_;
148 transmit_buffer_ = draw_buffer_;
153 if(persistentBufferContents)
155 for(
int d = 0; d < numDrivers; d++)
156 for(
int ch = 0; ch < 16; ch++)
157 draw_buffer_[d].leds[ch].off
158 = transmit_buffer_[d].leds[ch].off;
162 current_driver_idx_ = -1;
163 ContinueTransmission();
167 void ContinueTransmission()
169 current_driver_idx_ = current_driver_idx_ + 1;
170 if(current_driver_idx_ >= numDrivers)
172 current_driver_idx_ = -1;
176 const auto d = current_driver_idx_;
177 const uint8_t address = PCA9685_I2C_BASE_ADDRESS | addresses_[d];
179 (uint8_t*)&transmit_buffer_[d],
180 PCA9685TransmitBuffer::size,
190 uint16_t GetStartCycleForLed(
int ledIndex)
const
192 return (ledIndex << 2) & 0x0FFF;
195 uint8_t GetDriverForLed(
int ledIndex)
const {
return ledIndex >> 4; }
197 uint8_t GetDriverChannelForLed(
int ledIndex)
const
199 return ledIndex & 0x0F;
202 void InitializeBuffers()
206 const auto d = GetDriverForLed(led);
207 const auto ch = GetDriverChannelForLed(led);
208 const auto startCycle = GetStartCycleForLed(led);
209 draw_buffer_[d].registerAddr = PCA9685_LED0;
210 draw_buffer_[d].leds[ch].on = startCycle;
211 draw_buffer_[d].leds[ch].off = startCycle;
212 transmit_buffer_[d].registerAddr = PCA9685_LED0;
213 transmit_buffer_[d].leds[ch].on = startCycle;
214 transmit_buffer_[d].leds[ch].off = startCycle;
218 void InitializeDrivers()
224 oe_pin_gpio_.
Write(0);
228 for(
int d = 0; d < numDrivers; d++)
230 const uint8_t address = PCA9685_I2C_BASE_ADDRESS | addresses_[d];
232 buffer[0] = PCA9685_MODE1;
236 buffer[0] = PCA9685_MODE1;
240 buffer[0] = PCA9685_MODE1;
242 buffer[1] = 0b00100000;
245 buffer[0] = PCA9685_MODE2;
250 buffer[1] = 0b000110110;
256 template <
typename T>
257 T clamp(T in, T low, T high)
259 return (in < low) ? low : (high < in) ? high : in;
266 auto drv_ptr =
reinterpret_cast<
267 LedDriverPca9685<numDrivers, persistentBufferContents>*
>(context);
268 drv_ptr->ContinueTransmission();
272 PCA9685TransmitBuffer* draw_buffer_;
273 PCA9685TransmitBuffer* transmit_buffer_;
274 uint8_t addresses_[numDrivers];
278 volatile int8_t current_driver_idx_;
279 const uint16_t gamma_table_[256] = {
280 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
281 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5,
282 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 15, 16,
283 17, 18, 20, 21, 23, 25, 26, 28, 30, 32, 34, 36,
284 38, 40, 43, 45, 48, 50, 53, 56, 59, 62, 65, 68,
285 71, 75, 78, 82, 85, 89, 93, 97, 101, 105, 110, 114,
286 119, 123, 128, 133, 138, 143, 149, 154, 159, 165, 171, 177,
287 183, 189, 195, 202, 208, 215, 222, 229, 236, 243, 250, 258,
288 266, 273, 281, 290, 298, 306, 315, 324, 332, 341, 351, 360,
289 369, 379, 389, 399, 409, 419, 430, 440, 451, 462, 473, 485,
290 496, 508, 520, 532, 544, 556, 569, 582, 594, 608, 621, 634,
291 648, 662, 676, 690, 704, 719, 734, 749, 764, 779, 795, 811,
292 827, 843, 859, 876, 893, 910, 927, 944, 962, 980, 998, 1016,
293 1034, 1053, 1072, 1091, 1110, 1130, 1150, 1170, 1190, 1210, 1231, 1252,
294 1273, 1294, 1316, 1338, 1360, 1382, 1404, 1427, 1450, 1473, 1497, 1520,
295 1544, 1568, 1593, 1617, 1642, 1667, 1693, 1718, 1744, 1770, 1797, 1823,
296 1850, 1877, 1905, 1932, 1960, 1988, 2017, 2045, 2074, 2103, 2133, 2162,
297 2192, 2223, 2253, 2284, 2315, 2346, 2378, 2410, 2442, 2474, 2507, 2540,
298 2573, 2606, 2640, 2674, 2708, 2743, 2778, 2813, 2849, 2884, 2920, 2957,
299 2993, 3030, 3067, 3105, 3143, 3181, 3219, 3258, 3297, 3336, 3376, 3416,
300 3456, 3496, 3537, 3578, 3619, 3661, 3703, 3745, 3788, 3831, 3874, 3918,
301 3962, 4006, 4050, 4095};
303 static constexpr uint8_t PCA9685_I2C_BASE_ADDRESS = 0b01000000;
304 static constexpr uint8_t PCA9685_MODE1
306 static constexpr uint8_t PCA9685_MODE2
308 static constexpr uint8_t PCA9685_LED0
310 static constexpr uint8_t PRE_SCALE_MODE