Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PinDMD3: Add support for colored 4-bit #217

Merged
merged 5 commits into from
Apr 4, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion LibDmd/Output/PinDmd3/PinDmd3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace LibDmd.Output.PinDmd3
/// Output target for PinDMDv3 devices.
/// </summary>
/// <see cref="http://pindmd.com/"/>
public class PinDmd3 : IGray2Destination, IGray4Destination, IColoredGray2Destination, IRawOutput, IFixedSizeDestination
public class PinDmd3 : IGray2Destination, IGray4Destination, IColoredGray2Destination, IColoredGray4Destination, IRawOutput, IFixedSizeDestination
{
public string Name { get; } = "PinDMD v3";
public bool IsAvailable { get; private set; }
Expand All @@ -26,6 +26,7 @@ public class PinDmd3 : IGray2Destination, IGray4Destination, IColoredGray2Destin
const byte Rgb24CommandByte = 0x02;
const byte Gray2CommandByte = 0x30;
const byte Gray4CommandByte = 0x31;
const byte ColoredGray4CommandByte = 0x32;

/// <summary>
/// Firmware string read from the device if connected
Expand All @@ -42,7 +43,9 @@ public class PinDmd3 : IGray2Destination, IGray4Destination, IColoredGray2Destin
private readonly byte[] _frameBufferRgb24;
private readonly byte[] _frameBufferGray4;
private readonly byte[] _frameBufferGray2;
private readonly byte[] _frameBufferColoredGray4;
private bool _lastFrameFailed = false;
private bool _supportsColoredGray4 = false;

//private readonly byte[] _lastBuffer;
//private long _lastTick;
Expand Down Expand Up @@ -105,6 +108,11 @@ private PinDmd3()
_frameBufferGray2[0] = Gray2CommandByte;
_frameBufferGray2[DmdWidth * DmdHeight / 4 + 13] = Gray2CommandByte;

// 16 colors, 4 bytes of pixel, 2 control bytes
_frameBufferColoredGray4 = new byte[1 + 48 + DmdWidth * DmdHeight / 2 + 1];
_frameBufferColoredGray4[0] = ColoredGray4CommandByte;
_frameBufferColoredGray4[_frameBufferColoredGray4.Length - 1] = ColoredGray4CommandByte;

//_lastBuffer = new byte[DmdWidth * DmdHeight * 3 + 2];

ClearColor();
Expand Down Expand Up @@ -156,12 +164,14 @@ private bool Connect(string port, bool checkFirmware)
Logger.Info("Found PinDMDv3 device on {0}.", port);
Logger.Debug(" Firmware: {0}", Firmware);
Logger.Debug(" Resolution: {0}x{1}", (int)result[0], (int)result[1]);
_parseFirmware();
return true;
}
} else {
Logger.Info("Trusting that PinDMDv3 sits on port {0}.", port);
Logger.Debug(" Firmware: {0}", Firmware);
Logger.Debug(" Resolution: {0}x{1}", (int)result[0], (int)result[1]);
_parseFirmware();
return true;
}

Expand Down Expand Up @@ -216,6 +226,36 @@ public void RenderGray4(byte[] frame)
}
}

public void RenderColoredGray4(ColoredFrame frame)
{
// fall back if firmware doesn't support colored gray 4
if (!_supportsColoredGray4) {
var rgb24Frame = ColorUtil.ColorizeFrame(DmdWidth, DmdHeight,
FrameUtil.Join(DmdWidth, DmdHeight, frame.Planes), frame.Palette);
RenderRgb24(rgb24Frame);
return;
}

// copy palette
var paletteChanged = false;
for (var i = 0; i < 16; i++) {
var color = frame.Palette[i];
var j = i * 3;
paletteChanged = paletteChanged || (_frameBufferColoredGray4[j + 1] != color.R || _frameBufferColoredGray4[j + 2] != color.G || _frameBufferColoredGray4[j + 3] != color.B);
_frameBufferColoredGray4[j + 1] = color.R;
_frameBufferColoredGray4[j + 2] = color.G;
_frameBufferColoredGray4[j + 3] = color.B;
}

// copy frame
var frameChanged = FrameUtil.Copy(frame.Planes, _frameBufferColoredGray4, 49);

// send frame buffer to device
if (frameChanged || paletteChanged) {
RenderRaw(_frameBufferColoredGray4);
}
}

public void RenderRgb24(byte[] frame)
{
// copy data to frame buffer
Expand Down Expand Up @@ -339,5 +379,23 @@ public void Dispose()
}
}
}

private void _parseFirmware()
{
// parse firmware
var match = Regex.Match(Firmware, @"REV-vPin-(\d+)$", RegexOptions.IgnoreCase);
if (match.Success) {
var revision = Int32.Parse(match.Groups[1].Value);
Logger.Debug(" Revision: {0}", revision);
_supportsColoredGray4 = revision >= 1013;

} else {
Logger.Warn("Could not parse revision from firmware.");
}

if (_supportsColoredGray4) {
Logger.Info("Colored 4-bit frames for PinDMDv3 enabled.");
}
}
}
}