Skip to content

Commit 4d78188

Browse files
authored
ESP32-S2 mini support (Adalight AWA protocol) (#452)
1 parent d327fea commit 4d78188

File tree

6 files changed

+146
-66
lines changed

6 files changed

+146
-66
lines changed

.github/workflows/image-builder-from-repo.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ jobs:
6363
echo 'set -x' >> start_chroot_script
6464
echo 'set -e' >> start_chroot_script
6565
echo 'source /common.sh' >> start_chroot_script
66-
echo 'type -p curl >/dev/null || sudo apt install curl -y' >> start_chroot_script
67-
echo 'curl -fsSL https://awawa-dev.github.io/hyperhdr.public.apt.gpg.key | sudo dd of=/usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
68-
echo '&& sudo chmod go+r /usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
69-
echo '&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hyperhdr.public.apt.gpg.key] https://awawa-dev.github.io $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hyperhdr.list > /dev/null \' >> start_chroot_script
70-
echo '&& sudo apt update \' >> start_chroot_script
71-
echo '&& sudo apt install hyperhdr -y' >> start_chroot_script
66+
echo 'type -p curl >/dev/null || apt install curl -y' >> start_chroot_script
67+
echo 'curl -fsSL https://awawa-dev.github.io/hyperhdr.public.apt.gpg.key | dd of=/usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
68+
echo '&& chmod go+r /usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
69+
echo '&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hyperhdr.public.apt.gpg.key] https://awawa-dev.github.io $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hyperhdr.list > /dev/null \' >> start_chroot_script
70+
echo '&& apt update \' >> start_chroot_script
71+
echo '&& apt install hyperhdr -y' >> start_chroot_script
7272
echo 'touch /boot/ssh' >> start_chroot_script
7373
echo "echo -n 'pi:' > /boot/userconf" >> start_chroot_script
7474
echo "echo 'raspberry' | openssl passwd -6 -stdin >> /boot/userconf" >> start_chroot_script
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* EspTools.h
2+
*
3+
* MIT License
4+
*
5+
* Copyright (c) 2022 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 ESPTOOLS_H
29+
#define ESPTOOLS_H
30+
31+
class EspTools
32+
{
33+
public:
34+
35+
static void goingSleep(QSerialPort& _rs232Port)
36+
{
37+
uint8_t comBuffer[] = { 0x41, 0x77, 0x41, 0x2a, 0xa2, 0x35, 0x68, 0x79, 0x70, 0x65, 0x72, 0x68, 0x64, 0x72 };
38+
_rs232Port.write((char*)comBuffer, sizeof(comBuffer));
39+
_rs232Port.flush();
40+
_rs232Port.clear();
41+
}
42+
43+
static void initializeEsp(QSerialPort& _rs232Port, QSerialPortInfo& serialPortInfo, Logger*& _log)
44+
{
45+
if (serialPortInfo.productIdentifier() == 0x80c2 && serialPortInfo.vendorIdentifier() == 0x303a)
46+
{
47+
Warning(_log, "Detected ESP32-S2 lolin mini type board. HyperHDR skips the reset. State: %i, %i",
48+
_rs232Port.isDataTerminalReady(), _rs232Port.isRequestToSend());
49+
50+
uint8_t comBuffer[] = { 0x41, 0x77, 0x41, 0x2a, 0xa2, 0x15, 0x68, 0x79, 0x70, 0x65, 0x72, 0x68, 0x64, 0x72 };
51+
_rs232Port.write((char*)comBuffer, sizeof(comBuffer));
52+
53+
_rs232Port.setDataTerminalReady(true);
54+
_rs232Port.setRequestToSend(true);
55+
_rs232Port.setRequestToSend(false);
56+
}
57+
else
58+
{
59+
// reset to defaults
60+
_rs232Port.setDataTerminalReady(true);
61+
_rs232Port.setRequestToSend(false);
62+
QThread::msleep(50);
63+
64+
// reset device
65+
_rs232Port.setDataTerminalReady(false);
66+
_rs232Port.setRequestToSend(true);
67+
QThread::msleep(100);
68+
69+
// resume device
70+
_rs232Port.setRequestToSend(false);
71+
QThread::msleep(100);
72+
}
73+
74+
// read the reset message, search for AWA tag
75+
auto start = InternalClock::now();
76+
77+
while (InternalClock::now() - start < 1000)
78+
{
79+
_rs232Port.waitForReadyRead(100);
80+
if (_rs232Port.bytesAvailable() > 16)
81+
{
82+
auto incoming = _rs232Port.readAll();
83+
for (int i = 0; i < incoming.length(); i++)
84+
if (!(incoming[i] == '\n' ||
85+
(incoming[i] >= ' ' && incoming[i] <= 'Z') ||
86+
(incoming[i] >= 'a' && incoming[i] <= 'z')))
87+
{
88+
incoming.replace(incoming[i], '*');
89+
}
90+
QString result = QString(incoming).remove('*').replace('\n', ' ').trimmed();
91+
if (result.indexOf("Awa driver", Qt::CaseInsensitive) >= 0)
92+
{
93+
Info(_log, "DETECTED DEVICE USING HYPERSERIALESP8266/HYPERSERIALESP32 FIRMWARE (%s) at %i msec", QSTRING_CSTR(result), int(InternalClock::now() - start));
94+
start = 0;
95+
break;
96+
}
97+
}
98+
99+
if (InternalClock::now() <= start)
100+
break;
101+
}
102+
103+
if (start != 0)
104+
Error(_log, "Could not detect HyperSerialEsp8266/HyperSerialESP32 device");
105+
}
106+
};
107+
108+
#endif

sources/leddevice/dev_serial/LedDeviceAdalight.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void LedDeviceAdalight::CreateHeader()
7272
{
7373
_ligthBerryAPA102Mode = false;
7474
totalLedCount -= 1;
75-
auto finalSize = (uint64_t)_headerSize + _ledRGBCount + ((_awa_mode) ? 7 : 0);
75+
auto finalSize = (uint64_t)_headerSize + _ledRGBCount + ((_awa_mode) ? 8 : 0);
7676
_ledBuffer.resize(finalSize, 0x00);
7777

7878
if (_awa_mode)
@@ -113,7 +113,7 @@ int LedDeviceAdalight::write(const std::vector<ColorRgb>& ledValues)
113113
}
114114
else
115115
{
116-
auto bufferLength = _headerSize + ledValues.size() * sizeof(ColorRgb) + ((_awa_mode) ? 7 : 0);
116+
auto bufferLength = _headerSize + ledValues.size() * sizeof(ColorRgb) + ((_awa_mode) ? 8 : 0);
117117

118118
if (bufferLength > _ledBuffer.size())
119119
{
@@ -131,14 +131,17 @@ int LedDeviceAdalight::write(const std::vector<ColorRgb>& ledValues)
131131
{
132132
whiteChannelExtension(writer);
133133

134-
uint16_t fletcher1 = 0, fletcher2 = 0;
134+
uint16_t fletcher1 = 0, fletcher2 = 0, fletcherExt = 0;
135+
uint8_t position = 0;
135136
while (hasher < writer)
136137
{
138+
fletcherExt = (fletcherExt + (*(hasher) ^ (position++))) % 255;
137139
fletcher1 = (fletcher1 + *(hasher++)) % 255;
138140
fletcher2 = (fletcher2 + fletcher1) % 255;
139141
}
140142
*(writer++) = (uint8_t)fletcher1;
141143
*(writer++) = (uint8_t)fletcher2;
144+
*(writer++) = (uint8_t)((fletcherExt != 0x41) ? fletcherExt : 0xaa);
142145
}
143146
bufferLength = writer - _ledBuffer.data();
144147

sources/leddevice/dev_serial/ProviderRs232.cpp

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <chrono>
1212
#include <utils/InternalClock.h>
1313

14+
#include "EspTools.h"
15+
1416
// Constants
1517
constexpr std::chrono::milliseconds WRITE_TIMEOUT{ 1000 }; // device write timeout in ms
1618
constexpr std::chrono::milliseconds OPEN_TIMEOUT{ 5000 }; // device open timeout in ms
@@ -83,17 +85,23 @@ int ProviderRs232::open()
8385
return retval;
8486
}
8587

86-
void ProviderRs232::waitForExitStats()
87-
{
88+
void ProviderRs232::waitForExitStats(bool force)
89+
{
8890
if (_rs232Port.isOpen())
8991
{
90-
if (_rs232Port.bytesAvailable() > 16)
92+
if (!force && _rs232Port.bytesAvailable() > 32)
9193
{
92-
auto incoming = QString(_rs232Port.readAll());
94+
auto check = _rs232Port.peek(256);
95+
if (check.lastIndexOf('\n') > 1)
96+
{
97+
auto incoming = QString(_rs232Port.readAll());
98+
force = true;
9399

94-
Info(_log, "Received: %s", QSTRING_CSTR(incoming));
100+
Info(_log, "Received: '%s' (%i)", QSTRING_CSTR(incoming), incoming.length());
101+
}
95102
}
96-
if (!_isDeviceReady)
103+
104+
if (!_isDeviceReady && force)
97105
{
98106
Debug(_log, "Close UART: %s", QSTRING_CSTR(_deviceName));
99107
_rs232Port.close();
@@ -118,9 +126,10 @@ int ProviderRs232::close()
118126

119127
if (_espHandshake)
120128
{
121-
// read the statistics on goodbye
122-
QTimer::singleShot(6000, this, &ProviderRs232::waitForExitStats);
123-
connect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::waitForExitStats);
129+
EspTools::goingSleep(_rs232Port);
130+
131+
QTimer::singleShot(6000, this, [this](){waitForExitStats(true); });
132+
connect(&_rs232Port, &QSerialPort::readyRead, this, [this]() {waitForExitStats(false); });
124133
}
125134
else
126135
{
@@ -196,50 +205,7 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms)
196205
{
197206
disconnect(&_rs232Port, &QSerialPort::readyRead, nullptr, nullptr);
198207

199-
// reset to defaults
200-
_rs232Port.setDataTerminalReady(true);
201-
_rs232Port.setRequestToSend(false);
202-
QThread::msleep(50);
203-
204-
// reset device
205-
_rs232Port.setDataTerminalReady(false);
206-
_rs232Port.setRequestToSend(true);
207-
QThread::msleep(100);
208-
209-
// resume device
210-
_rs232Port.setRequestToSend(false);
211-
QThread::msleep(100);
212-
213-
// read the reset message, search for AWA tag
214-
auto start = InternalClock::now();
215-
216-
while(InternalClock::now() - start < 1000)
217-
{
218-
_rs232Port.waitForReadyRead(100);
219-
if (_rs232Port.bytesAvailable() > 16)
220-
{
221-
auto incoming = _rs232Port.readAll();
222-
for (int i = 0; i < incoming.length(); i++)
223-
if (!(incoming[i] == '\n' ||
224-
(incoming[i] >= ' ' && incoming[i] <= 'Z') ||
225-
(incoming[i] >= 'a' && incoming[i] <= 'z')))
226-
{
227-
incoming.replace(incoming[i], '*');
228-
}
229-
QString result = QString(incoming).remove('*').replace('\n',' ').trimmed();
230-
if (result.indexOf("Awa driver",Qt::CaseInsensitive) >= 0)
231-
{
232-
Info(_log, "DETECTED DEVICE USING HYPERSERIALESP8266/HYPERSERIALESP32 FIRMWARE (%s) at %i msec", QSTRING_CSTR(result), int(InternalClock::now() - start));
233-
start = 0;
234-
break;
235-
}
236-
}
237-
if (InternalClock::now() <= start)
238-
break;
239-
}
240-
241-
if (start != 0)
242-
Error(_log, "Could not detect HyperSerialEsp8266/HyperSerialESP32 device");
208+
EspTools::initializeEsp(_rs232Port, serialPortInfo, _log);
243209
}
244210
}
245211
else

sources/leddevice/dev_serial/ProviderRs232.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ protected slots:
9898
void setInError(const QString& errorMsg) override;
9999

100100
public slots:
101-
void waitForExitStats();
101+
void waitForExitStats(bool force);
102102

103103
private:
104104

sources/leddevice/dev_spi/LedDeviceAWA_spi.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void LedDeviceAWA_spi::CreateHeader()
4646
{
4747
unsigned int totalLedCount = _ledCount - 1;
4848

49-
auto finalSize = (uint64_t)_headerSize + (_ledCount * 3) + 7;
49+
auto finalSize = (uint64_t)_headerSize + (_ledCount * 3) + 8;
5050
_ledBuffer.resize(finalSize, 0x00);
5151

5252
Debug(_log, "SPI driver with data integration check AWA protocol");
@@ -72,7 +72,7 @@ int LedDeviceAWA_spi::write(const std::vector<ColorRgb>& ledValues)
7272
CreateHeader();
7373
}
7474

75-
auto bufferLength = _headerSize + ledValues.size() * sizeof(ColorRgb) + 7;
75+
auto bufferLength = _headerSize + ledValues.size() * sizeof(ColorRgb) + 8;
7676

7777
if (bufferLength > _ledBuffer.size())
7878
{
@@ -89,14 +89,17 @@ int LedDeviceAWA_spi::write(const std::vector<ColorRgb>& ledValues)
8989

9090
whiteChannelExtension(writer);
9191

92-
uint16_t fletcher1 = 0, fletcher2 = 0;
92+
uint16_t fletcher1 = 0, fletcher2 = 0, fletcherExt = 0;
93+
uint8_t position = 0;
9394
while (hasher < writer)
9495
{
96+
fletcherExt = (fletcherExt + (*(hasher) ^ (position++))) % 255;
9597
fletcher1 = (fletcher1 + *(hasher++)) % 255;
9698
fletcher2 = (fletcher2 + fletcher1) % 255;
9799
}
98100
*(writer++) = (uint8_t)fletcher1;
99101
*(writer++) = (uint8_t)fletcher2;
102+
*(writer++) = (uint8_t)((fletcherExt != 0x41) ? fletcherExt : 0xaa);
100103
bufferLength = writer -_ledBuffer.data();
101104

102105
if (_spiType == "esp8266")

0 commit comments

Comments
 (0)