Skip to content

Commit

Permalink
new data transfer protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Dec 18, 2024
1 parent d876b37 commit 03bc704
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 135 deletions.
104 changes: 28 additions & 76 deletions src/ZeDMDComm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ bool ZeDMDComm::FillDelayed()
size = m_frames.size();
delayed = m_delayedFrameReady || (size >= ZEDMD_COMM_FRAME_QUEUE_SIZE_MAX);
m_frameQueueMutex.unlock();
// if (delayed) Log("ZeDMD, next frame will be delayed");
if (delayed) Log("ZeDMD, next frame will be delayed");
return delayed;
}

Expand Down Expand Up @@ -504,24 +504,15 @@ bool ZeDMDComm::Connect(char* pDevice)

if (sp_blocking_read(m_pSerialPort, data, 1, ZEDMD_COMM_SERIAL_READ_TIMEOUT) && data[0] == 'R')
{
data[0] = ZEDMD_COMM_COMMAND::Chunk;
data[1] = (m_s3 ? ZEDMD_S3_COMM_MAX_SERIAL_WRITE_AT_ONCE : ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE) / 32;
sp_nonblocking_write(m_pSerialPort, (void*)CTRL_CHARS_HEADER, 6);
sp_blocking_write(m_pSerialPort, (void*)data, 2, ZEDMD_COMM_SERIAL_WRITE_TIMEOUT);
std::this_thread::sleep_for(std::chrono::milliseconds(4));

if (sp_blocking_read(m_pSerialPort, data, 1, ZEDMD_COMM_SERIAL_READ_TIMEOUT) && data[0] == 'A')
{
// Store the device name for reconnects.
SetDevice(pDevice);
m_noReadySignalCounter = 0;
m_flowControlCounter = 1;
if (m_cdc) m_zonesBytesLimit = m_width * m_height * 3 + 128;
// Store the device name for reconnects.
SetDevice(pDevice);
m_noReadySignalCounter = 0;
m_flowControlCounter = 1;
if (m_cdc) m_zonesBytesLimit = m_width * m_height * 3 + 128;

Log("ZeDMD found: %sdevice=%s, width=%d, height=%d", m_s3 ? "S3 " : "", pDevice, m_width, m_height);
Log("ZeDMD found: %sdevice=%s, width=%d, height=%d", m_s3 ? "S3 " : "", pDevice, m_width, m_height);

return true;
}
return true;
}
}
}
Expand Down Expand Up @@ -635,77 +626,38 @@ bool ZeDMDComm::StreamBytes(ZeDMDFrame* pFrame)
int8_t status;
int32_t bytes_waiting;

do
{
status = sp_blocking_read(m_pSerialPort, &flowControlCounter, 1, ZEDMD_COMM_SERIAL_READ_TIMEOUT);
bytes_waiting = sp_input_waiting(m_pSerialPort);
// Log("%d %d %d", status, bytes_waiting, flowControlCounter);
} while ((bytes_waiting > 0 || (bytes_waiting == 0 && status != 1) ||
(flowControlCounter == 'A' || flowControlCounter == 'E')) &&
!m_stopFlag.load(std::memory_order_relaxed));
// Log("next stream");

bool success = false;

if (!m_stopFlag)
{
if (flowControlCounter == m_flowControlCounter)
int position = 0;
success = true;
m_noReadySignalCounter = 0;
const uint16_t writeAtOnce = m_s3 ? ZEDMD_S3_COMM_MAX_SERIAL_WRITE_AT_ONCE : ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE;

while (position < size && success)
{
int position = 0;
success = true;
m_noReadySignalCounter = 0;
const uint16_t writeAtOnce =
m_s3 ? ZEDMD_S3_COMM_MAX_SERIAL_WRITE_AT_ONCE : ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE;
sp_nonblocking_write(m_pSerialPort, &pData[position],
((size - position) < writeAtOnce) ? (size - position) : writeAtOnce);

while (position < size && success)
{
sp_nonblocking_write(m_pSerialPort, &pData[position],
((size - position) < writeAtOnce) ? (size - position) : writeAtOnce);
position += writeAtOnce;
}

uint8_t response = 255;
do
{
status = sp_blocking_read(m_pSerialPort, &response, 1, ZEDMD_COMM_SERIAL_READ_TIMEOUT);
// It could be that we got one more flowcontrol counter on the line (race condition).
} while ((status != 1 ||
(status == 1 && ((response != 'A' && response != 'E') || response == m_flowControlCounter))) &&
!m_stopFlag.load(std::memory_order_relaxed));
free(pData);

if (m_stopFlag)
{
success = false;
}
else if (response == 'A')
{
position += writeAtOnce;
}
else
{
success = false;
Log("Write bytes failure: response=%d", response);
}
}
uint8_t response = 255;
do
{
status = sp_blocking_read(m_pSerialPort, &response, 1, ZEDMD_COMM_SERIAL_READ_TIMEOUT);
} while ((status != 1 || (status == 1 && response != 'A' && response != 'E')) &&
!m_stopFlag.load(std::memory_order_relaxed));

if (++m_flowControlCounter > 32)
{
m_flowControlCounter = 1;
}
}
else
if (response != 'A')
{
Log("No Ready Signal, counter is %d", ++m_noReadySignalCounter);
if (m_noReadySignalCounter > ZEDMD_COMM_NO_READY_SIGNAL_MAX)
{
Log("Too many missing Ready Signals, try to reconnect ...");
Disconnect();
Connect();
}
Log("Write bytes failure: response=%d", response);
return false;
}
}

