This commit is contained in:
Sven Vogel 2021-06-09 21:19:30 +02:00
parent 6230473ec6
commit b7d5b37fbc
20 changed files with 290 additions and 40 deletions

213
Arduino/LED_Matrix.ino Normal file
View File

@ -0,0 +1,213 @@
#include "Arduino.h"
#include "FastLED.h"
#define LED_TYPE WS2812B
#define DATA_PIN 6
#define MATRIX_MAX_WIDTH 20
#define MATRIX_MAX_HEIGHT 20
#define MATRIX_LED_MAX_COUNT (MATRIX_MAX_WIDTH * MATRIX_MAX_HEIGHT)
#define STD_WIDTH 10
#define STD_HEIGHT 10
#define STD_LED_MAX_COUNT (STD_WIDTH * STD_HEIGHT)
//#define DEBUG_PRINT_CALLBACK
#define WAIT while(!Serial.available());
uint8_t opcode = 99;
uint8_t width = STD_WIDTH;
uint8_t height = STD_HEIGHT;
uint32_t ledCount;
uint8_t gamma8(uint8_t x) {
uint32_t x2 = (uint32_t) x;
x2 = x2 * x2 * 258 >> 16;
return (uint8_t) x2;
}
CRGB leds[MATRIX_LED_MAX_COUNT];
typedef void (*FNPTR_t)();
uint8_t getByte() {
WAIT
return Serial.read();
}
uint16_t getWord() {
uint16_t highByte = getByte();
uint16_t lowByte = getByte();
return highByte << 8 | lowByte;
}
void scale() {
#ifdef DEBUG_PRINT_CALLBACK
Serial.println("scale called");
#endif
width = getByte();
height = getByte();
#ifdef DEBUG_PRINT_CALLBACK
Serial.print("Width: ");
Serial.println(width);
Serial.print("Height: ");
Serial.println(height);
#endif
uint16_t newLedCount = width * height;
if (newLedCount <= MATRIX_LED_MAX_COUNT) {
ledCount = newLedCount;
} else {
return;
}
#ifdef DEBUG_PRINT_CALLBACK
Serial.print("LEDs: ");
Serial.println(ledCount);
#endif
FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, ledCount);
for (uint16_t x = 0; x < ledCount; x++) {
leds[x].r = 0;
leds[x].g = 0;
leds[x].b = 0;
}
FastLED.show();
}
void single() {
#ifdef DEBUG_PRINT_CALLBACK
Serial.println("Single called");
#endif
uint16_t index = getWord();
uint8_t green = gamma8(getByte());
uint8_t red = gamma8(getByte());
uint8_t blue = gamma8(getByte());
#ifdef DEBUG_PRINT_CALLBACK
Serial.print("Index: ");
Serial.println(index);
Serial.print("Red: ");
Serial.println(red);
Serial.print("Green: ");
Serial.println(green);
Serial.print("Blue: ");
Serial.println(blue);
#endif
leds[index] = CRGB(red, green, blue);
FastLED.show();
}
void image() {
Serial.readBytes((char*) leds, ledCount * 3);
for (uint16_t x = 0; x < ledCount; x++) {
leds[x].r = gamma8(leds[x].r);
leds[x].g = gamma8(leds[x].g);
leds[x].b = gamma8(leds[x].b);
}
FastLED.show();
}
void fill() {
#ifdef DEBUG_PRINT_CALLBACK
Serial.println("Called fill");
#endif
uint8_t green = gamma8(getByte());
uint8_t red = gamma8(getByte());
uint8_t blue = gamma8(getByte());
#ifdef DEBUG_PRINT_CALLBACK
Serial.print("Red: ");
Serial.println(red);
Serial.print("Green: ");
Serial.println(green);
Serial.print("Blue: ");
Serial.println(blue);
#endif
for (uint16_t x = 0; x < ledCount; x++) {
leds[x].r = red;
leds[x].g = green;
leds[x].b = blue;
}
FastLED.show();
}
void config() {
Serial.write(width);
Serial.write(height);
for (uint32_t i = 0; i < ledCount; i++){
Serial.write((uint8_t) leds[i].r);
Serial.write((uint8_t) leds[i].g);
Serial.write((uint8_t) leds[i].b);
}
}
FNPTR_t opcodeTable[] = {
scale, // opcode 0x00
single, // opcode 0x01
image, // opcode 0x02
fill, // opcode 0x03
config // opcode 0x04
};
void setup() {
ledCount = STD_LED_MAX_COUNT;
Serial.begin(9600);
FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, ledCount);
for (uint16_t i = 0; i < ledCount; i++) {
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 0;
}
FastLED.show();
}
void loop() {
if (Serial.available()) {
#ifdef DEBUG_PRINT_CALLBACK
Serial.println("Opcode read in");
#endif
opcode = getByte();
#ifdef DEBUG_PRINT_CALLBACK
Serial.print("Opcode changed to:");
Serial.println(opcode);
#endif
if (opcode <= 4) {
opcodeTable[opcode]();
Serial.write(21);
}
}
}

