some changes

This commit is contained in:
Maff 2019-10-04 11:18:17 +01:00
parent 734ebf47e1
commit 471c9e5165
9 changed files with 150 additions and 126 deletions

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace liblogtiny {
namespace liblogtiny {
public partial class LogTiny {
public enum LogLevel {
Trace,

View File

@ -5,55 +5,57 @@ using System.Linq;
namespace libpaperang.Helpers {
public class CRC {
private uint _iv;
public uint iv { get => ~_iv; private set => _iv=~value; }
public uint mv = 0x35769521;
public uint Iv { get => ~_iv; private set => _iv = ~value; }
public uint Mv => 0x35769521u;
private uint poly = 0xedb88320;
private uint[] crctable;
public bool IsInitialised=false;
public CRC(bool autoinit = true) {
iv = 0;
if(autoinit) Initialise();
Iv = 0;
if(autoinit)
Initialise();
}
public CRC(uint iv, bool autoinit = true) {
this.iv = iv;
if (autoinit) Initialise();
Iv = iv;
if(autoinit)
Initialise();
}
public void Initialise() {
crctable=Enumerable.Range(0, 256).Select(i => {
crctable = Enumerable.Range(0, 256).Select(i => {
uint e=(uint)i;
for (ushort eb = 0; eb<8; eb++)
e=((e&1)!=0)
? (poly^(e>>1))
: (e>>1);
for(ushort eb = 0; eb < 8; eb++) {
e = ((e & 1) != 0)
? (poly ^ (e >> 1))
: (e >> 1);
}
return e;
}).ToArray();
IsInitialised=true;
IsInitialised = true;
}
public uint Reflect(uint iv) {
uint ivr=0;
for (int i = 0; i<32; i++) {
for(int i = 0; i < 32; i++) {
uint b=(iv>>i)&1;
ivr|=(b<<(31-i));
ivr |= b << (31 - i);
}
return ~ivr;
}
public uint GetChecksumUint<T>(IEnumerable<T> data) {
if (!IsInitialised) throw new CrcNotAvailableException();
if(!IsInitialised)
throw new CrcNotAvailableException();
try {
return ~data.Aggregate(_iv,
(cti, cb) => crctable[(cti&0xFF)^Convert.ToByte(cb)]^(cti>>8));
} catch (FormatException e) {
(cti, cb) => crctable[(cti & 0xFF) ^ Convert.ToByte(cb)] ^ (cti >> 8));
} catch(FormatException e) {
throw new FormatException("Could not read input as a byte stream", e);
} catch (InvalidCastException e) {
} catch(InvalidCastException e) {
throw new InvalidCastException("Could not read input as a byte stream", e);
} catch (OverflowException e) {
} catch(OverflowException e) {
throw new OverflowException("Could not read input as a byte stream", e);
}
}
public byte[] GetChecksumBytes<T>(IEnumerable<T> data) => BitConverter.GetBytes(GetChecksumUint(data));
public uint GetCrcIv() => iv == mv
? iv
: iv ^ mv;
public uint GetCrcIv() => Iv == Mv ? Iv : Iv ^ Mv;
public byte[] GetCrcIvBytes() => BitConverter.GetBytes(GetCrcIv());
}
}

View File

@ -1,5 +0,0 @@

namespace libpaperang.Helpers {
class Media {
}
}

View File

@ -7,23 +7,29 @@ namespace libpaperang.Helpers {
public BaseTypes.Opcodes Op;
public short OpLen;
public Transforms(BaseTypes.Packet FrameConstruction, BaseTypes.Opcodes Operations, short OperLen) {
Frame=FrameConstruction;
Op=Operations;
OpLen=OperLen;
Frame = FrameConstruction;
Op = Operations;
OpLen = OperLen;
}
public byte[] Oper(BaseTypes.Operations Operation) {
switch (Operation) {
case BaseTypes.Operations.NoOp: return Op.NoOp;
case BaseTypes.Operations.LineFeed: return Op.LineFeed;
case BaseTypes.Operations.CrcTransmit: return Op.TransmitCrc;
case BaseTypes.Operations.Print: return Op.Print;
default: throw new InvalidOperationException();
switch(Operation) {
case BaseTypes.Operations.NoOp:
return Op.NoOp;
case BaseTypes.Operations.LineFeed:
return Op.LineFeed;
case BaseTypes.Operations.CrcTransmit:
return Op.TransmitCrc;
case BaseTypes.Operations.Print:
return Op.Print;
default:
throw new InvalidOperationException();
}
}
public byte[] Arg(BaseTypes.Operations Operation, uint Data) {
switch(Operation) {
case BaseTypes.Operations.LineFeed: return BitConverter.GetBytes(SwapWordEndianness(
0x00000000 | (((((
case BaseTypes.Operations.LineFeed:
return BitConverter.GetBytes(SwapWordEndianness(
0x00000000 | (((((
Data & 0xffu) << 16) |
Data) & 0xffff00u) >> 8))).Skip(2).ToArray();
case BaseTypes.Operations.Print:
@ -31,17 +37,18 @@ namespace libpaperang.Helpers {
0x00010000 | (((((
Data & 0xffu) << 16) |
Data) & 0xffff00u) >> 8)));
default: throw new InvalidOperationException();
default:
throw new InvalidOperationException();
}
}
public byte[] Packet(byte[] oper, byte[] data, CRC checksum) {
byte[] packet = new byte[1+oper.Length+data.Length+5];
packet[0] = Frame.Start;
packet[packet.Length-1] = Frame.End;
packet[packet.Length - 1] = Frame.End;
Buffer.BlockCopy(oper,
0, packet, 1, oper.Length);
Buffer.BlockCopy(data,
0, packet, oper.Length+1, data.Length);
0, packet, oper.Length + 1, data.Length);
Buffer.BlockCopy(checksum.GetChecksumBytes(data),
0, packet, packet.Length - 5, 4);
return packet;
@ -54,7 +61,7 @@ namespace libpaperang.Helpers {
return p;
}
public uint SwapWordEndianness(uint value) => (
(value & 0x000000ffu) << 24)|
(value & 0x000000ffu) << 24) |
((value & 0x0000ff00u) << 8) |
((value & 0x00ff0000u) >> 8) |
((value & 0xff000000u) >> 24);

View File

@ -55,6 +55,8 @@ namespace libpaperang {
}
public interface IPrinter {
short LineWidth { get; }
short BasePrintDelay { get; }
uint MaximumDataSize { get; }
BaseTypes.Connection ConnectionMethod { get; }
BaseTypes.Model PrinterVariant { get; }
BaseTypes.State Status { get; }

View File

@ -10,7 +10,7 @@ namespace libpaperang.Interfaces {
// constants
private const ushort iV = 0x4348;
private const ushort iP = 0x5584;
private const short MaxDataSize = 1008;
public uint MaximumDataSize => 1008;
// types
private struct UsbComms {
@ -20,21 +20,35 @@ namespace libpaperang.Interfaces {
public UsbEndpointWriter tx;
}
private UsbComms Printer;
private BaseTypes.Model iModel;
private bool _initialised=false;
public short LineWidth {
get {
switch (iModel) {
case BaseTypes.Model.P1: return 48;
case BaseTypes.Model.P2: return 72;
case BaseTypes.Model.P2S: return 72; //assumption
case BaseTypes.Model.T1: throw new PrinterVariantNotSupportedException();
default: throw new InvalidOperationException();
switch(PrinterVariant) {
case BaseTypes.Model.P1:
return 48;
case BaseTypes.Model.P2:
return 72;
case BaseTypes.Model.T1:
throw new PrinterVariantNotSupportedException();
default:
throw new InvalidOperationException();
}
}
}
public short BasePrintDelay {
get {
switch(PrinterVariant) {
case BaseTypes.Model.P1:
return 80;
case BaseTypes.Model.P2:
return 140;
default:
throw new InvalidOperationException();
}
}
}
public BaseTypes.Connection ConnectionMethod => BaseTypes.Connection.USB;
public BaseTypes.Model PrinterVariant => iModel;
public BaseTypes.Model PrinterVariant { get; private set; }
public BaseTypes.State Status => BaseTypes.State.Offline;
public List<BaseTypes.Printer> AvailablePrinters {
get {
@ -52,33 +66,36 @@ namespace libpaperang.Interfaces {
}
}
public bool PrinterAvailable => AvailablePrinters.Count > 0;
public bool PrinterInitialised => _initialised;
public bool PrinterInitialised { get; private set; } = false;
public bool PrinterOpen => Printer.handle?.IsOpen ?? false;
public void OpenPrinter(BaseTypes.Printer printer) {
bool res;
try {
res = ((UsbRegistry)printer.Instance).Open(out Printer.handle);
} catch(Exception) {
throw new PrinterNotAvailableException();
}
if(!res)
throw new PrinterNotAvailableException();
}
public void ClosePrinter() => Printer.handle?.Close();
public void Initialise() {
if(!PrinterOpen)
throw new PrinterNotInitialisedException();
//WinUSB-specific
Printer.iface = Printer.handle as IUsbDevice;
_ = Printer.iface?.SetConfiguration(1);
_ = Printer.iface?.ClaimInterface(0);
Printer.rx = Printer.handle.OpenEndpointReader(ReadEndpointID.Ep01);
Printer.tx = Printer.handle.OpenEndpointWriter(WriteEndpointID.Ep02);
PrinterInitialised = true;
}
public void Deinitialise() {
Printer.rx?.Dispose();
Printer.tx?.Dispose();
_ = Printer.iface?.ReleaseInterface(0);
_ = Printer.iface?.Close();
}
public void Initialise() {
if (!PrinterOpen) throw new PrinterNotInitialisedException();
//WinUSB-specific
Printer.iface=Printer.handle as IUsbDevice;
_=Printer.iface?.SetConfiguration(1);
_=Printer.iface?.ClaimInterface(0);
Printer.rx=Printer.handle.OpenEndpointReader(ReadEndpointID.Ep01);
Printer.tx=Printer.handle.OpenEndpointWriter(WriteEndpointID.Ep02);
_initialised = true;
}
public void OpenPrinter(BaseTypes.Printer printer) {
bool res;
try {
res=((UsbRegistry)printer.Instance).Open(out Printer.handle);
} catch (Exception) {
throw new PrinterNotAvailableException();
}
if (!res) throw new PrinterNotAvailableException();
ClosePrinter();
}
public byte[] ReadBytes() {
byte[] readbuf=new byte[1024];
@ -91,6 +108,6 @@ namespace libpaperang.Interfaces {
Thread.Sleep(delay);
return _;
}
public USB(BaseTypes.Model model) => iModel=model;
public USB(BaseTypes.Model model) => PrinterVariant = model;
}
}

View File

@ -1,8 +1,8 @@
using libpaperang.Helpers;
using libpaperang.Interfaces;
using liblogtiny;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using liblogtiny;
using libpaperang.Helpers;
using libpaperang.Interfaces;
namespace libpaperang.Main {
public class Paperang {
@ -75,7 +75,7 @@ namespace libpaperang.Main {
logger?.Trace($"PrintBytes() invoked with data length of {data.Length}");
List<byte[]> segments = data
.Select((b,i) => new {Index=i,Value=b })
.GroupBy(b=>b.Index/1008)
.GroupBy(b=>b.Index/Printer.MaximumDataSize)
.Select(b=>b.Select(bb=>bb.Value).ToArray())
.ToList();
logger?.Trace($"data split into {segments.Count} segment(s)");
@ -84,7 +84,9 @@ namespace libpaperang.Main {
Transform.Arg(BaseTypes.Operations.Print, (uint)b.Length),
b,
Crc),
200-(b.Length/Printer.LineWidth)));
Printer.BasePrintDelay + (b.Length / Printer.LineWidth)));
if(autofeed)
Feed(185);
}
}
}

View File

@ -1,5 +1,5 @@
using liblogtiny;
using System.ComponentModel;
using System.ComponentModel;
using liblogtiny;
namespace paperangapp {
class LUITextbox : ILogTiny, INotifyPropertyChanged {
@ -11,13 +11,13 @@ namespace paperangapp {
//get { return _LogBuffer; }
get => _LogBuffer;
set {
if (value == _LogBuffer) return;
if (value == "!clearlog") _LogBuffer = "";
else _LogBuffer = value + "\n" + _LogBuffer;
if(value == _LogBuffer)
return;
_LogBuffer = value == "!clearlog" ? "" : value + "\n" + _LogBuffer;
OnPropertyChanged("LogBuffer");
}
}
public void ClearBuffer() => LogBuffer="!clearlog";
public void ClearBuffer() => LogBuffer = "!clearlog";
public void Trace(string msg) => Log(LogTiny.LogLevel.Trace, msg);
public void Debug(string msg) => Log(LogTiny.LogLevel.Debug, msg);
public void Verbose(string msg) => Log(LogTiny.LogLevel.Verbose, msg);
@ -25,7 +25,7 @@ namespace paperangapp {
public void Warn(string msg) => Log(LogTiny.LogLevel.Warn, msg);
public void Error(string msg) => Log(LogTiny.LogLevel.Error, msg);
public void Critical(string msg) => Log(LogTiny.LogLevel.Critical, msg);
public void Log(LogTiny.LogLevel level, string msg) => LogBuffer=$"{level}: {msg}";
public void Raw(string msg) => LogBuffer=msg;
public void Log(LogTiny.LogLevel level, string msg) => LogBuffer = $"{level}: {msg}";
public void Raw(string msg) => LogBuffer = msg;
}
}

View File

@ -1,15 +1,14 @@
using liblogtiny;
using libpaperang;
using libpaperang.Interfaces;
using libpaperang.Main;
using System;
using System.Timers;
using System.Windows;
using System.Windows.Forms;
//testing
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Timers;
using System.Windows;
using System.Windows.Forms;
using liblogtiny;
using libpaperang;
using libpaperang.Interfaces;
using libpaperang.Main;
namespace paperangapp {
public partial class MainWindow : Window {
@ -25,7 +24,7 @@ namespace paperangapp {
UnInitDev,
InitDev
};
private AppState state=AppState.UnInitNoDev;
private AppState state=AppState.UnInitDev;
// TODO: is it out of scope for this library to provide functionality for printing bitmap data?
public MainWindow() {
InitializeComponent();
@ -35,14 +34,14 @@ namespace paperangapp {
usbpoll = new System.Timers.Timer(200) {
AutoReset = true
};
usbpoll.Elapsed += evtUsbPoll;
usbpoll.Elapsed += EvtUsbPoll;
usbpoll.Start();
logger.Verbose("USB presence interval event started");
}
private void evtUsbPoll(object sender, ElapsedEventArgs e) =>_ = Dispatcher.BeginInvoke(new invDgtUsbPoll(dgtUsbPoll));
private void EvtUsbPoll(object sender, ElapsedEventArgs e) => _ = Dispatcher.BeginInvoke(new invDgtUsbPoll(DgtUsbPoll));
private delegate void invDgtUsbPoll();
private void dgtUsbPoll() {
private void DgtUsbPoll() {
try {
if(state == AppState.UnInitNoDev && prtr.PrinterAvailable) {
btInitUSB.IsEnabled = true;
@ -63,7 +62,8 @@ namespace paperangapp {
~MainWindow() {
logger.Warn("Application closing");
if(mmj!=null) USBDeInit();
if(mmj != null)
USBDeInit();
}
private void BtClearLog_Click(object sender, RoutedEventArgs e) =>
logger.Raw("!clearlog");
@ -115,9 +115,14 @@ namespace paperangapp {
}
private void BtFeed_Click(object sender, RoutedEventArgs e) => mmj.Feed((uint)slFeedTime.Value);
private void BtPrintText_Click(object sender, RoutedEventArgs e) {
if(!(txInput.Text.Length > 0)) {
logger.Warn("PrintText event but nothing to print.");
return;
}
Font fnt=new Font(txFont.Text, int.Parse(txSzF.Text));
Graphics g=Graphics.FromImage(new Bitmap(mmj.Printer.LineWidth*8, 1));
SizeF szText=g.MeasureString(txInput.Text, fnt);
System.Drawing.Size szText = TextRenderer.MeasureText(g, txInput.Text, fnt);
//SizeF szText=g.MeasureString(txInput.Text, fnt);
g.Dispose();
Bitmap b=new Bitmap(mmj.Printer.LineWidth*8, (int)szText.Height);
g = Graphics.FromImage(b);
@ -125,34 +130,37 @@ namespace paperangapp {
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.DrawString(txInput.Text, fnt, Brushes.Black, new PointF(0,0));
TextRenderer.DrawText(g, txInput.Text, fnt, new System.Drawing.Point(0, 0), Color.Black);
g.Flush();
PrintBitmap(b);
g.Dispose();
b.Dispose();
}
private void BtPrintImage_Click(object sender, RoutedEventArgs e) {
logger.Debug("Loading image for print");
logger.Debug("Invoking file selection dialogue.");
OpenFileDialog r = new OpenFileDialog {
Title="Select 1 (one) image file",
Multiselect=false,
Filter="PNG files|*.png|JPEG files|*.jpg;*.jpeg|Jraphics Interchange Format files|*.gif|Bitte-Mappe files|*.bmp|All of the above|*.jpg;*.jpeg;*.png;*.gif;*.bmp",
AutoUpgradeEnabled=true
};
if (r.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) {
logger.Debug("Image load cancelled");
if(r.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) {
logger.Warn("PrintImage event but no file was selected.");
r.Dispose();
return;
}
logger.Debug("Loading image for print");
Image _=Image.FromFile(r.FileName);
logger.Debug("Loaded image " + r.FileName);
r.Dispose();
logger.Debug("Disposed of dialog");
Bitmap bimg=new Bitmap(_, (mmj.Printer.LineWidth*8),
(int)((double)(mmj.Printer.LineWidth*8)*(double)((double)_.Height/(double)_.Width)));
Bitmap bimg=new Bitmap(_, mmj.Printer.LineWidth*8,
(int)(mmj.Printer.LineWidth*8*(double)((double)_.Height/(double)_.Width)));
logger.Debug("Loaded image as Bitmap");
_.Dispose();
logger.Debug("Disposed of Image");
PrintBitmap(bimg);
bimg.Dispose();
}
private void PrintBitmap(Bitmap bimg) {
bimg = CopyToBpp(bimg);
@ -172,17 +180,12 @@ namespace paperangapp {
for(int h = 0; h < hSzImg; h++) {
for(int w = 0; w < mmj.Printer.LineWidth; w++) {
iimg[(mmj.Printer.LineWidth * (hSzImg - 1 - h)) + (mmj.Printer.LineWidth - 1 - w)] = (byte)~
(img[startoffset + (mmj.Printer.LineWidth * h) + (mmj.Printer.LineWidth - 1 - w)]);
img[startoffset + (mmj.Printer.LineWidth * h) + (mmj.Printer.LineWidth - 1 - w)];
}
}
logger.Debug($"Have {img.Length} bytes of print data ({mmj.Printer.LineWidth*8}x{hSzImg}@1bpp)");
logger.Debug($"Have {img.Length} bytes of print data ({mmj.Printer.LineWidth * 8}x{hSzImg}@1bpp)");
mmj.PrintBytes(iimg, false);
//mmj.Feed(175);
}
static uint BitSwap1(uint x) => ((x & 0x55555555u) << 1) | ((x & (~0x55555555u)) >> 1);
static uint BitSwap2(uint x) => ((x & 0x33333333u) << 2) | ((x & (~0x33333333u)) >> 2);
static uint BitSwap4(uint x) => ((x & 0x0f0f0f0fu) << 4) | ((x & (~0x0f0f0f0fu)) >> 4);
static uint BitSwap(uint x) => BitSwap4(BitSwap2(BitSwap1(x)));
#region GDIBitmap1bpp
static Bitmap CopyToBpp(Bitmap b) {
int w=b.Width, h=b.Height;
@ -198,11 +201,11 @@ namespace paperangapp {
biXPelsPerMeter=1000000,
biYPelsPerMeter=1000000
};
bmi.biClrUsed=2;
bmi.biClrImportant=2;
bmi.cols=new uint[256];
bmi.cols[0]=MAKERGB(0, 0, 0);
bmi.cols[1]=MAKERGB(255, 255, 255);
bmi.biClrUsed = 2;
bmi.biClrImportant = 2;
bmi.cols = new uint[256];
bmi.cols[0] = MAKERGB(0, 0, 0);
bmi.cols[1] = MAKERGB(255, 255, 255);
IntPtr hbm0 = CreateDIBSection(IntPtr.Zero,ref bmi,DIB_RGB_COLORS,out _,IntPtr.Zero,0);
IntPtr sdc = GetDC(IntPtr.Zero);
IntPtr hdc = CreateCompatibleDC(sdc);
@ -248,7 +251,7 @@ namespace paperangapp {
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=256)]
public uint[] cols;
}
static uint MAKERGB(int r, int g, int b) => ((uint)(b&255)) | ((uint)((r&255)<<8)) | ((uint)((g&255)<<16));
static uint MAKERGB(int r, int g, int b) => ((uint)(b & 255)) | ((uint)((r & 255) << 8)) | ((uint)((g & 255) << 16));
#endregion
}
}