free(pData);

if (!success) return false;
}

return true;
Expand Down
12 changes: 3 additions & 9 deletions src/ZeDMDComm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#if defined(_WIN32) || defined(_WIN64)
#define ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE 1888
#else
#define ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE 992
#define ZEDMD_COMM_MAX_SERIAL_WRITE_AT_ONCE 4096
#endif

#define ZEDMD_S3_COMM_BAUD_RATE 2000000
Expand All @@ -51,18 +51,13 @@ typedef enum
{
FrameSize = 0x02,
Handshake = 0x0c,
Chunk = 0x0d,
Compression = 0x0e,
EnableCompression = 0x0e,
DisableCompression = 0x0f,
LEDTest = 0x10,
EnableUpscaling = 0x15,
DisableUpscaling = 0x14,
Brightness = 0x16,
RGBOrder = 0x17,
GetBrightness = 0x18,
GetRGBOrder = 0x19,
EnableFlowControlV2 = 0x1a,
SetWiFiSSID = 0x1b,
SetWiFiPassword = 0x1c,
SetWiFiPort = 0x1d,
Expand All @@ -71,7 +66,6 @@ typedef enum
GetVersionBytes = 0x20,
GetResolution = 0x21,

RGB24ZonesStream = 0x04,
RGB565ZonesStream = 0x05,
ClearScreen = 0x0a,

Expand Down Expand Up @@ -188,8 +182,8 @@ typedef void(ZEDMDCALLBACK* ZeDMD_LogCallback)(const char* format, va_list args,
class ZeDMDComm
{
public:
static const int CTRL_CHARS_HEADER_SIZE = 6;
static constexpr uint8_t CTRL_CHARS_HEADER[] = {0x5a, 0x65, 0x64, 0x72, 0x75, 0x6d};
static const int CTRL_CHARS_HEADER_SIZE = 5;
static constexpr uint8_t CTRL_CHARS_HEADER[] = {'Z', 'e', 'D', 'M', 'D'};

public:
ZeDMDComm();
Expand Down
31 changes: 13 additions & 18 deletions src/ZeDMDWiFi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,55 +245,50 @@ bool ZeDMDWiFi::StreamBytes(ZeDMDFrame* pFrame)

if (frameData.size < ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT && pFrame->command != 5)
{
uint8_t data[ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT + 4] = {0};
uint8_t data[ZEDMD_COMM_FRAME_SIZE_COMMAND_LIMIT + 1] = {0};
data[0] = pFrame->command; // command
data[1] = 0; // not compressed
data[2] = (uint8_t)(frameData.size >> 8 & 0xFF);
data[3] = (uint8_t)(frameData.size & 0xFF);
if (frameData.size > 0)
{
memcpy(&data[4], frameData.data, frameData.size);
memcpy(&data[1], frameData.data, frameData.size);
}

#if defined(_WIN32) || defined(_WIN64)
sendto(m_udpSocket, (const char*)data, frameData.size + 4, 0, (struct sockaddr*)&m_udpServer,
sizeof(m_udpServer));
#else
sendto(m_udpSocket, data, frameData.size + 4, 0, (struct sockaddr*)&m_udpServer, sizeof(m_udpServer));
sendto(m_udpSocket, data, frameData.size + 1, 0, (struct sockaddr*)&m_udpServer, sizeof(m_udpServer));
#endif
continue;
}
else
{
uint8_t data[ZEDMD_WIFI_ZONES_BYTES_LIMIT] = {0};
data[0] = pFrame->command; // command
// In case of a mostly black screen we can get 128 zones. That is handled in ZeDMD firmware.
data[1] = (uint8_t)(128 | frameData.numZones); // compressed + num zones

mz_ulong compressedSize = mz_compressBound(frameData.size);
int status = mz_compress(&data[4], &compressedSize, frameData.data, frameData.size);
mz_ulong compressedSize = mz_compressBound(ZEDMD_WIFI_MTU - 1);
int status = mz_compress(&data[1], &compressedSize, frameData.data, frameData.size);

if (compressedSize > ZEDMD_WIFI_MTU)
if (compressedSize > (ZEDMD_WIFI_MTU - 1))
{
Log("ZeDMD Wifi error, compressed size of %d exceeds the MTU payload of %d", compressedSize, ZEDMD_WIFI_MTU);
return false;
}
data[2] = (uint8_t)(compressedSize >> 8 & 0xFF);
data[3] = (uint8_t)(compressedSize & 0xFF);

if (status == MZ_OK)
{
#if defined(_WIN32) || defined(_WIN64)
sendto(m_udpSocket, (const char*)data, compressedSize + 4, 0, (struct sockaddr*)&m_udpServer,
sizeof(m_udpServer));
#else
sendto(m_udpSocket, data, compressedSize + 4, 0, (struct sockaddr*)&m_udpServer, sizeof(m_udpServer));
sendto(m_udpSocket, data, compressedSize + 1, 0, (struct sockaddr*)&m_udpServer, sizeof(m_udpServer));
#endif
continue;
}

Log("ZeDMD Wifi compression error");

return false;
else
{
Log("ZeDMD Wifi compression error");
return false;
}
}
}

Expand Down
43 changes: 11 additions & 32 deletions src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,22 @@ int main(int argc, const char* argv[])

if (pZeDMD->Open())
{
pZeDMD->EnableDebug();
//pZeDMD->EnableDebug();

uint16_t width = pZeDMD->GetWidth();
uint16_t height = pZeDMD->GetHeight();

pZeDMD->SetFrameSize(128, 32);
pZeDMD->EnableUpscaling();
//pZeDMD->EnableUpscaling();

uint8_t* pImage24 = CreateImageRGB24();
uint16_t sleep = 200;
uint16_t sleep = 10;

pZeDMD->EnablePreUpscaling();

for (int i = 0; i < 3; i++)
for (int i = 0; i < 10; i++)
{
printf("Render loop: %d\n", i);

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
pZeDMD->ClearScreen();

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
Expand All @@ -72,19 +62,9 @@ int main(int argc, const char* argv[])

pZeDMD->DisablePreUpscaling();

for (int i = 0; i < 3; i++)
for (int i = 0; i < 10; i++)
{
printf("Render loop: %d\n", i);

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
pZeDMD->ClearScreen();

printf("RGB24 Streaming\n");
pZeDMD->RenderRgb888(pImage24);
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
Expand Down Expand Up @@ -117,7 +97,6 @@ int main(int argc, const char* argv[])

memcpy(rgb565, buffer, size);
pZeDMD->RenderRgb565(rgb565);
std::this_thread::sleep_for(std::chrono::milliseconds(pZeDMD->IsS3() ? 50 : (width == 256 ? 240 : 80)));
}

if (width == 256)
Expand All @@ -136,7 +115,7 @@ int main(int argc, const char* argv[])

memcpy(rgb565, buffer, size);
pZeDMD->RenderRgb565(rgb565);
std::this_thread::sleep_for(std::chrono::milliseconds(pZeDMD->IsS3() ? 50 : 120));
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}

// test RGB565 centering
Expand All @@ -152,7 +131,7 @@ int main(int argc, const char* argv[])

memcpy(rgb565, buffer, size);
pZeDMD->RenderRgb565(rgb565);
std::this_thread::sleep_for(std::chrono::milliseconds(pZeDMD->IsS3() ? 50 : 80));
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}

pZeDMD->SetFrameSize(width, height);
Expand All @@ -173,14 +152,14 @@ int main(int argc, const char* argv[])
fclose(fileptr);

pZeDMD->RenderRgb888(rgb888);
std::this_thread::sleep_for(std::chrono::milliseconds(pZeDMD->IsS3() ? 50 : (width == 256 ? 420 : 140)));
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}

free(rgb888);

pZeDMD->LedTest();
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
// pZeDMD->LedTest();
// std::this_thread::sleep_for(std::chrono::milliseconds(5000));

pZeDMD->Close();
// pZeDMD->Close();
}
}

0 comments on commit 03bc704

Please sign in to comment.