| 228 | } |
| 229 | |
| 230 | void RCOutput_PCA9685::push() |
| 231 | { |
| 232 | if (!_corking) { |
| 233 | return; |
| 234 | } |
| 235 | _corking = false; |
| 236 | |
| 237 | if (_pending_write_mask == 0) |
| 238 | return; |
| 239 | |
| 240 | // Calculate the number of channels for this transfer. |
| 241 | uint8_t max_ch = (sizeof(unsigned) * 8) - __builtin_clz(_pending_write_mask); |
| 242 | uint8_t min_ch = __builtin_ctz(_pending_write_mask); |
| 243 | |
| 244 | /* |
| 245 | * scratch buffer size is always for all the channels, but we write only |
| 246 | * from min_ch to max_ch |
| 247 | */ |
| 248 | struct PACKED pwm_values { |
| 249 | uint8_t reg; |
| 250 | uint8_t data[PWM_CHAN_COUNT * 4]; |
| 251 | } pwm_values; |
| 252 | |
| 253 | for (unsigned ch = min_ch; ch < max_ch; ch++) { |
| 254 | uint16_t period_us = _pulses_buffer[ch]; |
| 255 | uint16_t length = 0; |
| 256 | |
| 257 | if (period_us) { |
| 258 | length = round((period_us * 4096) / (1000000.f / _frequency)) - 1; |
| 259 | } |
| 260 | |
| 261 | uint8_t *d = &pwm_values.data[(ch - min_ch) * 4]; |
| 262 | |
| 263 | if (_is_gpio_mask & (1 << ch)) { |
| 264 | *d++ = 0; // LEDn_ON_L |
| 265 | *d++ = period_us ? PCA9685_LED_ON_H_ALWAYS_ON_BIT : 0; // LEDn_ON_H |
| 266 | *d++ = 0; // LEDn_OFF_L |
| 267 | *d++ = period_us ? 0 : PCA9685_LED_OFF_H_ALWAYS_OFF_BIT; // LEDn_OFF_H |
| 268 | } else { |
| 269 | *d++ = 0; // LEDn_ON_L |
| 270 | *d++ = 0; // LEDn_ON_H |
| 271 | *d++ = length & 0xFF; // LEDn_OFF_L |
| 272 | *d++ = length >> 8; // LEDn_OFF_H |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | if (!_dev || !_dev->get_semaphore()->take_nonblocking()) { |
| 277 | return; |
| 278 | } |
| 279 | |
| 280 | pwm_values.reg = PCA9685_RA_LED0_ON_L + 4 * (_channel_offset + min_ch); |
| 281 | /* reg + all the channels we are going to write */ |
| 282 | size_t payload_size = 1 + (max_ch - min_ch) * 4; |
| 283 | |
| 284 | _dev->transfer((uint8_t *)&pwm_values, payload_size, nullptr, 0); |
| 285 | _dev->get_semaphore()->give(); |
| 286 | _pending_write_mask = 0; |
| 287 | } |
nothing calls this directly
no test coverage detected