mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Merge 555096dcba6541e090c161eb0b98b59406cae7d0 into dd81a23dfca5b434b7199153ab08c06cf611b3c7
This commit is contained in:
commit
04564416c1
@ -18,7 +18,7 @@ var bottomRight2bottomLeft = null;
|
|||||||
var bottomLeft2topLeft = null;
|
var bottomLeft2topLeft = null;
|
||||||
var toggleKeystoneCorrectionArea = false;
|
var toggleKeystoneCorrectionArea = false;
|
||||||
|
|
||||||
var devSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2812spi'];
|
var devSPI = ['apa102', 'apa104', 'hd108', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2801', 'ws2812spi'];
|
||||||
var devFTDI = ['apa102_ftdi', 'sk6812_ftdi', 'ws2812_ftdi'];
|
var devFTDI = ['apa102_ftdi', 'sk6812_ftdi', 'ws2812_ftdi'];
|
||||||
var devRPiPWM = ['ws281x'];
|
var devRPiPWM = ['ws281x'];
|
||||||
var devRPiGPIO = ['piblaster'];
|
var devRPiGPIO = ['piblaster'];
|
||||||
@ -1115,6 +1115,7 @@ $(document).ready(function () {
|
|||||||
case "ws2812spi":
|
case "ws2812spi":
|
||||||
case "piblaster":
|
case "piblaster":
|
||||||
case "ws281x":
|
case "ws281x":
|
||||||
|
case "hd108":
|
||||||
|
|
||||||
//Serial devices
|
//Serial devices
|
||||||
case "adalight":
|
case "adalight":
|
||||||
@ -1480,6 +1481,7 @@ $(document).ready(function () {
|
|||||||
case "apa102_ftdi":
|
case "apa102_ftdi":
|
||||||
case "sk6812_ftdi":
|
case "sk6812_ftdi":
|
||||||
case "ws2812_ftdi":
|
case "ws2812_ftdi":
|
||||||
|
case "hd108":
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1962,6 +1964,7 @@ function saveLedConfig(genDefLayout = false) {
|
|||||||
case "apa102_ftdi":
|
case "apa102_ftdi":
|
||||||
case "sk6812_ftdi":
|
case "sk6812_ftdi":
|
||||||
case "ws2812_ftdi":
|
case "ws2812_ftdi":
|
||||||
|
case "hd108":
|
||||||
default:
|
default:
|
||||||
if (genDefLayout === true) {
|
if (genDefLayout === true) {
|
||||||
ledConfig = {
|
ledConfig = {
|
||||||
@ -2219,6 +2222,7 @@ var updateOutputSelectList = function (ledType, discoveryInfo) {
|
|||||||
case "sk6822spi":
|
case "sk6822spi":
|
||||||
case "sk9822":
|
case "sk9822":
|
||||||
case "ws2812spi":
|
case "ws2812spi":
|
||||||
|
case "hd108":
|
||||||
case "piblaster":
|
case "piblaster":
|
||||||
for (const device of discoveryInfo.devices) {
|
for (const device of discoveryInfo.devices) {
|
||||||
enumVals.push(device.systemLocation);
|
enumVals.push(device.systemLocation);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
<file alias="schema-ws2812_ftdi">schemas/schema-ws2812_ftdi.json</file>
|
<file alias="schema-ws2812_ftdi">schemas/schema-ws2812_ftdi.json</file>
|
||||||
<file alias="schema-apa102_ftdi">schemas/schema-apa102_ftdi.json</file>
|
<file alias="schema-apa102_ftdi">schemas/schema-apa102_ftdi.json</file>
|
||||||
<file alias="schema-sk6812_ftdi">schemas/schema-sk6812_ftdi.json</file>
|
<file alias="schema-sk6812_ftdi">schemas/schema-sk6812_ftdi.json</file>
|
||||||
<file alias="schema-skydimo">schemas/schema-skydimo.json</file>
|
<file alias="schema-skydimo">schemas/schema-skydimo.json</file>
|
||||||
|
<file alias="schema-hd108">schemas/schema-hd108.json</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
133
libsrc/leddevice/dev_spi/LedDeviceHD108.cpp
Normal file
133
libsrc/leddevice/dev_spi/LedDeviceHD108.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#include "LedDeviceHD108.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor for the HD108 LED device.
|
||||||
|
*
|
||||||
|
* @param deviceConfig JSON configuration object for this device.
|
||||||
|
*/
|
||||||
|
LedDeviceHD108::LedDeviceHD108(const QJsonObject &deviceConfig)
|
||||||
|
: ProviderSpi(deviceConfig)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
// First, let the base SPI provider perform its initialization
|
||||||
|
if (ProviderSpi::init(deviceConfig))
|
||||||
|
{
|
||||||
|
// Read brightnessControlMaxLevel from the config, falling back to a default if absent
|
||||||
|
_brightnessControlMaxLevel = deviceConfig["brightnessControlMaxLevel"].toInt(HD108_BRIGHTNESS_MAX_LEVEL);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isInitOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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<ColorRgb> & 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<uint8_t> 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<uint16_t>(color.red) << 8) | color.red;
|
||||||
|
uint16_t green16 = (static_cast<uint16_t>(color.green) << 8) | color.green;
|
||||||
|
uint16_t blue16 = (static_cast<uint16_t>(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());
|
||||||
|
}
|
53
libsrc/leddevice/dev_spi/LedDeviceHD108.h
Normal file
53
libsrc/leddevice/dev_spi/LedDeviceHD108.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef LEDDEVICEHD108_H
|
||||||
|
#define LEDDEVICEHD108_H
|
||||||
|
|
||||||
|
#include "ProviderSpi.h"
|
||||||
|
|
||||||
|
/// The maximal level supported by the HD108 brightness control field, 31
|
||||||
|
const int HD108_BRIGHTNESS_MAX_LEVEL = 31;
|
||||||
|
|
||||||
|
|
||||||
|
class LedDeviceHD108 : public ProviderSpi
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Constructs an HD108 LED-device
|
||||||
|
///
|
||||||
|
/// @param deviceConfig Device's configuration as JSON-Object
|
||||||
|
///
|
||||||
|
explicit LedDeviceHD108(const QJsonObject &deviceConfig);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Constructs the LED-device
|
||||||
|
///
|
||||||
|
/// @param[in] deviceConfig Device's configuration as JSON-Object
|
||||||
|
/// @return LedDevice constructed
|
||||||
|
///
|
||||||
|
static LedDevice* construct(const QJsonObject &deviceConfig);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Initialise the device's configuration
|
||||||
|
///
|
||||||
|
/// @param[in] deviceConfig the JSON device configuration
|
||||||
|
/// @return True, if success
|
||||||
|
///
|
||||||
|
bool init(const QJsonObject &deviceConfig) override;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Writes the RGB-Color values to the LEDs.
|
||||||
|
///
|
||||||
|
/// @param[in] ledValues The RGB-color per LED
|
||||||
|
/// @return Zero on success, else negative
|
||||||
|
///
|
||||||
|
int write(const std::vector<ColorRgb> & ledValues) override;
|
||||||
|
|
||||||
|
/// The brighness level. Possibile values 1 .. 31.
|
||||||
|
int _brightnessControlMaxLevel;
|
||||||
|
uint16_t _global_brightness;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LEDDEVICEHD108_H
|
35
libsrc/leddevice/schemas/schema-hd108.json
Normal file
35
libsrc/leddevice/schemas/schema-hd108.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"output": {
|
||||||
|
"type": "string",
|
||||||
|
"title":"edt_dev_spec_spipath_title",
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"rate": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"edt_dev_spec_baudrate_title",
|
||||||
|
"default": 3000000,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"brightnessControlMaxLevel": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"edt_conf_color_brightness_title",
|
||||||
|
"default": 31,
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 31,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"rewriteTime": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"edt_dev_general_rewriteTime_title",
|
||||||
|
"default": 0,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"minimum": 0,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user