Skip to content

Commit

Permalink
ESP32-S2 mini support (Adalight AWA protocol) (#452)
Browse files Browse the repository at this point in the history
  • Loading branch information
awawa-dev authored Dec 12, 2022
1 parent d327fea commit 4d78188
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 66 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/image-builder-from-repo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ jobs:
echo 'set -x' >> start_chroot_script
echo 'set -e' >> start_chroot_script
echo 'source /common.sh' >> start_chroot_script
echo 'type -p curl >/dev/null || sudo apt install curl -y' >> start_chroot_script
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
echo '&& sudo chmod go+r /usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
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
echo '&& sudo apt update \' >> start_chroot_script
echo '&& sudo apt install hyperhdr -y' >> start_chroot_script
echo 'type -p curl >/dev/null || apt install curl -y' >> start_chroot_script
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
echo '&& chmod go+r /usr/share/keyrings/hyperhdr.public.apt.gpg.key \' >> start_chroot_script
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
echo '&& apt update \' >> start_chroot_script
echo '&& apt install hyperhdr -y' >> start_chroot_script
echo 'touch /boot/ssh' >> start_chroot_script
echo "echo -n 'pi:' > /boot/userconf" >> start_chroot_script
echo "echo 'raspberry' | openssl passwd -6 -stdin >> /boot/userconf" >> start_chroot_script
Expand Down
108 changes: 108 additions & 0 deletions sources/leddevice/dev_serial/EspTools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* EspTools.h
*
* MIT License
*
* Copyright (c) 2022 awawa-dev
*
* Project homesite: https://github.com/awawa-dev/HyperHDR
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef ESPTOOLS_H
#define ESPTOOLS_H

class EspTools
{
public:

static void goingSleep(QSerialPort& _rs232Port)
{
uint8_t comBuffer[] = { 0x41, 0x77, 0x41, 0x2a, 0xa2, 0x35, 0x68, 0x79, 0x70, 0x65, 0x72, 0x68, 0x64, 0x72 };
_rs232Port.write((char*)comBuffer, sizeof(comBuffer));
_rs232Port.flush();
_rs232Port.clear();
}

static void initializeEsp(QSerialPort& _rs232Port, QSerialPortInfo& serialPortInfo, Logger*& _log)
{
if (serialPortInfo.productIdentifier() == 0x80c2 && serialPortInfo.vendorIdentifier() == 0x303a)
{
Warning(_log, "Detected ESP32-S2 lolin mini type board. HyperHDR skips the reset. State: %i, %i",
_rs232Port.isDataTerminalReady(), _rs232Port.isRequestToSend());

uint8_t comBuffer[] = { 0x41, 0x77, 0x41, 0x2a, 0xa2, 0x15, 0x68, 0x79, 0x70, 0x65, 0x72, 0x68, 0x64, 0x72 };
_rs232Port.write((char*)comBuffer, sizeof(comBuffer));

_rs232Port.setDataTerminalReady(true);
_rs232Port.setRequestToSend(true);
_rs232Port.setRequestToSend(false);
}
else
{
// reset to defaults
_rs232Port.setDataTerminalReady(true);
_rs232Port.setRequestToSend(false);
QThread::msleep(50);

// reset device
_rs232Port.setDataTerminalReady(false);
_rs232Port.setRequestToSend(true);
QThread::msleep(100);

// resume device
_rs232Port.setRequestToSend(false);
QThread::msleep(100);
}

// read the reset message, search for AWA tag
auto start = InternalClock::now();

while (InternalClock::now() - start < 1000)
{
_rs232Port.waitForReadyRead(100);
if (_rs232Port.bytesAvailable() > 16)
{
auto incoming = _rs232Port.readAll();
for (int i = 0; i < incoming.length(); i++)
if (!(incoming[i] == '\n' ||
(incoming[i] >= ' ' && incoming[i] <= 'Z') ||
(incoming[i] >= 'a' && incoming[i] <= 'z')))
{
incoming.replace(incoming[i], '*');
}
QString result = QString(incoming).remove('*').replace('\n', ' ').trimmed();
if (result.indexOf("Awa driver", Qt::CaseInsensitive) >= 0)
{
Info(_log, "DETECTED DEVICE USING HYPERSERIALESP8266/HYPERSERIALESP32 FIRMWARE (%s) at %i msec", QSTRING_CSTR(result), int(InternalClock::now() - start));
start = 0;
break;
}
}

if (InternalClock::now() <= start)
break;
}

if (start != 0)
Error(_log, "Could not detect HyperSerialEsp8266/HyperSerialESP32 device");
}
};

#endif
9 changes: 6 additions & 3 deletions sources/leddevice/dev_serial/LedDeviceAdalight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void LedDeviceAdalight::CreateHeader()
{
_ligthBerryAPA102Mode = false;
totalLedCount -= 1;
auto finalSize = (uint64_t)_headerSize + _ledRGBCount + ((_awa_mode) ? 7 : 0);
auto finalSize = (uint64_t)_headerSize + _ledRGBCount + ((_awa_mode) ? 8 : 0);
_ledBuffer.resize(finalSize, 0x00);

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

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

uint16_t fletcher1 = 0, fletcher2 = 0;
uint16_t fletcher1 = 0, fletcher2 = 0, fletcherExt = 0;
uint8_t position = 0;
while (hasher < writer)
{
fletcherExt = (fletcherExt + (*(hasher) ^ (position++))) % 255;
fletcher1 = (fletcher1 + *(hasher++)) % 255;
fletcher2 = (fletcher2 + fletcher1) % 255;
}
*(writer++) = (uint8_t)fletcher1;
*(writer++) = (uint8_t)fletcher2;
*(writer++) = (uint8_t)((fletcherExt != 0x41) ? fletcherExt : 0xaa);
}
bufferLength = writer - _ledBuffer.data();

Expand Down
72 changes: 19 additions & 53 deletions sources/leddevice/dev_serial/ProviderRs232.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <chrono>
#include <utils/InternalClock.h>

#include "EspTools.h"

// Constants
constexpr std::chrono::milliseconds WRITE_TIMEOUT{ 1000 }; // device write timeout in ms
constexpr std::chrono::milliseconds OPEN_TIMEOUT{ 5000 }; // device open timeout in ms
Expand Down Expand Up @@ -83,17 +85,23 @@ int ProviderRs232::open()
return retval;
}

