Skip to content

Commit 555096d

Browse files
committed
Update HD108 integration, schema, and indentions
1 parent 2872620 commit 555096d

File tree

3 files changed

+100
-46
lines changed

3 files changed

+100
-46
lines changed

assets/webconfig/js/content_leds.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ $(document).ready(function () {
11151115
case "ws2812spi":
11161116
case "piblaster":
11171117
case "ws281x":
1118-
case "hd108":
1118+
case "hd108":
11191119

11201120
//Serial devices
11211121
case "adalight":
@@ -1481,7 +1481,7 @@ $(document).ready(function () {
14811481
case "apa102_ftdi":
14821482
case "sk6812_ftdi":
14831483
case "ws2812_ftdi":
1484-
case "hd108":
1484+
case "hd108":
14851485
default:
14861486
}
14871487

@@ -2222,7 +2222,7 @@ var updateOutputSelectList = function (ledType, discoveryInfo) {
22222222
case "sk6822spi":
22232223
case "sk9822":
22242224
case "ws2812spi":
2225-
case "hd108":
2225+
case "hd108":
22262226
case "piblaster":
22272227
for (const device of discoveryInfo.devices) {
22282228
enumVals.push(device.systemLocation);
Lines changed: 96 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,133 @@
11
#include "LedDeviceHD108.h"
22

3-
// Constructor
3+
/**
4+
* @brief Constructor for the HD108 LED device.
5+
*
6+
* @param deviceConfig JSON configuration object for this device.
7+
*/
48
LedDeviceHD108::LedDeviceHD108(const QJsonObject &deviceConfig)
59
: ProviderSpi(deviceConfig)
610
{
7-
// Overwrite non supported/required features
8-
_latchTime_ms = 0;
9-
// Initialize _global_brightness
10-
_global_brightness = 0xFFFF;
11+
// By default, set the global brightness register to full (16-bit max)
12+
_global_brightness = 0xFFFF;
1113
}
1214

15+
/**
16+
* @brief Factory method: creates an instance of LedDeviceHD108.
17+
*
18+
* @param deviceConfig The JSON configuration for the device.
19+
* @return A pointer to the newly constructed LedDeviceHD108 instance.
20+
*/
1321
LedDevice* LedDeviceHD108::construct(const QJsonObject &deviceConfig)
1422
{
15-
return new LedDeviceHD108(deviceConfig);
23+
return new LedDeviceHD108(deviceConfig);
1624
}
1725

18-
// Initialization method
26+
/**
27+
* @brief Initializes the HD108 device using the given JSON configuration.
28+
*
29+
* This reads certain device-specific parameters, such as the maximum brightness
30+
* level, and configures the global brightness register accordingly.
31+
*
32+
* @param deviceConfig The JSON object containing device parameters.
33+
* @return True if initialization succeeded, false otherwise.
34+
*/
1935
bool LedDeviceHD108::init(const QJsonObject &deviceConfig)
2036
{
21-
bool isInitOK = false;
37+
bool isInitOK = false;
2238

23-
if ( ProviderSpi::init(deviceConfig) )
24-
{
25-
_brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(HD108_BRIGHTNESS_MAX_LEVEL);
26-
Info(_log, "[%s] Setting maximum brightness to [%d] = %d%%", QSTRING_CSTR(_activeDeviceType), _brightnessControlMaxLevel, _brightnessControlMaxLevel * 100 / HD108_BRIGHTNESS_MAX_LEVEL);
39+
// First, let the base SPI provider perform its initialization
40+
if (ProviderSpi::init(deviceConfig))
41+
{
42+
// Read brightnessControlMaxLevel from the config, falling back to a default if absent
43+
_brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(HD108_BRIGHTNESS_MAX_LEVEL);
44+
45+
// Log the brightness info
46+
Info(_log,
47+
"[%s] Setting maximum brightness to [%d] = %d%%",
48+
QSTRING_CSTR(_activeDeviceType),
49+
_brightnessControlMaxLevel,
50+
_brightnessControlMaxLevel * 100 / HD108_BRIGHTNESS_MAX_LEVEL);
2751

28-
// Set the global brightness or control byte based on the provided formula
29-
_global_brightness = (1 << 15) | (_brightnessControlMaxLevel << 10) | (_brightnessControlMaxLevel << 5) | _brightnessControlMaxLevel;
52+
// Combine the brightness levels into the HD108's 16-bit brightness field.
53+
// According to the HD108 spec, this is composed of a control bit plus
54+
// the brightness level split into three segments for R, G, B.
55+
_global_brightness = (1 << 15)
56+
| (_brightnessControlMaxLevel << 10)
57+
| (_brightnessControlMaxLevel << 5)
58+
| _brightnessControlMaxLevel;
3059

31-
isInitOK = true;
32-
}
60+
isInitOK = true;
61+
}
3362

34-
return isInitOK;
63+
return isInitOK;
3564
}
3665

37-
// Write method to update the LED colors
66+
/**
67+
* @brief Writes a vector of RGB colors to the HD108 LEDs.
68+
*
69+
* The HD108 protocol requires:
70+
* - A start frame of 64 bits (8 bytes) all set to 0x00.
71+
* - For each LED, 64 bits:
72+
* - 16 bits of global brightness
73+
* - 16 bits for red
74+
* - 16 bits for green
75+
* - 16 bits for blue
76+
* - An end frame of at least (ledCount / 16 + 1) bytes of 0xFF.
77+
*
78+
* Each 8-bit color value is expanded to 16 bits by copying it into both the high
79+
* and low byte (e.g. 0x7F -> 0x7F7F). This ensures a correct mapping to the HD108's
80+
* internal 16-bit color resolution and allows for a true "off" state at 0x0000.
81+
*
82+
* @param ledValues A vector of ColorRgb (red, green, blue) structures.
83+
* @return The result of the SPI write operation (0 for success, or an error code).
84+
*/
3885
int LedDeviceHD108::write(const std::vector<ColorRgb> & ledValues)
3986
{
87+
// Calculate how much space we need in total:
88+
// - 8 bytes for the start frame
89+
// - 8 bytes per LED (16 bits global brightness + 16 bits R + G + B)
90+
// - end frame: ledCount / 16 + 1 bytes of 0xFF
91+
const size_t ledCount = ledValues.size();
92+
const size_t totalSize = 8 // start frame
93+
+ (ledCount * 8) // LED data (8 bytes each)
94+
+ (ledCount / 16 + 1); // end frame bytes
95+
96+
// Reserve enough space to avoid multiple allocations
4097
std::vector<uint8_t> hd108Data;
98+
hd108Data.reserve(totalSize);
4199

42-
// Start frame - 64 bits of 0 (8 bytes of 0)
100+
// 1) Start frame: 64 bits of 0x00
43101
hd108Data.insert(hd108Data.end(), 8, 0x00);
44102

45-
// Adapted logic from your HD108 library's "show" and "setPixelColor8Bit" methods
103+
// 2) For each LED, insert 8 bytes: 16 bits brightness, 16 bits R, 16 bits G, 16 bits B
46104
for (const ColorRgb &color : ledValues)
47105
{
48-
// Convert 8-bit to 16-bit colors
49-
uint16_t red16 = (color.red << 8) | color.red;
50-
uint16_t green16 = (color.green << 8) | color.green;
51-
uint16_t blue16 = (color.blue << 8) | color.blue;
106+
// Expand 8-bit color components to 16 bits each
107+
uint16_t red16 = (static_cast<uint16_t>(color.red) << 8) | color.red;
108+
uint16_t green16 = (static_cast<uint16_t>(color.green) << 8) | color.green;
109+
uint16_t blue16 = (static_cast<uint16_t>(color.blue) << 8) | color.blue;
52110

53-
// Push global and color components into hd108Data
54-
// Brightness
111+
// Global brightness (16 bits)
55112
hd108Data.push_back(_global_brightness >> 8);
56-
hd108Data.push_back(_global_brightness & 0xFF);
57-
// Color - Red
113+
hd108Data.push_back(_global_brightness & 0xFF);
114+
115+
// Red (16 bits)
58116
hd108Data.push_back(red16 >> 8);
59-
hd108Data.push_back(red16 & 0xFF);
60-
// Color - Green
117+
hd108Data.push_back(red16 & 0xFF);
118+
119+
// Green (16 bits)
61120
hd108Data.push_back(green16 >> 8);
62-
hd108Data.push_back(green16 & 0xFF);
63-
// Color - Blue
121+
hd108Data.push_back(green16 & 0xFF);
122+
123+
// Blue (16 bits)
64124
hd108Data.push_back(blue16 >> 8);
65-
hd108Data.push_back(blue16 & 0xFF);
125+
hd108Data.push_back(blue16 & 0xFF);
66126
}
67127

68-
// End frame - write "1"s equal to at least how many pixels are in the string
69-
hd108Data.insert(hd108Data.end(), ledValues.size() / 16 + 1, 0xFF);
128+
// 3) End frame: at least (ledCount / 16 + 1) bytes of 0xFF
129+
hd108Data.insert(hd108Data.end(), (ledCount / 16) + 1, 0xFF);
70130

71-
// Use ProviderSpi's writeBytes method to send the data
131+
// Finally, transmit the assembled data via SPI
72132
return writeBytes(hd108Data.size(), hd108Data.data());
73133
}

libsrc/leddevice/schemas/schema-hd108.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,9 @@
1010
"rate": {
1111
"type": "integer",
1212
"title":"edt_dev_spec_baudrate_title",
13-
"default": 1000000,
13+
"default": 3000000,
1414
"propertyOrder" : 2
1515
},
16-
"invert": {
17-
"type": "boolean",
18-
"title":"edt_dev_spec_invert_title",
19-
"default": false,
20-
"propertyOrder" : 3
21-
},
2216
"brightnessControlMaxLevel": {
2317
"type": "integer",
2418
"title":"edt_conf_color_brightness_title",

0 commit comments

Comments
 (0)