Skip to content

Commit

Permalink
Merge branch 'main' into gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Jan 26, 2024
2 parents cb23273 + 44a8f03 commit 49ee1c9
Show file tree
Hide file tree
Showing 405 changed files with 106,861 additions and 115 deletions.
49 changes: 40 additions & 9 deletions src/ZeDMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ void ZeDMD::SetFrameSize(uint16_t width, uint16_t height) {
}
}

uint16_t ZeDMD::GetWidth() {
return m_pZeDMDComm->GetWidth();
}

uint16_t ZeDMD::GetHeight() {
return m_pZeDMDComm->GetHeight();
}

void ZeDMD::LedTest() {
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::LEDTest);
}
Expand Down Expand Up @@ -192,7 +200,7 @@ bool ZeDMD::Open() {
m_pCommandBuffer =
(uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3 + 192);
m_pPlanes = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 3);
m_pRgb565Buffer = (uint16_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT);
m_pRgb565Buffer = (uint8_t*)malloc(ZEDMD_MAX_WIDTH * ZEDMD_MAX_HEIGHT * 2);

m_hd = (m_pZeDMDComm->GetWidth() == 256);

Expand Down Expand Up @@ -414,17 +422,31 @@ void ZeDMD::RenderRgb24EncodedAs565(uint8_t* pFrame) {
uint16_t height;

int bufferSize = Scale(m_pPlanes, m_pFrameBuffer, 3, &width, &height);
int rgb565BufferSize = bufferSize / 3;
for (uint16_t i = 0; i < rgb565BufferSize; i++) {
m_pRgb565Buffer[i] = (((uint16_t)(m_pPlanes[i * 3] & 0xF8)) << 8) |
(((uint16_t)(m_pPlanes[i * 3 + 1] & 0xFC)) << 3) |
(m_pPlanes[i * 3 + 2] >> 3);
int rgb565Size = bufferSize / 3;
for (uint16_t i = 0; i < rgb565Size; i++) {
uint16_t tmp = (((uint16_t)(m_pPlanes[i * 3] & 0xF8)) << 8) |
(((uint16_t)(m_pPlanes[i * 3 + 1] & 0xFC)) << 3) |
(m_pPlanes[i * 3 + 2] >> 3);
m_pRgb565Buffer[i * 2] = tmp >> 8;
m_pRgb565Buffer[i * 2 + 1] = tmp & 0xFF;
}

if (m_usb) {
m_pZeDMDComm->QueueRgb565Command(ZEDMD_COMM_COMMAND::RGB565ZonesStream,
m_pRgb565Buffer, rgb565BufferSize, width,
height);
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream,
m_pRgb565Buffer, rgb565Size * 2, width, height,
2);
}
}

void ZeDMD::RenderRgb565(uint16_t* pFrame) {
if (!m_usb || !UpdateFrameBuffer565(pFrame)) {
return;
}

if (m_usb) {
m_pZeDMDComm->QueueCommand(ZEDMD_COMM_COMMAND::RGB565ZonesStream,
m_pFrameBuffer, m_romWidth * m_romHeight * 2,
m_romWidth, m_romHeight, 2);
}
}

Expand All @@ -446,6 +468,15 @@ bool ZeDMD::UpdateFrameBuffer24(uint8_t* pFrame) {
return true;
}

bool ZeDMD::UpdateFrameBuffer565(uint16_t* pFrame) {
if (!memcmp(m_pFrameBuffer, pFrame, m_romWidth * m_romHeight * 2)) {
return false;
}

memcpy(m_pFrameBuffer, pFrame, m_romWidth * m_romHeight * 2);
return true;
}

/**
* Derived from
* https://github.com/freezy/dmd-extensions/blob/master/LibDmd/Common/FrameUtil.cs
Expand Down
30 changes: 27 additions & 3 deletions src/ZeDMD.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ class ZEDMDAPI ZeDMD {
*/
void SetFrameSize(uint16_t width, uint16_t height);

/** @brief Get the physical panel width
*
* Get the width of the physical dimensions of the LED panels.
*
* @return width
*/
uint16_t GetWidth();