void ProviderRs232::waitForExitStats()
{
void ProviderRs232::waitForExitStats(bool force)
{
if (_rs232Port.isOpen())
{
if (_rs232Port.bytesAvailable() > 16)
if (!force && _rs232Port.bytesAvailable() > 32)
{
auto incoming = QString(_rs232Port.readAll());
auto check = _rs232Port.peek(256);
if (check.lastIndexOf('\n') > 1)
{
auto incoming = QString(_rs232Port.readAll());
force = true;

Info(_log, "Received: %s", QSTRING_CSTR(incoming));
Info(_log, "Received: '%s' (%i)", QSTRING_CSTR(incoming), incoming.length());
}
}
if (!_isDeviceReady)

if (!_isDeviceReady && force)
{
Debug(_log, "Close UART: %s", QSTRING_CSTR(_deviceName));
_rs232Port.close();
Expand All @@ -118,9 +126,10 @@ int ProviderRs232::close()

if (_espHandshake)
{
// read the statistics on goodbye
QTimer::singleShot(6000, this, &ProviderRs232::waitForExitStats);
connect(&_rs232Port, &QSerialPort::readyRead, this, &ProviderRs232::waitForExitStats);
EspTools::goingSleep(_rs232Port);

QTimer::singleShot(6000, this, [this](){waitForExitStats(true); });
connect(&_rs232Port, &QSerialPort::readyRead, this, [this]() {waitForExitStats(false); });
}
else
{
Expand Down Expand Up @@ -196,50 +205,7 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms)
{
disconnect(&_rs232Port, &QSerialPort::readyRead, nullptr, nullptr);

// reset to defaults
_rs232Port.setDataTerminalReady(true);
_rs232Port.setRequestToSend(false);
QThread::msleep(50);

// reset device
_rs232Port.setDataTerminalReady(false);
_rs232Port.setRequestToSend(true);
QThread::msleep(100);

// resume device
_rs232Port.setRequestToSend(false);
QThread::msleep(100);

// read the reset message, search for AWA tag
auto start = InternalClock::now();

while(InternalClock::now() - start < 1000)
{
_rs232Port.waitForReadyRead(100);
if (_rs232Port.bytesAvailable() > 16)
{
auto incoming = _rs232Port.readAll();
for (int i = 0; i < incoming.length(); i++)
if (!(incoming[i] == '\n' ||
(incoming[i] >= ' ' && incoming[i] <= 'Z') ||
(incoming[i] >= 'a' && incoming[i] <= 'z')))
{
incoming.replace(incoming[i], '*');
}
QString result = QString(incoming).remove('*').replace('\n',' ').trimmed();
if (result.indexOf("Awa driver",Qt::CaseInsensitive) >= 0)
{
Info(_log, "DETECTED DEVICE USING HYPERSERIALESP8266/HYPERSERIALESP32 FIRMWARE (%s) at %i msec", QSTRING_CSTR(result), int(InternalClock::now() - start));
start = 0;
break;
}
}
if (InternalClock::now() <= start)
break;
}

if (start != 0)
Error(_log, "Could not detect HyperSerialEsp8266/HyperSerialESP32 device");
EspTools::initializeEsp(_rs232Port, serialPortInfo, _log);
}
}
else
Expand Down
2 changes: 1 addition & 1 deletion sources/leddevice/dev_serial/ProviderRs232.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected slots:
void setInError(const QString& errorMsg) override;

public slots:
void waitForExitStats();
void waitForExitStats(bool force);

private:

Expand Down
9 changes: 6 additions & 3 deletions sources/leddevice/dev_spi/LedDeviceAWA_spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void LedDeviceAWA_spi::CreateHeader()
{
unsigned int totalLedCount = _ledCount - 1;

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

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

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

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

whiteChannelExtension(writer);

uint16_t fletcher1 = 0, fletcher2 = 0;
uint16_t fletcher1 = 0, fletcher2 = 0, fletcherExt = 0;
uint8_t position = 0;
while (hasher < writer)
{
fletcherExt = (fletcherExt + (*(hasher) ^ (position++))) % 255;
fletcher1 = (fletcher1 + *(hasher++)) % 255;
fletcher2 = (fletcher2 + fletcher1) % 255;
}
*(writer++) = (uint8_t)fletcher1;
*(writer++) = (uint8_t)fletcher2;
*(writer++) = (uint8_t)((fletcherExt != 0x41) ? fletcherExt : 0xaa);
bufferLength = writer -_ledBuffer.data();

if (_spiType == "esp8266")
Expand Down

0 comments on commit 4d78188

Please sign in to comment.