Implement much more efficient LED driver updater algorithm that only talks to the LED driver ICs when necessary. Add LED_DRIVER_STRESS_TEST macro.

This commit is contained in:
László Monda
2017-07-31 17:30:33 +02:00
parent a30c078f02
commit 546ca5d0b2
4 changed files with 59 additions and 9 deletions

View File

@@ -60,6 +60,8 @@ void InitPeripherals(void)
InitI2c();
InitTestLed();
LedPwm_Init();
#ifndef LED_DRIVER_STRESS_TEST
InitI2cWatchdog();
#endif
EEPROM_Init();
}

View File

@@ -65,12 +65,12 @@ void LedDisplay_SetText(uint8_t length, const char* text) {
case 1:
allSegmentSets |= characterToSegmentSet(text[0]);
}
LedDriverStates[LedDriverId_Left].ledValues[11] = allSegmentSets & 0b00000001 ? 255 : 0;
LedDriverStates[LedDriverId_Left].ledValues[12] = allSegmentSets & 0b00000010 ? 255 : 0;
LedDriverStates[LedDriverId_Left].sourceLedValues[11] = allSegmentSets & 0b00000001 ? 255 : 0;
LedDriverStates[LedDriverId_Left].sourceLedValues[12] = allSegmentSets & 0b00000010 ? 255 : 0;
allSegmentSets >>= 2;
for (uint8_t i = 24; i <= 136; i += 16) {
for (uint8_t j = 0; j < 5; j++) {
LedDriverStates[LedDriverId_Left].ledValues[i + j] = allSegmentSets & 1 << j ? 255 : 0;
LedDriverStates[LedDriverId_Left].sourceLedValues[i + j] = allSegmentSets & 1 << j ? 255 : 0;
}
allSegmentSets >>= 5;
}
@@ -79,13 +79,13 @@ void LedDisplay_SetText(uint8_t length, const char* text) {
void LedDisplay_SetLayer(uint8_t layerId) {
for (uint8_t i = 13; i <= 45; i += 16) {
LedDriverStates[LedDriverId_Left].ledValues[i] = 0;
LedDriverStates[LedDriverId_Left].sourceLedValues[i] = 0;
}
if (layerId >= LAYER_ID_MOD && layerId <= LAYER_ID_MOUSE) {
LedDriverStates[LedDriverId_Left].ledValues[16 * layerId - 3] = 255;
LedDriverStates[LedDriverId_Left].sourceLedValues[16 * layerId - 3] = 255;
}
}
void LedDisplay_SetIcon(led_display_icon_t icon, bool isEnabled) {
LedDriverStates[LedDriverId_Left].ledValues[8 + icon] = isEnabled ? 255 : 0;
LedDriverStates[LedDriverId_Left].sourceLedValues[8 + icon] = isEnabled ? 255 : 0;
}

View File

@@ -63,6 +63,7 @@ void LedSlaveDriver_Init(uint8_t ledDriverId) {
currentLedDriverState->phase = LedDriverPhase_SetFunctionFrame;
currentLedDriverState->ledIndex = 0;
LedDriverStates[LedDriverId_Left].setupLedControlRegistersCommand[7] |= 0b00000010; // Enable the LED of the ISO key.
memset(currentLedDriverState->targetLedValues, 0xff, LED_DRIVER_LED_COUNT);
SetLeds(0xff);
LedDisplay_SetText(3, "ABC");
}
@@ -94,20 +95,66 @@ void LedSlaveDriver_Update(uint8_t ledDriverId) {
*ledDriverPhase = LedDriverPhase_Initialized;
break;
case LedDriverPhase_Initialized:
{
#ifdef LED_DRIVER_STRESS_TEST
updatePwmRegistersBuffer[0] = FRAME_REGISTER_PWM_FIRST + *ledIndex;
memcpy(updatePwmRegistersBuffer+1, currentLedDriverState->ledValues + *ledIndex, PMW_REGISTER_UPDATE_CHUNK_SIZE);
memcpy(updatePwmRegistersBuffer+1, currentLedDriverState->sourceLedValues + *ledIndex, PMW_REGISTER_UPDATE_CHUNK_SIZE);
I2cAsyncWrite(ledDriverAddress, updatePwmRegistersBuffer, PWM_REGISTER_BUFFER_LENGTH);
*ledIndex += PMW_REGISTER_UPDATE_CHUNK_SIZE;
if (*ledIndex >= LED_DRIVER_LED_COUNT) {
*ledIndex = 0;
}
#else
uint8_t *sourceLedValues = currentLedDriverState->sourceLedValues;
uint8_t *targetLedValues = currentLedDriverState->targetLedValues;
uint8_t lastLedChunkStartIndex = LED_DRIVER_LED_COUNT - PMW_REGISTER_UPDATE_CHUNK_SIZE;
uint8_t startLedIndex = *ledIndex > lastLedChunkStartIndex ? lastLedChunkStartIndex : *ledIndex;
uint8_t count;
for (count=0; count<LED_DRIVER_LED_COUNT; count++) {
if (sourceLedValues[startLedIndex] != targetLedValues[startLedIndex]) {
break;
}
if (++startLedIndex >= LED_DRIVER_LED_COUNT) {
startLedIndex = 0;
}
}
bool foundStartIndex = count < LED_DRIVER_LED_COUNT;
if (!foundStartIndex) {
*ledIndex = 0;
return;
}
uint8_t maxChunkSize = MIN(LED_DRIVER_LED_COUNT - startLedIndex, PMW_REGISTER_UPDATE_CHUNK_SIZE);
uint8_t maxEndLedIndex = startLedIndex + maxChunkSize - 1;
uint8_t endLedIndex = startLedIndex;
for (uint8_t index=startLedIndex; index<=maxEndLedIndex; index++) {
if (sourceLedValues[index] != targetLedValues[index]) {
endLedIndex = index;
}
}
updatePwmRegistersBuffer[0] = FRAME_REGISTER_PWM_FIRST + startLedIndex;
uint8_t length = endLedIndex - startLedIndex + 1;
memcpy(updatePwmRegistersBuffer+1, currentLedDriverState->sourceLedValues + startLedIndex, length);
memcpy(currentLedDriverState->targetLedValues + startLedIndex, currentLedDriverState->sourceLedValues + startLedIndex, length);
I2cAsyncWrite(ledDriverAddress, updatePwmRegistersBuffer, length+1);
*ledIndex += length;
if (*ledIndex >= LED_DRIVER_LED_COUNT) {
*ledIndex = 0;
}
#endif
break;
}
}
}
void SetLeds(uint8_t ledBrightness)
{
for (uint8_t i=0; i<LED_DRIVER_MAX_COUNT; i++) {
memset(&LedDriverStates[i].ledValues, ledBrightness, LED_DRIVER_LED_COUNT);
memset(&LedDriverStates[i].sourceLedValues, ledBrightness, LED_DRIVER_LED_COUNT);
}
}

View File

@@ -31,7 +31,8 @@
typedef struct {
led_driver_phase_t phase;
uint8_t ledValues[LED_DRIVER_LED_COUNT];
uint8_t sourceLedValues[LED_DRIVER_LED_COUNT];
uint8_t targetLedValues[LED_DRIVER_LED_COUNT];
uint8_t ledIndex;
uint8_t i2cAddress;
uint8_t setupLedControlRegistersCommand[LED_CONTROL_REGISTERS_COMMAND_LENGTH];