/** @brief Get the physical panel height
*
* Get the height of the physical dimensions of the LED panels.
*
* @return height
*/
uint16_t GetHeight();

/** @brief Set the palette
*
* Set the color palette to use to render gray scaled content.
Expand Down Expand Up @@ -319,7 +335,7 @@ class ZEDMDAPI ZeDMD {
* and only updates zones that have changes compared to the previous
* frame. This method results in less data that needs to be transfered
* and in smoother animations. But it takes a bit longer if the entire
* frame changes. Zone streaming is the default for RebderRGB24() and
* frame changes. Zone streaming is the default for RenderRGB24() and
* RenderRgb24EncodedAs565(). All other modes use the classic way by
* default unless EnforceStreaming() is called.
* @see RenderGray2()
Expand Down Expand Up @@ -413,10 +429,18 @@ class ZEDMDAPI ZeDMD {
*/
void RenderRgb24EncodedAs565(uint8_t* frame);

/** @brief Render a RGB565 frame
*
* Renders a true color RGB565 frame. Only zone streaming mode is supported.
*
* @param frame the RGB565 frame
*/
void RenderRgb565(uint16_t* frame);

private:
bool UpdateFrameBuffer8(uint8_t* pFrame);
bool UpdateFrameBuffer24(uint8_t* pFrame);

