Skip to content

Commit

Permalink
Reduced duplicate code
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Dec 28, 2023
1 parent 2996311 commit 1c0ad4e
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 234 deletions.
10 changes: 5 additions & 5 deletions src/ZeDMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ void ZeDMD::ClearScreen()
}
else if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_WIFI_COMMAND::UDP_ClearScreen);
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::ClearScreen);
}
}

Expand All @@ -310,7 +310,7 @@ void ZeDMD::RenderGray2(uint8_t *pFrame)

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_WIFI_COMMAND::UDP_RGB24, m_pPlanes, bufferSize * 3, width, height);
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
Expand Down Expand Up @@ -345,7 +345,7 @@ void ZeDMD::RenderGray4(uint8_t *pFrame)

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_WIFI_COMMAND::UDP_RGB24, m_pPlanes, bufferSize * 3, width, height);
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
Expand Down Expand Up @@ -384,7 +384,7 @@ void ZeDMD::RenderColoredGray6(uint8_t *pFrame, uint8_t *pRotations)

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_WIFI_COMMAND::UDP_RGB24, m_pPlanes, bufferSize * 3, width, height);
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize * 3, width, height);
}
Expand Down Expand Up @@ -420,7 +420,7 @@ void ZeDMD::RenderRgb24(uint8_t *pFrame)

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_WIFI_COMMAND::UDP_RGB24, m_pPlanes, bufferSize, width, height);
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB24ZonesStream, m_pPlanes, bufferSize, width, height);
}
else if (m_hd || m_streaming)
{
Expand Down
25 changes: 20 additions & 5 deletions src/ZeDMDComm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void ZeDMDComm::Run()
LogMessage("ZeDMDComm run thread starting");
int8_t lastStreamId = -1;

while (m_serialPort.IsOpen())
while (IsConnected())
{
m_frameQueueMutex.lock();

Expand Down Expand Up @@ -81,7 +81,7 @@ void ZeDMDComm::Run()
delay = m_delayedFrameReady;
m_delayedFrameMutex.unlock();

if (delay && m_frameCounter > 2) {
if (delay && m_frameCounter > ZEDMD_COMM_FRAME_QUEUE_SIZE_MAX_DELAYED) {
while (m_frames.size() > 0)
{
m_frames.pop();
Expand Down Expand Up @@ -135,7 +135,7 @@ void ZeDMDComm::Run()

void ZeDMDComm::QueueCommand(char command, uint8_t *data, int size, int8_t streamId, bool delayed)
{
if (!m_serialPort.IsOpen())
if (!IsConnected())
{
return;
}
Expand Down Expand Up @@ -201,6 +201,16 @@ void ZeDMDComm::QueueCommand(char command, uint8_t *data, int size, uint16_t wid
uint16_t bufferSize = 0;
uint8_t idx = 0;
uint8_t zone[16 * 8 * 3] = { 0 };
uint16_t zonesBytesLimit = 0;
if (m_zonesBytesLimit) {
while (zonesBytesLimit < m_zonesBytesLimit)
{
zonesBytesLimit += m_zoneWidth * m_zoneHeight * 3 + 1;
}
}
else {
zonesBytesLimit = width * m_zoneHeight * 3 + 16;
}

if (++m_streamId > 64)
{
Expand Down Expand Up @@ -240,7 +250,7 @@ void ZeDMDComm::QueueCommand(char command, uint8_t *data, int size, uint16_t wid
memcpy(&buffer[bufferSize], zone, m_zoneWidth * m_zoneHeight * 3);
bufferSize += m_zoneWidth * m_zoneHeight * 3;

if (bufferSize >= (width * m_zoneHeight * 3 + 16))
if (bufferSize >= zonesBytesLimit)
{
QueueCommand(command, buffer, bufferSize, m_streamId, delayed);
bufferSize = 0;
Expand Down Expand Up @@ -330,7 +340,7 @@ bool ZeDMDComm::Connect()

void ZeDMDComm::Disconnect()
{
if (!m_serialPort.IsOpen())
if (!IsConnected())
return;

Reset();
Expand Down Expand Up @@ -425,6 +435,11 @@ bool ZeDMDComm::Connect(char *pDevice)
return false;
}

bool ZeDMDComm::IsConnected()
{
return m_serialPort.IsOpen();
}

void ZeDMDComm::Reset()
{
m_serialPort.ClearDTR();
Expand Down
18 changes: 12 additions & 6 deletions src/ZeDMDComm.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct ZeDMDFrame

#define ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT 10
#define ZEDMD_COMM_FRAME_QUEUE_SIZE_MAX 8
#define ZEDMD_COMM_FRAME_QUEUE_SIZE_MAX_DELAYED 2

#ifdef __ANDROID__
typedef void *(*ZeDMD_AndroidGetJNIEnvFunc)();
Expand All @@ -102,8 +103,9 @@ class ZeDMDComm
void IgnoreDevice(const char *ignore_device);
void SetDevice(const char *device);

bool Connect();
void Disconnect();
virtual bool Connect();
virtual void Disconnect();
virtual bool IsConnected();

void Run();
void QueueCommand(char command, uint8_t *buffer, int size, uint16_t width, uint16_t height);
Expand All @@ -115,20 +117,24 @@ class ZeDMDComm
uint16_t GetWidth();
uint16_t GetHeight();

protected:
virtual bool StreamBytes(ZeDMDFrame* pFrame);
virtual void Reset();

uint16_t m_zonesBytesLimit = 0;
uint8_t m_zoneWidth = 8;
uint8_t m_zoneHeight = 4;

private:
void LogMessage(const char *format, ...);

bool Connect(char *pName);
void Reset();
bool StreamBytes(ZeDMDFrame *pFrame);

ZeDMD_LogMessageCallback m_logMessageCallback = nullptr;
const void *m_logMessageUserData = nullptr;
uint64_t m_zoneHashes[128] = {0};
uint16_t m_width = 128;
uint16_t m_height = 32;
uint8_t m_zoneWidth = 8;
uint8_t m_zoneHeight = 4;
int8_t m_streamId = -1;
int8_t m_lastStreamId = -1;
uint8_t m_flowControlCounter = 0;
Expand Down
187 changes: 28 additions & 159 deletions src/ZeDMDWiFi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,6 @@
#include "miniz/miniz.h"
#include "komihash/komihash.h"

ZeDMDWiFi::ZeDMDWiFi()
{
m_pThread = NULL;
}

ZeDMDWiFi::~ZeDMDWiFi()
{
if (m_pThread)
{
m_pThread->join();

delete m_pThread;
}
}

void ZeDMDWiFi::SetLogMessageCallback(ZeDMD_LogMessageCallback callback, const void *userData)
{
m_logMessageCallback = callback;
m_logMessageUserData = userData;
}

void ZeDMDWiFi::LogMessage(const char *format, ...)
{
if (!m_logMessageCallback)
return;

va_list args;
va_start(args, format);
(*(m_logMessageCallback))(format, args, m_logMessageUserData);
va_end(args);
}

void ZeDMDWiFi::Run()
{
m_pThread = new std::thread([this]()
{
LogMessage("ZeDMDWiFi run thread starting");

while (true)
{
m_frameQueueMutex.lock();

if (m_frames.empty())
{
m_frameQueueMutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}

ZeDMDWiFiFrame frame = m_frames.front();
m_frames.pop();
m_frameQueueMutex.unlock();

StreamBytes(&frame);

if (frame.data)
{
free(frame.data);
}
}

LogMessage("ZeDMDWiFi run thread finished"); });
}

void ZeDMDWiFi::QueueCommand(char command, uint8_t *data, int size, uint16_t width, uint16_t height)
{
ZeDMDWiFiFrame frame = {0};
frame.command = command;
frame.size = size;
frame.width = width;
frame.height = height;

if (data && size > 0)
{
frame.data = (uint8_t *)malloc(size);
memcpy(frame.data, data, size);
}

m_frameQueueMutex.lock();
m_frames.push(frame);
m_frameQueueMutex.unlock();
}

void ZeDMDWiFi::QueueCommand(char command, uint8_t value)
{
QueueCommand(command, &value, 1, 0, 0);
}

void ZeDMDWiFi::QueueCommand(char command)
{
QueueCommand(command, NULL, 0, 0, 0);
}

bool ZeDMDWiFi::Connect(const char *ip, int port)
{
#if defined(_WIN32) || defined(_WIN64)
Expand All @@ -113,6 +20,7 @@ bool ZeDMDWiFi::Connect(const char *ip, int port)
m_wifiServer.sin_family = AF_INET;
m_wifiServer.sin_port = htons(port);
m_wifiServer.sin_addr.s_addr = inet_addr(ip);
m_connected = true;

return true;
}
Expand All @@ -126,20 +34,25 @@ void ZeDMDWiFi::Disconnect()
#endif
}

bool ZeDMDWiFi::IsConnected()
{
return m_connected;
}

void ZeDMDWiFi::Reset()
{
}

void ZeDMDWiFi::StreamBytes(ZeDMDWiFiFrame *pFrame)
bool ZeDMDWiFi::StreamBytes(ZeDMDFrame *pFrame)
{
// An UDP package should not exceed the MTU (WiFi rx_buffer in ESP32 is 1460 bytes).
// We send obe zones of 16 * 8 pixels:
// 128 pixels, 3 bytes RGB per pixel, 5 byte command header: 389 bytes
// And we additionally use compression.
// We send 4 zones of 16 * 8 pixels:
// 512 pixels, 3 bytes RGB per pixel, 4 bytes for zones index, 4 bytes command header: 1544 bytes
// As we additionally use compression, that should be safe.

if (pFrame->size < ZEDMD_WIFI_FRAME_SIZE_COMMAND_LIMIT)
if (pFrame->size < ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT)
{
uint8_t data[ZEDMD_WIFI_FRAME_SIZE_COMMAND_LIMIT + 4] = {0};
uint8_t data[ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT + 4] = {0};
data[0] = pFrame->command; // command
data[1] = 0; // not compressed
data[2] = (uint8_t)(pFrame->size >> 8 & 0xFF);
Expand All @@ -159,73 +72,29 @@ void ZeDMDWiFi::StreamBytes(ZeDMDWiFiFrame *pFrame)
#endif
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return;
return true;
}

uint8_t idx = 0;
for (uint16_t y = 0; y < pFrame->height; y += 8)
else
{
for (uint16_t x = 0; x < pFrame->width; x += 16)
{
uint8_t data[16 * 8 * 3 + 4] = {0};
data[0] = pFrame->command; // command

uint8_t zone[16 * 8 * 3] = {0};
for (uint8_t z = 0; z < 8; z++)
{
memcpy(&zone[z * 16 * 3], &pFrame->data[((y + z) * pFrame->width + x) * 3], 16 * 3);
}

uint64_t hash = komihash(zone, 16 * 8 * 3, 0);
if (hash != m_zoneHashes[idx])
{
m_zoneHashes[idx] = hash;

if (m_compression)
{
data[1] = (uint8_t)(128 | idx); // compressed + zone index

mz_ulong compressedSize = 16 * 8 * 3;
int status = mz_compress(&data[4], &compressedSize, zone, 16 * 8 * 3);
data[2] = (uint8_t)(compressedSize >> 8 & 0xFF);
data[3] = (uint8_t)(compressedSize & 0xFF);

if (status == MZ_OK)
{
#if defined(_WIN32) || defined(_WIN64)
sendto(m_wifiSocket, (const char *)data, compressedSize + 4, 0, (struct sockaddr *)&m_wifiServer, sizeof(m_wifiServer));
#else
sendto(m_wifiSocket, data, compressedSize + 4, 0, (struct sockaddr *)&m_wifiServer, sizeof(m_wifiServer));
#endif
}
}
else
{
data[1] = (uint8_t)idx; // not compressed + zone index
uint8_t data[ZEDMD_WIFI_ZONES_BYTES_LIMIT] = { 0 };
data[0] = pFrame->command; // command
data[1] = (uint8_t)(128 | (pFrame->size / (m_zoneWidth * m_zoneHeight * 3 + 1))); // compressed + zone index

int size = 16 * 8 * 3;
data[2] = (uint8_t)(size >> 8 & 0xFF);
data[3] = (uint8_t)(size & 0xFF);
memcpy(&data[4], zone, size);
mz_ulong compressedSize = pFrame->size;
int status = mz_compress(&data[4], &compressedSize, pFrame->data, pFrame->size);
data[2] = (uint8_t)(compressedSize >> 8 & 0xFF);
data[3] = (uint8_t)(compressedSize & 0xFF);

if (status == MZ_OK)
{
#if defined(_WIN32) || defined(_WIN64)
sendto(m_wifiSocket, (const char *)data, size + 4, 0, (struct sockaddr *)&m_wifiServer, sizeof(m_wifiServer));
sendto(m_wifiSocket, (const char*)data, compressedSize + 4, 0, (struct sockaddr*)&m_wifiServer, sizeof(m_wifiServer));
#else
sendto(m_wifiSocket, data, size + 4, 0, (struct sockaddr *)&m_wifiServer, sizeof(m_wifiServer));
sendto(m_wifiSocket, data, compressedSize + 4, 0, (struct sockaddr*)&m_wifiServer, sizeof(m_wifiServer));
#endif
}
}
idx++;
}
return true;
}
}
}

uint16_t ZeDMDWiFi::GetWidth()
{
return m_width;
return false;
}

uint16_t ZeDMDWiFi::GetHeight()
{
return m_height;
}
Loading

0 comments on commit 1c0ad4e

Please sign in to comment.