Skip to content

Commit

Permalink
fixed HD memory issues
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Dec 19, 2024
1 parent 03bc704 commit f0a22e1
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 108 deletions.
75 changes: 25 additions & 50 deletions src/ZeDMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ ZeDMD::ZeDMD()

m_pFrameBuffer = nullptr;
m_pScaledFrameBuffer = nullptr;
m_pCommandBuffer = nullptr;
m_pRgb565Buffer = nullptr;

m_pZeDMDComm = new ZeDMDComm();
Expand All @@ -38,11 +37,6 @@ ZeDMD::~ZeDMD()
delete m_pScaledFrameBuffer;
}

if (m_pCommandBuffer)
{
delete m_pCommandBuffer;
}

if (m_pRgb565Buffer)
{
delete m_pRgb565Buffer;
Expand Down Expand Up @@ -264,11 +258,13 @@ bool ZeDMD::OpenWiFi(const char* ip, int port)

if (m_wifi && !m_usb)
{
uint16_t width = m_pZeDMDWiFi->GetWidth();
uint16_t height = m_pZeDMDWiFi->GetHeight();
m_hd = (width == 256);

m_pFrameBuffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3);
m_pScaledFrameBuffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3);
m_pRgb565Buffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT);

m_hd = (m_pZeDMDWiFi->GetWidth() == 256);
m_pRgb565Buffer = (uint8_t*)malloc(width * height * 2);

m_pZeDMDWiFi->Run();
}
Expand All @@ -284,12 +280,13 @@ bool ZeDMD::Open()

if (m_usb && !m_wifi)
{
uint16_t width = m_pZeDMDComm->GetWidth();
uint16_t height = m_pZeDMDComm->GetHeight();
m_hd = (width == 256);

m_pFrameBuffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3);
m_pScaledFrameBuffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3);
m_pCommandBuffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3 + 192);
m_pRgb565Buffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT);

m_hd = (m_pZeDMDComm->GetWidth() == 256);
m_pRgb565Buffer = (uint8_t*)malloc(width * height * 2);

m_pZeDMDComm->Run();
}
Expand Down Expand Up @@ -328,10 +325,7 @@ void ZeDMD::RenderRgb888(uint8_t* pFrame)
return;
}

uint16_t width;
uint16_t height;

int bufferSize = Scale888(m_pScaledFrameBuffer, m_pFrameBuffer, 3, &width, &height);
int bufferSize = Scale888(m_pScaledFrameBuffer, m_pFrameBuffer, 3);
int rgb565Size = bufferSize / 3;
for (uint16_t i = 0; i < rgb565Size; i++)
{
Expand All @@ -343,11 +337,11 @@ void ZeDMD::RenderRgb888(uint8_t* pFrame)

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream, m_pRgb565Buffer, rgb565Size * 2, width, height);
m_pZeDMDWiFi->QueueFrame(m_pRgb565Buffer, rgb565Size * 2);
}
else if (m_usb)
{
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream, m_pRgb565Buffer, rgb565Size * 2, width, height);
m_pZeDMDComm->QueueFrame(m_pRgb565Buffer, rgb565Size * 2);
}
}

Expand All @@ -358,18 +352,15 @@ void ZeDMD::RenderRgb565(uint16_t* pFrame)
return;
}

uint16_t width;
uint16_t height;

int rgb565Size = Scale565(m_pScaledFrameBuffer, pFrame, &width, &height, is_bigendian());
int size = Scale565(m_pScaledFrameBuffer, pFrame, is_bigendian());

if (m_wifi)
{
m_pZeDMDWiFi->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream, m_pScaledFrameBuffer, rgb565Size, width, height);
m_pZeDMDWiFi->QueueFrame(m_pScaledFrameBuffer, size);
}
else if (m_usb)
{
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream, m_pScaledFrameBuffer, rgb565Size, width, height);
m_pZeDMDComm->QueueFrame(m_pScaledFrameBuffer, size);
}
}
bool ZeDMD::UpdateFrameBuffer888(uint8_t* pFrame)
Expand All @@ -394,72 +385,56 @@ bool ZeDMD::UpdateFrameBuffer565(uint16_t* pFrame)
return true;
}

uint8_t ZeDMD::GetScaleMode(uint16_t frameWidth, uint16_t frameHeight, uint16_t* pWidth, uint16_t* pHeight,
uint8_t ZeDMD::GetScaleMode(uint16_t frameWidth, uint16_t frameHeight,
uint8_t* pXOffset, uint8_t* pYOffset)
{
if (m_upscaling && m_romWidth == 192 && frameWidth == 256)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
(*pXOffset) = 32;
return 0;
}
else if (m_downscaling && m_romWidth == 192 && frameWidth == 128)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
(*pXOffset) = 16;
return 1;
}
else if (m_upscaling && m_romHeight == 16 && frameHeight == 32)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
(*pYOffset) = 8;
return 0;
}
else if (m_upscaling && m_romHeight == 16 && frameHeight == 64)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
(*pYOffset) = 16;
return 2;
}
else if (m_downscaling && m_romWidth == 256 && frameWidth == 128)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
return 1;
}
else if (m_upscaling && m_romWidth == 128 && frameWidth == 256)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
return 2;
}
else if (!m_upscaling && m_romWidth == 128 && frameWidth == 256)
{
(*pWidth) = frameWidth;
(*pHeight) = frameHeight;
(*pXOffset) = 64;
(*pYOffset) = 16;
return 0;
}

