Update LedDeviceAPA102.cpp

This fix the previous limit of 64 APA102 leds, because of too short end frame. Now the end frame is computed accordling to this documentation: https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/. Tested on my 98 leds, it works fine.

I suggest to modify hyperion to allow LED drivers to apply the brightness parameter because APA102 has a parameter for that, without the need to elaborate RGB color to simulate it (result is wrong colors!). Is it possible to introduce such parameter in LED drivers and let the driver apply that?

Former-commit-id: 2d714e6eb075ec57e0973839fe96d2d7a051c57f
This commit is contained in:
pcaffardi 2015-08-09 16:15:25 +02:00
parent cc5b57e4c0
commit 2eea311dce

View File

@ -1,4 +1,3 @@
// STL includes
#include <cstring>
#include <cstdio>
@ -18,22 +17,45 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned
// empty
}
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define APA102_START_FRAME_BYTES 4
#define APA102_LED_BYTES 4
#define APA102_END_FRAME_BITS_MIN 32
#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN)
#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1)
#define APA102_LED_HEADER 0xe0
#define APA102_LED_MAX_INTENSITY 0x1f
int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
{
const unsigned int startFrameSize = 4;
const unsigned int endFrameSize = (ledValues.size() + 63) / 64 * 4;
const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize;
if(_ledBuffer.size() != mLedCount){
_ledBuffer.resize(mLedCount, 0x00);
const unsigned int startFrameSize = APA102_START_FRAME_BYTES;
const unsigned int ledsCount = ledValues.size() ;
const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ;
const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ;
const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ;
const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ;
if(_ledBuffer.size() != transferSize){
_ledBuffer.resize(transferSize, 0x00);
}
unsigned idx = 0, i;
for (i=0; i<APA102_START_FRAME_BYTES; i++) {
_ledBuffer[idx++] = 0x00 ;
}
for (unsigned iLed=1; iLed<=ledValues.size(); ++iLed) {
const ColorRgb& rgb = ledValues[iLed];
_ledBuffer[iLed*4] = 0xFF;
_ledBuffer[iLed*4+1] = rgb.red;
_ledBuffer[iLed*4+2] = rgb.green;
_ledBuffer[iLed*4+3] = rgb.blue;
for (i=0; i<ledsCount; i++) {
const ColorRgb& rgb = ledValues[i];
_ledBuffer[idx++] = APA102_LED_HEADER + APA102_LED_MAX_INTENSITY;
_ledBuffer[idx++] = rgb.red;
_ledBuffer[idx++] = rgb.green;
_ledBuffer[idx++] = rgb.blue;
}
for(i=0; i<endFrameSize; i++)
_ledBuffer[idx++] = 0x00 ;
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}
@ -41,4 +63,4 @@ int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
int LedDeviceAPA102::switchOff()
{
return write(std::vector<ColorRgb>(_ledBuffer.size(), ColorRgb{0,0,0}));
}
}