Skip to content

Commit

Permalink
fixed size data streams
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Jan 23, 2025
1 parent 15ba0f9 commit bb7cd51
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 77 deletions.
113 changes: 68 additions & 45 deletions src/ZeDMDComm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

ZeDMDComm::ZeDMDComm()
{
m_keepAliveInterval = std::chrono::milliseconds(ZEDMD_COMM_KEEP_ALIVE_INTERVAL);

m_stopFlag.store(false, std::memory_order_release);
m_fullFrameFlag.store(false, std::memory_order_release);

Expand Down Expand Up @@ -52,6 +54,8 @@ void ZeDMDComm::Log(const char* format, ...)

void ZeDMDComm::Run()
{
m_lastKeepAlive = std::chrono::steady_clock::now();

m_pThread = new std::thread(
[this]()
{
Expand Down Expand Up @@ -595,78 +599,77 @@ void ZeDMDComm::SoftReset()

bool ZeDMDComm::StreamBytes(ZeDMDFrame* pFrame)
{
#if !( \
(defined(__APPLE__) && ((defined(TARGET_OS_IOS) && TARGET_OS_IOS) || (defined(TARGET_OS_TV) && TARGET_OS_TV))) || \
defined(__ANDROID__))
m_lastKeepAlive = std::chrono::steady_clock::now();

uint8_t* pData;
uint16_t size;
static uint8_t payload[36864] = {0};
uint16_t pos = 0;

for (auto it = pFrame->data.rbegin(); it != pFrame->data.rend(); ++it)
{
ZeDMDFrameData frameData = *it;

if (pFrame->command != ZEDMD_COMM_COMMAND::RGB565ZonesStream)
{
size = CTRL_CHARS_HEADER_SIZE + 3 + frameData.size;
pData = (uint8_t*)malloc(size);
memcpy(pData, CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pData[CTRL_CHARS_HEADER_SIZE] = pFrame->command;
pData[CTRL_CHARS_HEADER_SIZE + 1] = (uint8_t)(frameData.size >> 8 & 0xFF);
pData[CTRL_CHARS_HEADER_SIZE + 2] = (uint8_t)(frameData.size & 0xFF);
memcpy(&payload[pos], CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pos += CTRL_CHARS_HEADER_SIZE;
payload[pos++] = pFrame->command;
payload[pos++] = (uint8_t)(frameData.size >> 8 & 0xFF);
payload[pos++] = (uint8_t)(frameData.size & 0xFF);
payload[pos++] = 0;
if (frameData.size > 0)
{
memcpy(pData + CTRL_CHARS_HEADER_SIZE + 1, frameData.data, frameData.size);
memcpy(&payload[pos], frameData.data, frameData.size);
pos += frameData.size;
}
}
else
{
mz_ulong compressedSize = mz_compressBound(frameData.size);
pData = (uint8_t*)malloc(CTRL_CHARS_HEADER_SIZE + 3 + compressedSize);
memcpy(pData, CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pData[CTRL_CHARS_HEADER_SIZE] = pFrame->command;
int status = mz_compress(pData + CTRL_CHARS_HEADER_SIZE + 3, &compressedSize, frameData.data, frameData.size);
if (status != MZ_OK)
memcpy(&payload[pos], CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pos += CTRL_CHARS_HEADER_SIZE;
payload[pos++] = pFrame->command;
int status = mz_compress(&payload[pos + 3], &compressedSize, frameData.data, frameData.size);
if (status != MZ_OK || compressedSize > frameData.size || 0 >= compressedSize)
{
Log("Compression error: %d", status);
free(pData);
return false;
if (status != MZ_OK)
{
Log("Compression error. Status: %d, Frame Size: %d, Compressed Size: %d", status, frameData.size,
compressedSize);
}
payload[pos++] = (uint8_t)(frameData.size >> 8 & 0xFF);
payload[pos++] = (uint8_t)(frameData.size & 0xFF);
payload[pos++] = 0;
if (frameData.size > 0)
{
memcpy(&payload[pos], frameData.data, frameData.size);
pos += frameData.size;
}
}
size = CTRL_CHARS_HEADER_SIZE + 3 + compressedSize;
pData[CTRL_CHARS_HEADER_SIZE + 1] = (uint8_t)(compressedSize >> 8 & 0xFF);
pData[CTRL_CHARS_HEADER_SIZE + 2] = (uint8_t)(compressedSize & 0xFF);
if ((0 == pData[CTRL_CHARS_HEADER_SIZE + 1] && 0 == pData[CTRL_CHARS_HEADER_SIZE + 2]) ||
compressedSize > (frameData.size + 32))
else
{
Log("Compression error");
free(pData);
return false;
payload[pos++] = (uint8_t)(compressedSize >> 8 & 0xFF);
payload[pos++] = (uint8_t)(compressedSize & 0xFF);
payload[pos++] = 1;
pos += compressedSize;
}
}

bool success = SendChunks(pData, size);
free(pData);
if (!success) return false;
}

if (m_s3 && pFrame->command == ZEDMD_COMM_COMMAND::RGB565ZonesStream)
{
size = CTRL_CHARS_HEADER_SIZE + 3;
pData = (uint8_t*)malloc(size);
memcpy(pData, CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pData[CTRL_CHARS_HEADER_SIZE] = ZEDMD_COMM_COMMAND::RenderRGB565Frame;
pData[CTRL_CHARS_HEADER_SIZE + 1] = 0;
pData[CTRL_CHARS_HEADER_SIZE + 2] = 0;

bool success = SendChunks(pData, size);
free(pData);
if (!success) return false;
memcpy(&payload[pos], CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pos += CTRL_CHARS_HEADER_SIZE;
payload[pos++] = ZEDMD_COMM_COMMAND::RenderRGB565Frame;
payload[pos++] = 0;
payload[pos++] = 0;
payload[pos++] = 0;
}

if (!SendChunks(payload, pos)) return false;

m_lastKeepAlive = std::chrono::steady_clock::now();

return true;
#else
return false;
#endif
}

bool ZeDMDComm::SendChunks(uint8_t* pData, uint16_t size)
Expand Down Expand Up @@ -695,6 +698,7 @@ bool ZeDMDComm::SendChunks(uint8_t* pData, uint16_t size)
}

sent += status;
ack[0] = 0;
status = sp_blocking_read(m_pSerialPort, ack, sizeof(ack), ZEDMD_COMM_CDC_READ_TIMEOUT);
if (ack[0] != 'A')
{
Expand All @@ -709,6 +713,25 @@ bool ZeDMDComm::SendChunks(uint8_t* pData, uint16_t size)
return false;
}

void ZeDMDComm::KeepAlive()
{
auto now = std::chrono::steady_clock::now();
if (now - m_lastKeepAlive > m_keepAliveInterval)
{
m_lastKeepAlive = now;

uint16_t size = CTRL_CHARS_HEADER_SIZE + 4;
uint8_t* pData = (uint8_t*)malloc(size);
memcpy(pData, CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pData[CTRL_CHARS_HEADER_SIZE] = ZEDMD_COMM_COMMAND::KeepAlive;
pData[CTRL_CHARS_HEADER_SIZE + 1] = 0;
pData[CTRL_CHARS_HEADER_SIZE + 2] = 0;
pData[CTRL_CHARS_HEADER_SIZE + 3] = 0;
SendChunks(pData, size);
free(pData);
}
}

uint16_t const ZeDMDComm::GetWidth() { return m_width; }

uint16_t const ZeDMDComm::GetHeight() { return m_height; }
Expand Down
9 changes: 6 additions & 3 deletions src/ZeDMDComm.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@

#define ZEDMD_COMM_SERIAL_READ_TIMEOUT 16
#define ZEDMD_COMM_SERIAL_WRITE_TIMEOUT 8
#define ZEDMD_COMM_NUM_TIMEOUTS_TO_WAIT_FOR_ACKNOWLEDGE 3

#define ZEDMD_COMM_CDC_READ_TIMEOUT 16
#define ZEDMD_COMM_CDC_WRITE_TIMEOUT 16
#define ZEDMD_COMM_CDC_WRITE_TIMEOUT 8

#define ZEDMD_COMM_KEEP_ALIVE_INTERVAL 3000

#define ZEDMD_COMM_FRAME_QUEUE_SIZE_MAX 8

Expand Down Expand Up @@ -210,7 +211,6 @@ class ZeDMDComm

protected:
virtual bool SendChunks(uint8_t* pData, uint16_t size);
virtual bool KeepAlive() { return false; }
virtual void Reset();
void Log(const char* format, ...);
void ClearFrames();
Expand All @@ -224,11 +224,13 @@ class ZeDMDComm
uint8_t m_zoneHeight = 4;
std::atomic<bool> m_stopFlag;
std::atomic<bool> m_fullFrameFlag;
std::chrono::milliseconds m_keepAliveInterval;

private:
bool Connect(char* pName);
bool Handshake(char* pDevice);
bool StreamBytes(ZeDMDFrame* pFrame);
void KeepAlive();

ZeDMD_LogCallback m_logCallback = nullptr;
const void* m_logUserData = nullptr;
Expand All @@ -251,4 +253,5 @@ class ZeDMDComm
std::mutex m_delayedFrameMutex;
bool m_delayedFrameReady = false;
uint16_t m_writeAtOnce = ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE;
std::chrono::steady_clock::time_point m_lastKeepAlive;
};
26 changes: 0 additions & 26 deletions src/ZeDMDWiFi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,32 +305,6 @@ bool ZeDMDWiFi::IsConnected() { return m_connected; }

void ZeDMDWiFi::Reset() {}

bool ZeDMDWiFi::KeepAlive()
{
static auto lastRun = std::chrono::steady_clock::now();
const auto minInterval = std::chrono::milliseconds(100);

auto now = std::chrono::steady_clock::now();
if (now - lastRun < minInterval)
{
// Skip this call
return true;
}

lastRun = now;

uint16_t size = CTRL_CHARS_HEADER_SIZE + 3;
uint8_t* pData = (uint8_t*)malloc(size);
memcpy(pData, CTRL_CHARS_HEADER, CTRL_CHARS_HEADER_SIZE);
pData[CTRL_CHARS_HEADER_SIZE] = ZEDMD_COMM_COMMAND::KeepAlive;
pData[CTRL_CHARS_HEADER_SIZE + 1] = 0;
pData[CTRL_CHARS_HEADER_SIZE + 2] = 0;
SendChunks(pData, size);
free(pData);

return true;
}

bool ZeDMDWiFi::SendChunks(uint8_t* pData, uint16_t size)
{
if (m_tcpConnector->write_n(pData, size) < 0)
Expand Down
5 changes: 3 additions & 2 deletions src/ZeDMDWiFi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
#endif
#include "sockpp/tcp_connector.h"

#define ZEDMD_WIFI_KEEP_ALIVE_INTERVAL 100

class ZeDMDWiFi : public ZeDMDComm
{
public:
ZeDMDWiFi() : ZeDMDComm() {}
ZeDMDWiFi() : ZeDMDComm() { m_keepAliveInterval = std::chrono::milliseconds(ZEDMD_WIFI_KEEP_ALIVE_INTERVAL); }

virtual bool Connect(const char* name_or_ip);
virtual void Disconnect();
Expand All @@ -23,7 +25,6 @@ class ZeDMDWiFi : public ZeDMDComm
protected:
bool DoConnect(const char* ip);
virtual bool SendChunks(uint8_t* pData, uint16_t size);
virtual bool KeepAlive();
virtual void Reset();
bool openTcpConnection(int sock, sockaddr_in server, int16_t timeout);
bool SendGetRequest(const std::string& path);
Expand Down
7 changes: 6 additions & 1 deletion src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ int main(int argc, const char* argv[])

if (fileptr == NULL)
{
printf("Failed to open file, make sure to copy the test folder with the RAW files!");
printf("Failed to open file, make sure to copy the test folder with the RAW files!\n");
break;
}

Expand All @@ -100,6 +100,11 @@ int main(int argc, const char* argv[])
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}

printf("Test KeepAlive\n");
pZeDMD->EnableDebug();
std::this_thread::sleep_for(std::chrono::seconds(10));
pZeDMD->DisableDebug();

if (width == 256)
{
// test RGB565 upscaling
Expand Down

0 comments on commit bb7cd51

Please sign in to comment.