Skip to content

Commit 69da76c

Browse files
authored
Add support for HD108 led strip (16bits colors) (#527)
* Add support for HD108 led strip (16bits colors) * HD108 improvements * HD108 improvements
1 parent 7d180e9 commit 69da76c

File tree

5 files changed

+239
-2
lines changed

5 files changed

+239
-2
lines changed

Diff for: sources/leddevice/LedDeviceSchemas.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<file alias="schema-sk6812spi">schemas/schema-sk6812spi.json</file>
2020
<file alias="schema-sk6822spi">schemas/schema-sk6822spi.json</file>
2121
<file alias="schema-sk9822">schemas/schema-sk9822.json</file>
22+
<file alias="schema-hd108">schemas/schema-hd108.json</file>
2223
<file alias="schema-tinkerforge">schemas/schema-tinkerforge.json</file>
2324
<file alias="schema-tpm2net">schemas/schema-tpm2net.json</file>
2425
<file alias="schema-tpm2">schemas/schema-tpm2.json</file>

Diff for: sources/leddevice/dev_spi/LedDeviceHD108.cpp

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/* LedDeviceHD108.cpp
2+
*
3+
* MIT License
4+
*
5+
* Copyright (c) 2023 awawa-dev
6+
*
7+
* Project homesite: https://github.com/awawa-dev/HyperHDR
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*/
27+
28+
#include "LedDeviceHD108.h"
29+
30+
// Local HyperHDR includes
31+
#include <utils/Logger.h>
32+
#include <cmath>
33+
#include <algorithm>
34+
35+
const int HD108_MAX_LEVEL = 0x1F;
36+
const uint32_t HD108_MAX_THRESHOLD = 100u;
37+
const uint32_t HD108_MAX_THRESHOLD_2 = HD108_MAX_THRESHOLD * HD108_MAX_THRESHOLD;
38+
const uint16_t HD108_MAX_LEVEL_BIT = 0b1000000000000000;
39+
40+
LedDeviceHD108::LedDeviceHD108(const QJsonObject& deviceConfig)
41+
: ProviderSpi(deviceConfig)
42+
, _globalBrightnessControlThreshold(HD108_MAX_THRESHOLD)
43+
, _globalBrightnessControlMaxLevel(HD108_MAX_LEVEL)
44+
{
45+
}
46+
47+
LedDevice* LedDeviceHD108::construct(const QJsonObject& deviceConfig)
48+
{
49+
return new LedDeviceHD108(deviceConfig);
50+
}
51+
52+
bool LedDeviceHD108::init(const QJsonObject& deviceConfig)
53+
{
54+
bool isInitOK = false;
55+
56+
// Initialise sub-class
57+
if (ProviderSpi::init(deviceConfig))
58+
{
59+
_globalBrightnessControlThreshold = static_cast<uint32_t>(std::min(
60+
std::lround(deviceConfig["globalBrightnessControlThreshold"].toDouble(HD108_MAX_THRESHOLD) * HD108_MAX_THRESHOLD),
61+
(long)HD108_MAX_THRESHOLD_2));
62+
_globalBrightnessControlMaxLevel = deviceConfig["globalBrightnessControlMaxLevel"].toInt(HD108_MAX_LEVEL);
63+
Info(_log, "[HD108] Using global brightness control with threshold of %d and max level of %d", _globalBrightnessControlThreshold, _globalBrightnessControlMaxLevel);
64+
65+
_ledBuffer.resize(0, 0x00);
66+
_ledBuffer.resize((_ledCount * 8) + 16, 0x00);
67+
68+
isInitOK = true;
69+
}
70+
return isInitOK;
71+
}
72+
73+
static inline uint16_t MSB_FIRST(uint16_t x, bool littleEndian)
74+
{
75+
if (littleEndian)
76+
return (x >> 8) | (x << 8);
77+
else
78+
return x;
79+
}
80+
81+
int LedDeviceHD108::write(const std::vector<ColorRgb>& ledValues)
82+
{
83+
int littleEndian = 1;
84+
85+
if (*(char*)&littleEndian != 1)
86+
littleEndian = 0;
87+
88+
89+
if (_ledCount != ledValues.size())
90+
{
91+
Warning(_log, "HD108 led's number has changed (old: %d, new: %d). Rebuilding buffer.", _ledCount, ledValues.size());
92+
_ledCount = static_cast<uint>(ledValues.size());
93+
_ledBuffer.resize(0, 0x00);
94+
_ledBuffer.resize((_ledCount * 8) + 16, 0x00);
95+
}
96+
97+
98+
int index = 8;
99+
uint16_t* data = reinterpret_cast<uint16_t*>(_ledBuffer.data());
100+
for (auto const& rgb : ledValues)
101+
{
102+
const int isLit = (rgb.red || rgb.green || rgb.blue);
103+
uint16_t red = rgb.red * 256u;
104+
uint16_t green = rgb.green * 256u;
105+
uint16_t blue = rgb.blue * 256u;
106+
uint16_t level = HD108_MAX_LEVEL_BIT;
107+
108+
for (int i = 0; i < 3 && isLit; i++)
109+
{
110+
level |= (_globalBrightnessControlMaxLevel & HD108_MAX_LEVEL) << (5 * i);
111+
}
112+
113+
if (_globalBrightnessControlThreshold < HD108_MAX_THRESHOLD_2)
114+
{
115+
red = (red * _globalBrightnessControlThreshold) / HD108_MAX_THRESHOLD_2;
116+
green = (green * _globalBrightnessControlThreshold) / HD108_MAX_THRESHOLD_2;
117+
blue = (blue * _globalBrightnessControlThreshold) / HD108_MAX_THRESHOLD_2;
118+
}
119+
120+
121+
data[index + 0] = MSB_FIRST(level, littleEndian);
122+
data[index + 1] = MSB_FIRST(red, littleEndian);
123+
data[index + 2] = MSB_FIRST(green, littleEndian);
124+
data[index + 3] = MSB_FIRST(blue, littleEndian);
125+
index += 4;
126+
}
127+
128+
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
129+
}

Diff for: sources/leddevice/dev_spi/LedDeviceHD108.h

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* LedDeviceHD108.h
2+
*
3+
* MIT License
4+
*
5+
* Copyright (c) 2023 awawa-dev
6+
*
7+
* Project homesite: https://github.com/awawa-dev/HyperHDR
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*/
27+
28+
#ifndef LEDEVICEHD108_H
29+
#define LEDEVICEHD108_H
30+
31+
// HyperHDR includes
32+
#include "ProviderSpi.h"
33+
34+
///
35+
/// Implementation of the LedDevice interface for writing to LedDeviceHD108 led device via SPI.
36+
///
37+
class LedDeviceHD108 : public ProviderSpi
38+
{
39+
public:
40+
explicit LedDeviceHD108(const QJsonObject& deviceConfig);
41+
42+
static LedDevice* construct(const QJsonObject& deviceConfig);
43+
44+
private:
45+
uint32_t _globalBrightnessControlThreshold;
46+
uint16_t _globalBrightnessControlMaxLevel;
47+
48+
bool init(const QJsonObject& deviceConfig) override;
49+
50+
int write(const std::vector<ColorRgb>& ledValues) override;
51+
};
52+
53+
#endif // LEDEVICEHD108_H

Diff for: sources/leddevice/schemas/schema-hd108.json

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"type":"object",
3+
"required":true,
4+
"properties":{
5+
"output": {
6+
"type": "string",
7+
"title":"edt_dev_spec_spipath_title",
8+
"default" : "/dev/spidev0.0",
9+
"required" : true,
10+
"propertyOrder" : 1
11+
},
12+
"rate": {
13+
"type": "integer",
14+
"format" : "stepper",
15+
"step" : 1000000,
16+
"title":"edt_dev_spec_baudrate_title",
17+
"default": 1000000,
18+
"minimum": 1000000,
19+
"required" : true,
20+
"propertyOrder" : 2
21+
},
22+
"invert": {
23+
"type": "boolean",
24+
"format": "checkbox",
25+
"title":"edt_dev_spec_invert_title",
26+
"default": false,
27+
"propertyOrder" : 3
28+
},
29+
"globalBrightnessControlMaxLevel": {
30+
"type": "integer",
31+
"format" : "stepper",
32+
"step" : 1,
33+
"title":"edt_dev_spec_globalBrightnessControlMaxLevel_title",
34+
"default": 31,
35+
"minimum": 1,
36+
"maximum": 31,
37+
"required" : true,
38+
"propertyOrder" : 4
39+
},
40+
"globalBrightnessControlThreshold": {
41+
"type": "number",
42+
"format" : "stepper",
43+
"title": "edt_conf_color_brightness_title",
44+
"default": 100.0,
45+
"minimum": 0,
46+
"maximum": 100.0,
47+
"step" : 0.25,
48+
"append" : "edt_append_percent",
49+
"required" : true,
50+
"propertyOrder" : 5
51+
}
52+
},
53+
"additionalProperties": true
54+
}

