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()
223 oe_pin_gpio_.
pin = oe_pin_;
231 for(
int d = 0; d < numDrivers; d++)
233 const uint8_t address = PCA9685_I2C_BASE_ADDRESS | addresses_[d];
235 buffer[0] = PCA9685_MODE1;
239 buffer[0] = PCA9685_MODE1;
243 buffer[0] = PCA9685_MODE1;
245 buffer[1] = 0b00100000;
248 buffer[0] = PCA9685_MODE2;
253 buffer[1] = 0b000110110;
259 template <
typename T>
260 T clamp(T in, T low, T high)
262 return (in < low) ? low : (high < in) ? high : in;
269 auto drv_ptr =
reinterpret_cast<
270 LedDriverPca9685<numDrivers, persistentBufferContents>*
>(context);
271 drv_ptr->ContinueTransmission();
275 PCA9685TransmitBuffer* draw_buffer_;
276 PCA9685TransmitBuffer* transmit_buffer_;
277 uint8_t addresses_[numDrivers];
281 volatile int8_t current_driver_idx_;
282 const uint16_t gamma_table_[256] = {
283 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
284 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5,
285 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 15, 16,
286 17, 18, 20, 21, 23, 25, 26, 28, 30, 32, 34, 36,
287 38, 40, 43, 45, 48, 50, 53, 56, 59, 62, 65, 68,
288 71, 75, 78, 82, 85, 89, 93, 97, 101, 105, 110, 114,
289 119, 123, 128, 133, 138, 143, 149, 154, 159, 165, 171, 177,
290 183, 189, 195, 202, 208, 215, 222, 229, 236, 243, 250, 258,
291 266, 273, 281, 290, 298, 306, 315, 324, 332, 341, 351, 360,
292 369, 379, 389, 399, 409, 419, 430, 440, 451, 462, 473, 485,
293 496, 508, 520, 532, 544, 556, 569, 582, 594, 608, 621, 634,
294 648, 662, 676, 690, 704, 719, 734, 749, 764, 779, 795, 811,
295 827, 843, 859, 876, 893, 910, 927, 944, 962, 980, 998, 1016,
296 1034, 1053, 1072, 1091, 1110, 1130, 1150, 1170, 1190, 1210, 1231, 1252,
297 1273, 1294, 1316, 1338, 1360, 1382, 1404, 1427, 1450, 1473, 1497, 1520,
298 1544, 1568, 1593, 1617, 1642, 1667, 1693, 1718, 1744, 1770, 1797, 1823,
299 1850, 1877, 1905, 1932, 1960, 1988, 2017, 2045, 2074, 2103, 2133, 2162,
300 2192, 2223, 2253, 2284, 2315, 2346, 2378, 2410, 2442, 2474, 2507, 2540,
301 2573, 2606, 2640, 2674, 2708, 2743, 2778, 2813, 2849, 2884, 2920, 2957,
302 2993, 3030, 3067, 3105, 3143, 3181, 3219, 3258, 3297, 3336, 3376, 3416,
303 3456, 3496, 3537, 3578, 3619, 3661, 3703, 3745, 3788, 3831, 3874, 3918,
304 3962, 4006, 4050, 4095};
306 static constexpr uint8_t PCA9685_I2C_BASE_ADDRESS = 0b01000000;
307 static constexpr uint8_t PCA9685_MODE1
309 static constexpr uint8_t PCA9685_MODE2
311 static constexpr uint8_t PCA9685_LED0
313 static constexpr uint8_t PRE_SCALE_MODE