Matomat/Matomat/Output/LCDDisplay.cs

261 lines
8.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO.Ports;
using Matomat.Helper;
namespace Matomat.Output
{
class LCDDisplay
{
private class Message
{
public string text;
public Status status;
public int time;
public Message(string text, Status status, int time)
{
this.text = text;
this.status = status;
this.time = time;
}
}
private class Beeb
{
public int frequency;
public int duration;
public Beeb(int frequency, int duration)
{
this.frequency = frequency;
this.duration = duration;
}
}
private static Dictionary<string,LCDDisplay> instances = new Dictionary<string,LCDDisplay>();
private Queue<Message> messages;
private Queue<Beeb> beeb;
private volatile bool _shouldStop;
private SerialPort serialPort;
private bool disable = false;
private LCDDisplay(string port)
{
this.serialPort = new SerialPort(port, 19200, Parity.None, 8, StopBits.One);
try
{
this.serialPort.Open();
}
catch (Exception)
{
this.disable = true;
}
this.createChars();
this.messages = new Queue<Message>();
new Thread(this.DisplayThread).Start();
this.beeb = new Queue<Beeb>();
new Thread(this.BeebThread).Start();
}
private void BeebThread()
{
Beeb b;
while (!_shouldStop)
{
Thread.Sleep(1);
if (this.beeb.Count != 0)
{
b = this.beeb.Dequeue();
Console.Beep(b.frequency, b.duration);
}
}
}
private void DisplayThread()
{
Message m;
DateTime timeout = new DateTime();
while (!_shouldStop)
{
Thread.Sleep(1);
if (messages.Count != 0)
{
if (timeout.Ticks < DateTime.Now.Ticks)
{
m = messages.Dequeue();
timeout = DateTime.Now.AddSeconds(m.time);
display(m.text, m.status);
}
}
}
}
private void beep(int frequency, int duration)
{
Beeb b = new Beeb(frequency, duration);
this.beeb.Enqueue(b);
}
private void display(string text, Status status)
{
if (status == Status.Warn)
{
this.beep(750, 750);
}
if (status == Status.Error)
{
this.beep(750, 500);
this.beep(37, 100);
this.beep(750, 500);
this.beep(37, 100);
this.beep(750, 500);
}
this.displayClear();
byte[] btext = text.ToCharArray("ÄÖÜäöüß²€µ", new byte[] { 0xE1, 0xEF, 0xF5, 0xE1, 0xEF, 0xF5, 0xE2, 0xFF, 0x80, 0x81 });
byte[] upper;
byte[] lower;
if (text.Length > 80)
{
upper = btext.Substring(0, 80);
lower = btext.Substring(80);
}
else
{
upper = btext;
lower = new byte[0];
}
this.displayEscCode("GTO0@");
this.displayCode(upper);
this.displayEscCode("GTO2@");
this.displayCode(lower);
text = text.PadRight(160, ' ');
text = text.Substring(0, 40) + "\n" + text.Substring(40, 40) + "\n" + text.Substring(80, 40) + "\n" + text.Substring(120, 40);
Console.WriteLine(text);
}
private void displayClear()
{
this.displayEscCode("GTO0@");
this.displayCode(new byte[] { 0x0c });
this.displayEscCode("GTO2@");
this.displayCode(new byte[] { 0x0c });
this.displayEscCode("GTO0@");
}
private void displayCode(byte[] p)
{
if (!disable)
{
this.serialPort.Write(p, 0, p.Length);
}
}
private void createChars()
{
this.displayEscCode("GTO0@");
this.specialChars();
this.displayEscCode("GTO2@");
this.specialChars();
}
private void specialChars()
{
this.displayEscCode("UDC0GH_H_HG@"); //[0, 0x80] Eurosymbol
this.displayEscCode("UDC1GGGGGGGG"); //[1, 0x81] Eurosymbol
this.displayEscCode("UDC2GH_H_HG@"); //[2] Eurosymbol
this.displayEscCode("UDC3GH_H_HG@"); //[3] Eurosymbol
}
private void displayEscCode(string code)
{
this.displayCode(new byte[] { 0x1b });
if (!disable)
{
this.serialPort.Write(code);
}
this.displayCode(new byte[] { 0x0d });
}
public enum Status
{
OK,
Warn,
Error
}
private void printb(string text, int time = 0, Status status = Status.OK)
{
string[] lines = text.Split('\n');
string line1 = "";
string line2 = "";
if (lines.Length == 1)
{
line1 = lines[0];
}
else
{
line1 = lines[0];
line2 = lines[1];
}
if(line1.Length > 38)
line1 = line1.Substring(0, 38);
double ll1 = ((38D - line1.Length) / 2);
line1 = line1.PadLeft((int)Math.Floor(ll1) + line1.Length, ' ');
line1 = line1.PadRight((int)Math.Ceiling(ll1) + line1.Length, ' ');
if (line2.Length > 38)
line2 = line2.Substring(0, 38);
double ll2 = ((38D - line2.Length) / 2);
line2 = line2.PadLeft((int)Math.Floor(ll2) + line2.Length, ' ');
line2 = line2.PadRight((int)Math.Ceiling(ll2) + line2.Length, ' ');
this.anzeige("²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²" +
"²" + line1 + "²" +
"²" + line2 + "²" +
"²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²", status, time);
}
/// <summary>
/// Prints a text on the display with the minimum duration of the time and beebcodes when status is not Status.OK
/// if the text is >= than 160 Chars it will display a border.
/// </summary>
/// <param name="text">Text to display. Break with \n, max length 38 chars each line</param>
/// <param name="time" value="0">Minimum duration of displaying the text</param>
/// <param name="status" value="Status.OK">Status code for that Item</param>
public void print(string text, int time = 0, Status status = Status.OK)
{
if (text.Length <= 80)
{
this.printb(text, time, status);
return;
}
this.anzeige(text, status, time);
}
private void anzeige(string text, Status status, int time)
{
Message m = new Message(text, status, time);
messages.Enqueue(m);
}
public static LCDDisplay getInstance(string port)
{
if (instances.Keys.Contains(port))
{
return instances[port];
}
instances.Add(port,new LCDDisplay(port));
return instances[port];
}
public void RequestStop()
{
while (messages.Count != 0) { Thread.Sleep(10); }
while (beeb.Count != 0) { Thread.Sleep(10); }
Thread.Sleep(100);
_shouldStop = true;
if (this.serialPort.IsOpen)
this.serialPort.Close();
}
}
}