Diff for: www/js/light_source.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ $(document).ready(function()
880880
var yeelight_title = 'wiz_yeelight_title';
881881
changeWizard(data, yeelight_title, startWizardYeelight);
882882
}
883-
else if (["apa102", "apa104", "awa_spi", "lpd6803", "lpd8806", "p9813", "sk6812spi", "sk6822spi", "sk9822", "ws2801", "ws2812spi", "wled", "adalight", "atmo", "dmx", "karate", "sedu", "tpm2"].includes(ledType))
883+
else if (["apa102", "apa104", "awa_spi", "lpd6803", "lpd8806", "p9813", "sk6812spi", "sk6822spi", "sk9822", "ws2801", "ws2812spi", "wled", "adalight", "atmo", "dmx", "karate", "sedu", "tpm2", "hd108"].includes(ledType))
884884
{
885885
let selectorControl = $("<select id=\"deviceListInstances\" />");
886886
let targetControl = 'output';
@@ -918,7 +918,7 @@ $(document).ready(function()
918918

919919
// create led device selection
920920
var ledDevices = window.serverInfo.ledDevices.available;
921-
var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2812spi','awa_spi'];
921+
var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'sk9822', 'ws2812spi', 'awa_spi', 'hd108'];
922922
var devRPiPWM = ['ws281x'];
923923
var devRPiGPIO = ['piblaster'];
924924

0 commit comments

Comments
 (0)