(*pWidth) = m_romWidth;
(*pHeight) = m_romHeight;
return 255;
}

int ZeDMD::Scale888(uint8_t* pScaledFrame, uint8_t* pFrame, uint8_t bytes, uint16_t* width, uint16_t* height)
int ZeDMD::Scale888(uint8_t* pScaledFrame, uint8_t* pFrame, uint8_t bytes)
{
uint8_t bits = bytes * 8;
uint8_t xoffset = 0;
uint8_t yoffset = 0;
uint16_t frameWidth = GetWidth();
uint16_t frameHeight = GetHeight();
int bufferSize = m_romWidth * m_romHeight * bytes;
uint8_t scale = GetScaleMode(frameWidth, frameHeight, width, height, &xoffset, &yoffset);
uint8_t scale = GetScaleMode(frameWidth, frameHeight, &xoffset, &yoffset);

if (scale == 255)
{
Expand All @@ -472,28 +447,28 @@ int ZeDMD::Scale888(uint8_t* pScaledFrame, uint8_t* pFrame, uint8_t bytes, uint1

if (scale == 1)
{
FrameUtil::Helper::ScaleDown(pScaledFrame, *width, *height, pFrame, m_romWidth, m_romHeight, bits);
FrameUtil::Helper::ScaleDown(pScaledFrame, frameWidth, frameHeight, pFrame, m_romWidth, m_romHeight, bits);
}
else if (scale == 2)
{
FrameUtil::Helper::ScaleUp(pScaledFrame, pFrame, m_romWidth, m_romHeight, bits);
if (*width > (m_romWidth * 2) || *height > (m_romHeight * 2))
if (frameWidth > (m_romWidth * 2) || frameHeight > (m_romHeight * 2))
{
uint8_t* pUncenteredFrame = (uint8_t*)malloc(bufferSize);
memcpy(pUncenteredFrame, pScaledFrame, bufferSize);
FrameUtil::Helper::Center(pScaledFrame, *width, *height, pUncenteredFrame, m_romWidth * 2, m_romHeight * 2, bits);
FrameUtil::Helper::Center(pScaledFrame, frameWidth, frameHeight, pUncenteredFrame, m_romWidth * 2, m_romHeight * 2, bits);
free(pUncenteredFrame);
}
}
else
{
FrameUtil::Helper::Center(pScaledFrame, *width, *height, pFrame, m_romWidth, m_romHeight, bits);
FrameUtil::Helper::Center(pScaledFrame, frameWidth, frameHeight, pFrame, m_romWidth, m_romHeight, bits);
}

return bufferSize;
}

int ZeDMD::Scale565(uint8_t* pScaledFrame, uint16_t* pFrame, uint16_t* width, uint16_t* height, bool bigEndian)
int ZeDMD::Scale565(uint8_t* pScaledFrame, uint16_t* pFrame, bool bigEndian)
{
int bufferSize = m_romWidth * m_romHeight;
uint8_t* pConvertedFrame = (uint8_t*)malloc(bufferSize * 2);
Expand All @@ -503,7 +478,7 @@ int ZeDMD::Scale565(uint8_t* pScaledFrame, uint16_t* pFrame, uint16_t* width, ui
pConvertedFrame[i * 2 + bigEndian] = pFrame[i] & 0xFF;
}

bufferSize = Scale888(pScaledFrame, pConvertedFrame, 2, width, height);
bufferSize = Scale888(pScaledFrame, pConvertedFrame, 2);
free(pConvertedFrame);

return bufferSize;
Expand Down
7 changes: 3 additions & 4 deletions src/ZeDMD.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,10 @@ class ZEDMDAPI ZeDMD
private:
bool UpdateFrameBuffer888(uint8_t* pFrame);
bool UpdateFrameBuffer565(uint16_t* pFrame);
uint8_t GetScaleMode(uint16_t frameWidth, uint16_t frameHeight, uint16_t* pWidth, uint16_t* pHeight,
uint8_t GetScaleMode(uint16_t frameWidth, uint16_t frameHeight,
uint8_t* pXOffset, uint8_t* pYOffset);
int Scale888(uint8_t* pScaledFrame, uint8_t* pFrame, uint8_t bytes, uint16_t* width, uint16_t* height);
int Scale565(uint8_t* pScaledFrame, uint16_t* pFrame, uint16_t* width, uint16_t* height, bool bigEndian);
int Scale888(uint8_t* pScaledFrame, uint8_t* pFrame, uint8_t bytes);
int Scale565(uint8_t* pScaledFrame, uint16_t* pFrame, bool bigEndian);

ZeDMDComm* m_pZeDMDComm;
ZeDMDWiFi* m_pZeDMDWiFi;
Expand All @@ -351,7 +351,6 @@ class ZEDMDAPI ZeDMD

uint8_t* m_pFrameBuffer;
uint8_t* m_pScaledFrameBuffer;
uint8_t* m_pCommandBuffer;
uint8_t* m_pRgb565Buffer;
};

Expand Down
43 changes: 11 additions & 32 deletions src/ZeDMDComm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ void ZeDMDComm::Run()
if (m_frames.front().data.empty())
{
// In case of a simple command, add metadata to indicate that the payload data size is 0.
m_frames.front().data.emplace_back(nullptr, 0, 0);
m_frames.front().data.emplace_back(nullptr, 0);

}
bool success = StreamBytes(&(m_frames.front()));
m_frames.pop();
Expand Down Expand Up @@ -136,7 +137,7 @@ void ZeDMDComm::QueueCommand(char command, uint8_t value) { QueueCommand(command

void ZeDMDComm::QueueCommand(char command) { QueueCommand(command, nullptr, 0); }

void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t width, uint16_t height)
void ZeDMDComm::QueueFrame(uint8_t* data, int size)
{
if (memcmp(data, m_allBlack, size) == 0)
{
Expand Down Expand Up @@ -172,28 +173,15 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t wid
}

uint8_t idx = 0;
uint8_t numZones = 0;
uint16_t zonesBytesLimit = 0;
uint16_t zonesBytesLimit = ZEDMD_ZONES_BYTE_LIMIT;
const uint16_t zoneBytes = m_zoneWidth * m_zoneHeight * 2;
const uint16_t zoneBytesTotal = zoneBytes + 1;
uint8_t* zone = (uint8_t*)malloc(zoneBytes);

if (m_zonesBytesLimit)
{
// Find the limit as integer that is closest to m_zonesBytesLimit for example 1540 for RGB888 HD.
uint8_t zones = m_zonesBytesLimit / zoneBytesTotal;
zonesBytesLimit = zones * zoneBytesTotal;
}
else
{
// For USB UART send one row (16 zones).
zonesBytesLimit = width * m_zoneHeight * 2 + 16;
}
uint8_t* buffer = (uint8_t*)malloc(zonesBytesLimit);
uint16_t bufferPosition = 0;
const uint16_t bufferSizeThreshold = zonesBytesLimit - zoneBytesTotal;

ZeDMDFrame frame(command);
ZeDMDFrame frame(ZEDMD_COMM_COMMAND::RGB565ZonesStream);

bool delayed = FillDelayed();
if (delayed)
Expand All @@ -204,13 +192,13 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t wid
}

memset(buffer, 0, zonesBytesLimit);
for (uint16_t y = 0; y < height; y += m_zoneHeight)
for (uint16_t y = 0; y < m_height; y += m_zoneHeight)
{
for (uint16_t x = 0; x < width; x += m_zoneWidth)
for (uint16_t x = 0; x < m_width; x += m_zoneWidth)
{
for (uint8_t z = 0; z < m_zoneHeight; z++)
{
memcpy(&zone[z * m_zoneWidth * 2], &data[((y + z) * width + x) * 2], m_zoneWidth * 2);
memcpy(&zone[z * m_zoneWidth * 2], &data[((y + z) * m_width + x) * 2], m_zoneWidth * 2);
}

bool black = (memcmp(zone, m_allBlack, zoneBytes) == 0);
Expand All @@ -221,7 +209,6 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t wid
{
m_zoneHashes[idx] = hash;
m_zoneRepeatCounters[idx] = 0;
numZones++;

if (black)
{
Expand All @@ -237,10 +224,9 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t wid

if (bufferPosition > bufferSizeThreshold)
{
frame.data.emplace_back(buffer, bufferPosition, numZones);
frame.data.emplace_back(buffer, bufferPosition);
memset(buffer, 0, zonesBytesLimit);
bufferPosition = 0;
numZones = 0;
}
}
idx++;
Expand All @@ -249,7 +235,7 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size, uint16_t wid

if (bufferPosition > 0)
{
frame.data.emplace_back(buffer, bufferPosition, numZones);
frame.data.emplace_back(buffer, bufferPosition);
}

free(buffer);
Expand Down Expand Up @@ -506,10 +492,6 @@ bool ZeDMDComm::Connect(char* pDevice)
{
// 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);

return true;
Expand Down Expand Up @@ -612,9 +594,7 @@ bool ZeDMDComm::StreamBytes(ZeDMDFrame* pFrame)
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]) ||
// The not compressed RGB565 frame is m_width * m_height * 2, but if every pixel is different, we might be
// bigger.
compressedSize > (m_width * m_height * 3))
compressedSize > (ZEDMD_ZONES_BYTE_LIMIT))
{
Log("Compression error");
free(pData);
Expand All @@ -632,7 +612,6 @@ bool ZeDMDComm::StreamBytes(ZeDMDFrame* pFrame)
{
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)
Expand Down
Loading

0 comments on commit f0a22e1

Please sign in to comment.