From 555096dcba6541e090c161eb0b98b59406cae7d0 Mon Sep 17 00:00:00 2001 From: FutureMan Date: Sat, 22 Feb 2025 15:55:49 +0100 Subject: [PATCH] Update HD108 integration, schema, and indentions --- assets/webconfig/js/content_leds.js | 6 +- libsrc/leddevice/dev_spi/LedDeviceHD108.cpp | 164 +++++++++++++------- libsrc/leddevice/schemas/schema-hd108.json | 8 +- 3 files changed, 116 insertions(+), 62 deletions(-) diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js index 2a1f6ee8..aa468cd1 100755 --- a/assets/webconfig/js/content_leds.js +++ b/assets/webconfig/js/content_leds.js @@ -1115,7 +1115,7 @@ $(document).ready(function () { case "ws2812spi": case "piblaster": case "ws281x": - case "hd108": + case "hd108": //Serial devices case "adalight": @@ -1481,7 +1481,7 @@ $(document).ready(function () { case "apa102_ftdi": case "sk6812_ftdi": case "ws2812_ftdi": - case "hd108": + case "hd108": default: } @@ -2222,7 +2222,7 @@ var updateOutputSelectList = function (ledType, discoveryInfo) { case "sk6822spi": case "sk9822": case "ws2812spi": - case "hd108": + case "hd108": case "piblaster": for (const device of discoveryInfo.devices) { enumVals.push(device.systemLocation); diff --git a/libsrc/leddevice/dev_spi/LedDeviceHD108.cpp b/libsrc/leddevice/dev_spi/LedDeviceHD108.cpp index 2df1dddb..964c9b5d 100644 --- a/libsrc/leddevice/dev_spi/LedDeviceHD108.cpp +++ b/libsrc/leddevice/dev_spi/LedDeviceHD108.cpp @@ -1,73 +1,133 @@ #include "LedDeviceHD108.h" -// Constructor +/** + * @brief Constructor for the HD108 LED device. + * + * @param deviceConfig JSON configuration object for this device. + */ LedDeviceHD108::LedDeviceHD108(const QJsonObject &deviceConfig) : ProviderSpi(deviceConfig) { - // Overwrite non supported/required features - _latchTime_ms = 0; - // Initialize _global_brightness - _global_brightness = 0xFFFF; + // By default, set the global brightness register to full (16-bit max) + _global_brightness = 0xFFFF; } +/** + * @brief Factory method: creates an instance of LedDeviceHD108. + * + * @param deviceConfig The JSON configuration for the device. + * @return A pointer to the newly constructed LedDeviceHD108 instance. + */ LedDevice* LedDeviceHD108::construct(const QJsonObject &deviceConfig) { - return new LedDeviceHD108(deviceConfig); + return new LedDeviceHD108(deviceConfig); } -// Initialization method +/** + * @brief Initializes the HD108 device using the given JSON configuration. + * + * This reads certain device-specific parameters, such as the maximum brightness + * level, and configures the global brightness register accordingly. + * + * @param deviceConfig The JSON object containing device parameters. + * @return True if initialization succeeded, false otherwise. + */ bool LedDeviceHD108::init(const QJsonObject &deviceConfig) { - bool isInitOK = false; + bool isInitOK = false; - if ( ProviderSpi::init(deviceConfig) ) - { - _brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(HD108_BRIGHTNESS_MAX_LEVEL); - Info(_log, "[%s] Setting maximum brightness to [%d] = %d%%", QSTRING_CSTR(_activeDeviceType), _brightnessControlMaxLevel, _brightnessControlMaxLevel * 100 / HD108_BRIGHTNESS_MAX_LEVEL); - - // Set the global brightness or control byte based on the provided formula - _global_brightness = (1 << 15) | (_brightnessControlMaxLevel << 10) | (_brightnessControlMaxLevel << 5) | _brightnessControlMaxLevel; - - isInitOK = true; - } - - return isInitOK; -} - -// Write method to update the LED colors -int LedDeviceHD108::write(const std::vector & ledValues) -{ - std::vector hd108Data; - - // Start frame - 64 bits of 0 (8 bytes of 0) - hd108Data.insert(hd108Data.end(), 8, 0x00); - - // Adapted logic from your HD108 library's "show" and "setPixelColor8Bit" methods - for (const ColorRgb &color : ledValues) + // First, let the base SPI provider perform its initialization + if (ProviderSpi::init(deviceConfig)) { - // Convert 8-bit to 16-bit colors - uint16_t red16 = (color.red << 8) | color.red; - uint16_t green16 = (color.green << 8) | color.green; - uint16_t blue16 = (color.blue << 8) | color.blue; + // Read brightnessControlMaxLevel from the config, falling back to a default if absent + _brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(HD108_BRIGHTNESS_MAX_LEVEL); - // Push global and color components into hd108Data - // Brightness - hd108Data.push_back(_global_brightness >> 8); - hd108Data.push_back(_global_brightness & 0xFF); - // Color - Red - hd108Data.push_back(red16 >> 8); - hd108Data.push_back(red16 & 0xFF); - // Color - Green - hd108Data.push_back(green16 >> 8); - hd108Data.push_back(green16 & 0xFF); - // Color - Blue - hd108Data.push_back(blue16 >> 8); - hd108Data.push_back(blue16 & 0xFF); + // Log the brightness info + Info(_log, + "[%s] Setting maximum brightness to [%d] = %d%%", + QSTRING_CSTR(_activeDeviceType), + _brightnessControlMaxLevel, + _brightnessControlMaxLevel * 100 / HD108_BRIGHTNESS_MAX_LEVEL); + + // Combine the brightness levels into the HD108's 16-bit brightness field. + // According to the HD108 spec, this is composed of a control bit plus + // the brightness level split into three segments for R, G, B. + _global_brightness = (1 << 15) + | (_brightnessControlMaxLevel << 10) + | (_brightnessControlMaxLevel << 5) + | _brightnessControlMaxLevel; + + isInitOK = true; } - // End frame - write "1"s equal to at least how many pixels are in the string - hd108Data.insert(hd108Data.end(), ledValues.size() / 16 + 1, 0xFF); + return isInitOK; +} - // Use ProviderSpi's writeBytes method to send the data +/** + * @brief Writes a vector of RGB colors to the HD108 LEDs. + * + * The HD108 protocol requires: + * - A start frame of 64 bits (8 bytes) all set to 0x00. + * - For each LED, 64 bits: + * - 16 bits of global brightness + * - 16 bits for red + * - 16 bits for green + * - 16 bits for blue + * - An end frame of at least (ledCount / 16 + 1) bytes of 0xFF. + * + * Each 8-bit color value is expanded to 16 bits by copying it into both the high + * and low byte (e.g. 0x7F -> 0x7F7F). This ensures a correct mapping to the HD108's + * internal 16-bit color resolution and allows for a true "off" state at 0x0000. + * + * @param ledValues A vector of ColorRgb (red, green, blue) structures. + * @return The result of the SPI write operation (0 for success, or an error code). + */ +int LedDeviceHD108::write(const std::vector & ledValues) +{ + // Calculate how much space we need in total: + // - 8 bytes for the start frame + // - 8 bytes per LED (16 bits global brightness + 16 bits R + G + B) + // - end frame: ledCount / 16 + 1 bytes of 0xFF + const size_t ledCount = ledValues.size(); + const size_t totalSize = 8 // start frame + + (ledCount * 8) // LED data (8 bytes each) + + (ledCount / 16 + 1); // end frame bytes + + // Reserve enough space to avoid multiple allocations + std::vector hd108Data; + hd108Data.reserve(totalSize); + + // 1) Start frame: 64 bits of 0x00 + hd108Data.insert(hd108Data.end(), 8, 0x00); + + // 2) For each LED, insert 8 bytes: 16 bits brightness, 16 bits R, 16 bits G, 16 bits B + for (const ColorRgb &color : ledValues) + { + // Expand 8-bit color components to 16 bits each + uint16_t red16 = (static_cast(color.red) << 8) | color.red; + uint16_t green16 = (static_cast(color.green) << 8) | color.green; + uint16_t blue16 = (static_cast(color.blue) << 8) | color.blue; + + // Global brightness (16 bits) + hd108Data.push_back(_global_brightness >> 8); + hd108Data.push_back(_global_brightness & 0xFF); + + // Red (16 bits) + hd108Data.push_back(red16 >> 8); + hd108Data.push_back(red16 & 0xFF); + + // Green (16 bits) + hd108Data.push_back(green16 >> 8); + hd108Data.push_back(green16 & 0xFF); + + // Blue (16 bits) + hd108Data.push_back(blue16 >> 8); + hd108Data.push_back(blue16 & 0xFF); + } + + // 3) End frame: at least (ledCount / 16 + 1) bytes of 0xFF + hd108Data.insert(hd108Data.end(), (ledCount / 16) + 1, 0xFF); + + // Finally, transmit the assembled data via SPI return writeBytes(hd108Data.size(), hd108Data.data()); } diff --git a/libsrc/leddevice/schemas/schema-hd108.json b/libsrc/leddevice/schemas/schema-hd108.json index 43bc649c..8f3c30af 100644 --- a/libsrc/leddevice/schemas/schema-hd108.json +++ b/libsrc/leddevice/schemas/schema-hd108.json @@ -10,15 +10,9 @@ "rate": { "type": "integer", "title":"edt_dev_spec_baudrate_title", - "default": 1000000, + "default": 3000000, "propertyOrder" : 2 }, - "invert": { - "type": "boolean", - "title":"edt_dev_spec_invert_title", - "default": false, - "propertyOrder" : 3 - }, "brightnessControlMaxLevel": { "type": "integer", "title":"edt_conf_color_brightness_title",