bool UpdateFrameBuffer565(uint16_t* pFrame);
void Split(uint8_t* planes, uint16_t width, uint16_t height, uint8_t bitlen,
uint8_t* frame);
void ConvertToRgb24(uint8_t* pFrameRgb24, uint8_t* pFrame, int size,
Expand Down Expand Up @@ -445,7 +469,7 @@ class ZEDMDAPI ZeDMD {
uint8_t* m_pScaledFrameBuffer;
uint8_t* m_pCommandBuffer;
uint8_t* m_pPlanes;
uint16_t* m_pRgb565Buffer;
uint8_t* m_pRgb565Buffer;

uint8_t m_palette4[4 * 3] = {0};
uint8_t m_palette16[16 * 3] = {0};
Expand Down
95 changes: 12 additions & 83 deletions src/ZeDMDComm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size,
frame.streamId = streamId;

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

Expand Down Expand Up @@ -185,18 +185,18 @@ void ZeDMDComm::QueueCommand(char command) {
}

void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size,
uint16_t width, uint16_t height) {
uint8_t buffer[256 * 16 * 3 + 16];
uint16_t width, uint16_t height, uint8_t bytes) {
uint8_t buffer[256 * 16 * bytes + 16];
uint16_t bufferSize = 0;
uint8_t idx = 0;
uint8_t zone[16 * 8 * 3] = {0};
uint8_t zone[16 * 8 * bytes] = {0};
uint16_t zonesBytesLimit = 0;
if (m_zonesBytesLimit) {
while (zonesBytesLimit < m_zonesBytesLimit) {
zonesBytesLimit += m_zoneWidth * m_zoneHeight * 3 + 1;
zonesBytesLimit += m_zoneWidth * m_zoneHeight * bytes + 1;
}
} else {
zonesBytesLimit = width * m_zoneHeight * 3 + 16;
zonesBytesLimit = width * m_zoneHeight * bytes + 16;
}

if (++m_streamId > 64) {
Expand All @@ -205,6 +205,7 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size,

bool delayed = false;
if (FillDelayed()) {
// printf("DELAYED\n");
delayed = true;
m_delayedFrameMutex.lock();
m_delayedFrameReady = false;
Expand All @@ -220,89 +221,17 @@ void ZeDMDComm::QueueCommand(char command, uint8_t* data, int size,
for (uint16_t y = 0; y < height; y += m_zoneHeight) {
for (uint16_t x = 0; x < width; x += m_zoneWidth) {
for (uint8_t z = 0; z < m_zoneHeight; z++) {
memcpy(&zone[z * m_zoneWidth * 3], &data[((y + z) * width + x) * 3],
m_zoneWidth * 3);
memcpy(&zone[z * m_zoneWidth * bytes],
&data[((y + z) * width + x) * bytes], m_zoneWidth * bytes);
}

uint64_t hash = komihash(zone, m_zoneWidth * m_zoneHeight * 3, 0);
uint64_t hash = komihash(zone, m_zoneWidth * m_zoneHeight * bytes, 0);
if (hash != m_zoneHashes[idx]) {
m_zoneHashes[idx] = hash;

buffer[bufferSize++] = idx;
memcpy(&buffer[bufferSize], zone, m_zoneWidth * m_zoneHeight * 3);
bufferSize += m_zoneWidth * m_zoneHeight * 3;

if (bufferSize >= zonesBytesLimit) {
QueueCommand(command, buffer, bufferSize, m_streamId, delayed);
bufferSize = 0;
}
}
idx++;
}
}

if (bufferSize > 0) {
QueueCommand(command, buffer, bufferSize, m_streamId, delayed);
}

if (delayed) {
m_delayedFrameMutex.lock();
m_delayedFrameReady = true;
m_delayedFrameMutex.unlock();
}
}

void ZeDMDComm::QueueRgb565Command(char command, uint16_t* data, int size,
uint16_t width, uint16_t height) {
uint8_t buffer[256 * 16 * 2 + 16];
uint16_t bufferSize = 0;
uint8_t idx = 0;
uint8_t zone[16 * 8 * 2] = {0};
uint16_t zonesBytesLimit = 0;
if (m_zonesBytesLimit) {
while (zonesBytesLimit < m_zonesBytesLimit) {
zonesBytesLimit += m_zoneWidth * m_zoneHeight * 2 + 1;
}
} else {
zonesBytesLimit = width * m_zoneHeight * 2 + 16;
}

if (++m_streamId > 64) {
m_streamId = 0;
}

bool delayed = false;
if (FillDelayed()) {
delayed = true;
m_delayedFrameMutex.lock();
m_delayedFrameReady = false;
while (m_delayedFrames.size() > 0) {
m_delayedFrames.pop();
}

m_delayedFrameMutex.unlock();
// A delayed frame needs to be complete.
memset(m_zoneHashes, 0, sizeof(m_zoneHashes));
}

for (uint16_t y = 0; y < height; y += m_zoneHeight) {
for (uint16_t x = 0; x < width; x += m_zoneWidth) {
for (uint8_t zy = 0; zy < m_zoneHeight; zy++) {
for (uint8_t zx = 0; zx < m_zoneWidth; zx++) {
zone[(zy * m_zoneWidth + zx) * 2] =
data[((y + zy) * width) + x + zx] >> 8;
zone[(zy * m_zoneWidth + zx) * 2 + 1] =
data[((y + zy) * width) + x + zx] & 0xFF;
}
}

uint64_t hash = komihash(zone, m_zoneWidth * m_zoneHeight * 2, 0);
if (hash != m_zoneHashes[idx]) {
m_zoneHashes[idx] = hash;

buffer[bufferSize++] = idx;
memcpy(&buffer[bufferSize], zone, m_zoneWidth * m_zoneHeight * 2);
bufferSize += m_zoneWidth * m_zoneHeight * 2;
memcpy(&buffer[bufferSize], zone, m_zoneWidth * m_zoneHeight * bytes);
bufferSize += m_zoneWidth * m_zoneHeight * bytes;

if (bufferSize >= zonesBytesLimit) {
QueueCommand(command, buffer, bufferSize, m_streamId, delayed);
Expand Down
4 changes: 1 addition & 3 deletions src/ZeDMDComm.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ class ZeDMDComm {

void Run();
void QueueCommand(char command, uint8_t* buffer, int size, uint16_t width,
uint16_t height);
void QueueRgb565Command(char command, uint16_t* buffer, int size,
uint16_t width, uint16_t height);
uint16_t height, uint8_t bytes = 3);
void QueueCommand(char command, uint8_t* buffer, int size,
int8_t streamId = -1, bool delayed = false);
void QueueCommand(char command);
Expand Down
Loading

0 comments on commit 49ee1c9

Please sign in to comment.