View File

@ -37,6 +37,6 @@
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Remove="SplashScreen.resx" /> <EmbeddedResource Remove="SplashScreen.resx" />
<None Remove="Resources\pfüsikuh.png" /> <None Remove="Resources\pfüsikuh.png" />
<EmbeddedResource Include="Resources\pfüsikuh.png" /> <None Remove="Utils.cs~" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -63,7 +63,7 @@ namespace Matrix_App
// apply light-mode by default // apply light-mode by default
new LightMode().ApplyTheme(this); new LightMode().ApplyTheme(this);
} }
private void Init() private void Init()
{ {
// Create port name update timer // Create port name update timer
@ -99,7 +99,7 @@ namespace Matrix_App
if (((int) DateTime.Now.DayOfWeek) != 3) if (((int) DateTime.Now.DayOfWeek) != 3)
return; return;
if (new Random().Next(0, 9) <= 1) if (new Random().Next(0, 9) >= 1)
return; return;
using (Bitmap wednesdayFrog = new Bitmap(Properties.Resources.Frosch)) using (Bitmap wednesdayFrog = new Bitmap(Properties.Resources.Frosch))
@ -646,7 +646,7 @@ namespace Matrix_App
{ {
if (Timeline.InvokeRequired) if (Timeline.InvokeRequired)
{ {
// invoke on the comboboxes thread // invoke on the combo-boxes thread
Timeline.Invoke(new Action(() => Timeline.Invoke(new Action(() =>
{ {
if (Timeline.Value < Timeline.Maximum) if (Timeline.Value < Timeline.Maximum)

View File

@ -1,5 +1,6 @@
using Matrix_App.PregeneratedMods; using Matrix_App.PregeneratedMods;
using System; using System;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -85,8 +86,8 @@ namespace Matrix_App
}; };
button.Click += (sender, e) => OpenGeneratorUi(generator, matrix); button.Click += (sender, e) => OpenGeneratorUi(generator, matrix);
button.Image = CreateSnapshot(generator); button.Image = CreateSnapshot(generator);
button.TextImageRelation = TextImageRelation.ImageAboveText; button.TextImageRelation = TextImageRelation.ImageBeforeText;
button.Height = FilterPreviewHeight * 2; button.Height = FilterPreviewHeight * 3 / 2;
anchor.Controls.Add(button); anchor.Controls.Add(button);
} }
@ -179,7 +180,7 @@ namespace Matrix_App
PlaybackTimer.Interval = _form.GetDelayTime(); PlaybackTimer.Interval = _form.GetDelayTime();
PlaybackTimer.Enabled = true; PlaybackTimer.Enabled = true;
CreateDivider(controlPanel); CreateDivider(controlPanel, 2);
foreach (var field in fields) foreach (var field in fields)
{ {
if (field.IsStatic || !field.IsPublic) if (field.IsStatic || !field.IsPublic)
@ -187,23 +188,11 @@ namespace Matrix_App
var fieldValue = field.GetValue(_generator); var fieldValue = field.GetValue(_generator);
controlPanel.Controls.Add(GetFieldUi(field, fieldValue, _generator)); controlPanel.Controls.AddRange(GetFieldUi(field, _generator.GetType(), fieldValue, _generator));
} CreateDivider(controlPanel, 1);
if (controlPanel.Controls.Count > 1)
{
CreateDivider(controlPanel);
var label = new Label() { Text = "Settings" };
label.Font = new Font(label.Font, FontStyle.Bold);
controlPanel.Controls.Add(label);
} }
controlPanel.Controls.Add(_preview); controlPanel.Controls.Add(_preview);
CreateDivider(controlPanel);
var playLabel = new Label() { Text = "Playback preview" };
playLabel.Font = new Font(playLabel.Font, FontStyle.Bold);
controlPanel.Controls.Add(playLabel);
FlowLayoutPanel southPane = new FlowLayoutPanel FlowLayoutPanel southPane = new FlowLayoutPanel
{ {
@ -229,7 +218,7 @@ namespace Matrix_App
return success; return success;
} }
private static Control GetFieldUi(FieldInfo field, object? fieldValue, MatrixGifGenerator generator) private static Control[] GetFieldUi(FieldInfo field, Type clazz, object? fieldValue, MatrixGifGenerator generator)
{ {
var panel = new FlowLayoutPanel var panel = new FlowLayoutPanel
{ {
@ -237,11 +226,24 @@ namespace Matrix_App
Anchor = AnchorStyles.Top | AnchorStyles.Left, Anchor = AnchorStyles.Top | AnchorStyles.Left,
AutoSize = true AutoSize = true
}; };
var title = GetBetterFieldName(field.Name);
var description = new Label();
if (Attribute.GetCustomAttribute(field, typeof(UiDescriptionAttribute)) is UiDescriptionAttribute desc)
{
title = desc.title;
description.Text = desc.description;
description.ForeColor = Color.Gray;
description.Height += 10;
description.AutoSize = true;
}
panel.Controls.Add(new Label panel.Controls.Add(new Label
{ {
TextAlign = System.Drawing.ContentAlignment.MiddleLeft, TextAlign = ContentAlignment.MiddleLeft,
Text = GetBetterFieldName(field.Name), Text = title,
Dock = DockStyle.Left, Dock = DockStyle.Left,
Anchor = AnchorStyles.Top | AnchorStyles.Left, Anchor = AnchorStyles.Top | AnchorStyles.Left,
Width = 100 Width = 100
@ -305,7 +307,7 @@ namespace Matrix_App
} }
} }
return panel; return new Control[] {description, panel};
} }
/// <summary> /// <summary>
@ -354,13 +356,13 @@ namespace Matrix_App
/// Adds a separating line to the controls /// Adds a separating line to the controls
/// </summary> /// </summary>
/// <param name="controlPanel"></param> /// <param name="controlPanel"></param>
private static void CreateDivider(Control controlPanel) private static void CreateDivider(Control controlPanel, int height)
{ {
var divider = new Label var divider = new Label
{ {
BorderStyle = BorderStyle.Fixed3D, BorderStyle = BorderStyle.Fixed3D,
AutoSize = false, AutoSize = false,
Height = 2, Height = height,
Width = 500 Width = 500
}; };

View File

@ -1,12 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App.PregeneratedMods namespace Matrix_App.PregeneratedMods
{ {
public class Boxblur : MatrixGifGenerator public sealed class Boxblur : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Blur size", description: "The side length of the bounding square used to blur in pixels")]
public int blurSize = 2; public int blurSize = 2;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)

View File

@ -7,12 +7,18 @@ namespace Matrix_App.PregeneratedMods
{ {
public sealed class ColorAdjust : MatrixGifGenerator public sealed class ColorAdjust : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Tone offset", description: "Sets an additional offset to the pixels hue")]
public float hueOffset = 0.0f; public float hueOffset = 0.0f;
[UiDescriptionAttribute(title: "Saturation boost", description: "Decreases or increases saturation")]
public float saturationBoost = 0.5f; public float saturationBoost = 0.5f;
[UiDescriptionAttribute(title: "Brightness boost", description: "Decreases or increases brightness")]
public float valueBoost = 0.5f; public float valueBoost = 0.5f;
[UiDescriptionAttribute(title: "Red boost", description: "Decreases or increases Red")]
public float redBoost = 0.5f; public float redBoost = 0.5f;
[UiDescriptionAttribute(title: "Green boost", description: "Decreases or increases Green")]
public float greenBoost = 0.5f; public float greenBoost = 0.5f;
[UiDescriptionAttribute(title: "Blue boost", description: "Decreases or increases Blue")]
public float blueBoost = 0.5f; public float blueBoost = 0.5f;
private float boost(float x, float y) private float boost(float x, float y)

View File

@ -7,6 +7,7 @@ namespace Matrix_App.PregeneratedMods
{ {
public sealed class Grayscale : MatrixGifGenerator public sealed class Grayscale : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "use Luminance", description: "Use luminance as defined by ITU-R BT.709 as grayscale output")]
public bool byLuminance = false; public bool byLuminance = false;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)

View File

@ -4,6 +4,7 @@ namespace Matrix_App.PregeneratedMods
{ {
public class RandomPixels : MatrixGifGenerator public class RandomPixels : MatrixGifGenerator
{ {
[UiDescriptionAttribute(title: "Seed", description: "Just a seed for a bad deterministic random function")]
public int seed = 0; public int seed = 0;
protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b) protected override void ColorFragment(in int x, in int y, in float u, in float v, in int frame, out float r, out float g, out float b)

View File

@ -1,17 +1,18 @@
using System; using System;
using System.Collections.Generic;
using System.Text;
using static Matrix_App.GifGeneratorUtils; using static Matrix_App.GifGeneratorUtils;
namespace Matrix_App namespace Matrix_App.PregeneratedMods
{ {
public class SimpleRainbow : MatrixGifGenerator public class SimpleRainbow : MatrixGifGenerator
{ {
[UiDescription(title: "Radial", description: "Uses the angle to alter hues")]
public bool radial = false; public bool radial = false;
[UiDescription(title: "Saturation", description: "Overall saturation")]
public float saturation = 1.0f; public float saturation = 1.0f;
[UiDescription(title: "Brightness", description: "Overall brightness")]
public float value = 1.0f; public float value = 1.0f;
[UiDescription(title: "Hue rotation", description: "Offset for hue calculation")]
public float rotation = 0.0f; public float rotation = 0.0f;
protected override void ColorFragment(in int x, in int y, protected override void ColorFragment(in int x, in int y,

View File

@ -0,0 +1,17 @@
using System;
namespace Matrix_App.PregeneratedMods
{
[AttributeUsage(AttributeTargets.Field)]
public class UiDescriptionAttribute : Attribute
{
public string title;
public string description;
public UiDescriptionAttribute(string title, string description)
{
this.title = title;
this.description = description;
}
}
}

View File

@ -10,17 +10,22 @@ namespace Matrix_App
/// </summary> /// </summary>
[STAThread] [STAThread]
private static void Main() private static void Main()
{ {
SplashScreen.ShowSplashScreen();
Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
SplashScreen.ShowSplashScreen();
var designer = new MatrixDesignerMain(); var designer = new MatrixDesignerMain();
SplashScreen.CloseForm(); SplashScreen.CloseForm();
designer.StartPosition = FormStartPosition.CenterScreen;
designer.WindowState = FormWindowState.Minimized;
designer.Show();
designer.WindowState = FormWindowState.Normal;
Application.Run(designer); Application.Run(designer);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -1,4 +1,5 @@
using System.Threading; using System.Drawing;
using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
namespace Matrix_App namespace Matrix_App
@ -17,8 +18,12 @@ namespace Matrix_App
Controls.Add(new Label() Controls.Add(new Label()
{ {
Image = Properties.Resources.Pfüsikuh Image = Properties.Resources.Pfüsikuh,
Size = new Size(Properties.Resources.Pfüsikuh.Width, Properties.Resources.Pfüsikuh.Height)
}); });
Size = new Size(Properties.Resources.Pfüsikuh.Width, Properties.Resources.Pfüsikuh.Height);
StartPosition = FormStartPosition.CenterScreen;
} }
public static void ShowSplashScreen() public static void ShowSplashScreen()

View File

@ -1 +1 @@
ee8b86baf58d13435f960406ec4b0be78d0cc26c 0e5f843b45897d8b4a3e6250399d748fbf87d606