diff --git a/libpaperang/Helpers/CRC.cs b/libpaperang/Helpers/CRC.cs new file mode 100644 index 0000000..becad64 --- /dev/null +++ b/libpaperang/Helpers/CRC.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace libpaperang.Helpers { + public class CRC { + public uint iv { get => ~iv; private set => iv=~value; } + public uint mv = 0x35769521; + private uint poly = 0xedb88320; + private uint[] crctable; + public bool IsInitialised=false; + public CRC() { this.iv=0; } + public CRC(uint iv) => this.iv=iv; + public void Initialise() { + 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); + return e; + }).ToArray(); + IsInitialised=true; + } + public uint Reflect(uint iv) { + uint ivr=0; + for (int i = 0; i<32; i++) { + uint b=(iv>>i)&1; + ivr|=(b<<(31-i)); + } + return ~ivr; + } + public uint GetChecksumUint(IEnumerable data) { + if (!IsInitialised) throw new InvalidOperationException("CRC object has not been Initialise()'d first. Please do that."); + try { + return ~data.Aggregate(iv, + (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) { + throw new InvalidCastException("Could not read input as a byte stream", e); + } catch (OverflowException e) { + throw new OverflowException("Could not read input as a byte stream", e); + } + } + public byte[] GetChecksumBytes(IEnumerable data) => BitConverter.GetBytes(GetChecksumUint(data)); + public uint GetCrcIv() => iv == mv + ? iv + : iv ^ mv; + public byte[] GetCrcIvBytes() => BitConverter.GetBytes(GetCrcIv()); + } +} diff --git a/libpaperang/Helpers/Media.cs b/libpaperang/Helpers/Media.cs new file mode 100644 index 0000000..f6c7cb2 --- /dev/null +++ b/libpaperang/Helpers/Media.cs @@ -0,0 +1,5 @@ + +namespace libpaperang.Helpers { + class Media { + } +} diff --git a/libpaperang/Helpers/Transforms.cs b/libpaperang/Helpers/Transforms.cs new file mode 100644 index 0000000..0ca4233 --- /dev/null +++ b/libpaperang/Helpers/Transforms.cs @@ -0,0 +1,12 @@ + +namespace libpaperang.Helpers { + class Transforms { + public BaseTypes.Packet Frame; + public BaseTypes.Opcodes Op; + public Transforms(BaseTypes.Packet FrameConstruction, BaseTypes.Opcodes Operations) { + Frame=FrameConstruction; + Op=Operations; + } + + } +} diff --git a/libpaperang/IPrinter.cs b/libpaperang/IPrinter.cs new file mode 100644 index 0000000..6caa9cf --- /dev/null +++ b/libpaperang/IPrinter.cs @@ -0,0 +1,60 @@ + + +namespace libpaperang { + public abstract class BaseTypes { + public enum Connection { + None, + UART, + USB, + Bluetooth + } + public struct Packet { + byte Start; + byte End; + } + public enum Model { + P1, + T1, + P2, + P2S + } + public enum State { + Offline, + Available, + Ready, + NotReady, + Printing, + } + public enum Fault { + PaperEmpty, + DoorOpen + } + public enum Operations { + NoOp, + LineFeed, + CrcTransmit, + Print + } + public struct Opcodes { + byte[] NoOp; + byte[] LineFeed; + byte[] Print; + byte[] TransmitCrc; + } + } + interface IPrinter { + short LineWidth { get; } + BaseTypes.Connection ConnectionMethod { get; } + BaseTypes.Model PrinterVariant { get; } + BaseTypes.State Status { get; } + bool IsPrinterAvailable(); + bool IsPrinterInitialised(); + bool Initialise(); + bool OpenPrinter(); + bool ClosePrinter(); + bool Deinitialise(); + bool WriteBytes(byte[] packet); + bool WriteBytes(byte[] packet, int delay); + bool[] ReadBytes(); + } +} diff --git a/libpaperang/USB.cs b/libpaperang/USB.cs new file mode 100644 index 0000000..93f6b69 --- /dev/null +++ b/libpaperang/USB.cs @@ -0,0 +1,23 @@ +using System; + +namespace libpaperang { + public class USB : IPrinter { + public short LineWidth => throw new NotImplementedException(); + + public BaseTypes.Connection ConnectionMethod => throw new NotImplementedException(); + + public BaseTypes.Model PrinterVariant => throw new NotImplementedException(); + + public BaseTypes.State Status => throw new NotImplementedException(); + + public bool ClosePrinter() => throw new NotImplementedException(); + public bool Deinitialise() => throw new NotImplementedException(); + public bool Initialise() => throw new NotImplementedException(); + public bool IsPrinterAvailable() => throw new NotImplementedException(); + public bool IsPrinterInitialised() => throw new NotImplementedException(); + public bool OpenPrinter() => throw new NotImplementedException(); + public bool[] ReadBytes() => throw new NotImplementedException(); + public bool WriteBytes(byte[] packet) => throw new NotImplementedException(); + public bool WriteBytes(byte[] packet, int delay) => throw new NotImplementedException(); + } +} diff --git a/libpaperang/libpaperang.csproj b/libpaperang/libpaperang.csproj new file mode 100644 index 0000000..1a97df7 --- /dev/null +++ b/libpaperang/libpaperang.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/libsharperang/Base.cs b/libsharperang/Base.cs index f493eab..2c5d0cb 100644 --- a/libsharperang/Base.cs +++ b/libsharperang/Base.cs @@ -8,7 +8,6 @@ namespace libsharperang { Bluetooth } internal DataTransforms transform=new DataTransforms(); - //public Printer printer; public string Model { get; internal set; } public string FirmwareVer { get; internal set; } public int Battery { get; internal set; } diff --git a/libsharperang/usb.cs b/libsharperang/usb.cs index e05d044..7a6787d 100644 --- a/libsharperang/usb.cs +++ b/libsharperang/usb.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using LibUsbDotNet; using LibUsbDotNet.Main; @@ -31,7 +32,7 @@ namespace libsharperang { private byte[] ResolveOpcode(Opcode opcode) { switch (opcode) { case Opcode.SessionBegin: return new byte[] { 0x06, 0x00, 0x02, 0x00 }; - case Opcode.Feed: return new byte[] { 0x1a, 0x00, 0x02, 0x00 }; + case Opcode.Feed: return new byte[] { 0x1a, 0x00, 0x02, 0x00 }; case Opcode.CrcTransmit: return new byte[] { 0x18, 0x01, 0x04, 0x00 }; default: throw new NullReferenceException(); } @@ -73,7 +74,7 @@ namespace libsharperang { public USBPrinter() { ActiveConnectionType=ConnectionType.USB; - ImageWidth=48; + ImageWidth=72; } ~USBPrinter() { Close(); @@ -156,15 +157,16 @@ namespace libsharperang { } public void PollPrinter() { StartSession(); - NoOp(); + NoOp(); } - public void Feed() => Feed(100); - //Feed 0 is equivalent to a no-op, though on the P2 model it appears to engage the roller even though it doesn't ultimately result in any rotation - public void NoOp() => Feed(0); - public void Feed(int milliseconds) => WriteBytes(builder.Build(Frame.Opcode.Feed, BitConverter.GetBytes(transform.SwapEndianness( - 0x00000000 | ((((( - (uint)milliseconds & 0xFFU) << 16) | - (uint)milliseconds) & 0xFFFF00U) >> 8))).Skip(2).ToArray())); + public void Feed() => Feed(100); + //Feed 0 is equivalent to a no-op, though on the P2 model it appears to engage the roller even though it doesn't ultimately result in any rotation + public void NoOp() => Feed(0); + public void Feed(int milliseconds) => WriteBytes( + builder.Build(Frame.Opcode.Feed, BitConverter.GetBytes( + transform.SwapEndianness(0x00000000 | ((((( + (uint)milliseconds & 0xFFU) << 16) | + (uint)milliseconds) & 0xFFFF00U) >> 8))).Skip(2).ToArray())); public void PrintBytes(byte[] data, bool autofeed=true) { List datas = data .Select((b, i) => new {Index = i, Value = b }) @@ -172,7 +174,7 @@ namespace libsharperang { .Select(b => b.Select(bb => bb.Value).ToArray()) .ToList(); datas.ForEach(b => WriteBytes(builder.Build(transform.GeneratePrintOpcode(b), b))); - if (autofeed) Feed(60); + if (autofeed) Feed(200); } public bool IsPrinterPresent() => (Devices != null && Devices.Count > 0); bool IPrinter.Initialised() => Initialised(); @@ -186,8 +188,13 @@ namespace libsharperang { return bRead; } public bool WriteBytes(byte[] Frame) { + return WriteBytes(Frame, ImageWidth*3); + } + public bool WriteBytes(byte[] Frame, int milliseconds) { if (_uWr==null) _uWr=_uDv?.OpenEndpointWriter(WriteEndpointID.Ep02); - return (_uWr.Write(Frame, 1000, out int _) == ErrorCode.None); + bool result = _uWr.Write(Frame, 500, out int _) == ErrorCode.None; + Thread.Sleep(milliseconds); + return result; } } } \ No newline at end of file diff --git a/sharperang.sln b/sharperang.sln index b44a1e9..dbd84cb 100644 --- a/sharperang.sln +++ b/sharperang.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.29215.179 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharperang", "sharperang\sharperang.csproj", "{677A8867-809E-4476-A9AE-7BEB5CE02F96}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libsharperang", "libsharperang\libsharperang.csproj", "{93203F87-29D0-4CDE-B2EE-156488E30186}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "libsharperang", "libsharperang\libsharperang.csproj", "{93203F87-29D0-4CDE-B2EE-156488E30186}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libpaperang", "libpaperang\libpaperang.csproj", "{A429CCEB-9331-4CD9-B3C0-A8F736732DEA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {93203F87-29D0-4CDE-B2EE-156488E30186}.Debug|Any CPU.Build.0 = Debug|Any CPU {93203F87-29D0-4CDE-B2EE-156488E30186}.Release|Any CPU.ActiveCfg = Release|Any CPU {93203F87-29D0-4CDE-B2EE-156488E30186}.Release|Any CPU.Build.0 = Release|Any CPU + {A429CCEB-9331-4CD9-B3C0-A8F736732DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A429CCEB-9331-4CD9-B3C0-A8F736732DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A429CCEB-9331-4CD9-B3C0-A8F736732DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A429CCEB-9331-4CD9-B3C0-A8F736732DEA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sharperang/MainWindow.xaml.cs b/sharperang/MainWindow.xaml.cs index 817c46c..d33a1d6 100644 --- a/sharperang/MainWindow.xaml.cs +++ b/sharperang/MainWindow.xaml.cs @@ -8,9 +8,6 @@ using System.Drawing.Imaging; using System.IO; namespace sharperang { - /// - /// Interaction logic for MainWindow.xaml - /// public partial class MainWindow : Window { private LogBridge logger; private USBPrinter printer=new USBPrinter(); @@ -26,7 +23,7 @@ namespace sharperang { logger.ClearBuffer(); private void BtInitUSB_Click(object sender, RoutedEventArgs e) { logger.Info("USB Initialising"); - printer.Initialise(); + printer.Initialise(); //printer = new LibSharperang(logger); logger.Debug("IsPrinterPresent => "+printer.IsPrinterPresent()); logger.Debug("FoundPrinterGuids => "+printer.FoundPrinterGuids()); @@ -37,30 +34,30 @@ namespace sharperang { printer.InitPrinter(); logger.Debug("Printer initialised and ready"); } - private void BtTestLine_Click(object sender, RoutedEventArgs e) => printer.Feed(200); + private void BtTestLine_Click(object sender, RoutedEventArgs e) => printer.Feed(200); private void BtLoadImage_Click(object sender, RoutedEventArgs e) { - logger.Debug("Loading image for print"); + logger.Debug("Loading image for print"); OpenFileDialog r = new OpenFileDialog { Title="Select 1 (one) image file", Multiselect=false, Filter="PNG files (*.png)|*.png|JPEG files (*.jpe?g)|*.jpg *.jpeg|Jraphics Interchange Format files (*.gif)|*.gif|Bitte-Mappe files (*.bmp)|*.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"); - return; - } + if (r.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) { + logger.Debug("Image load cancelled"); + return; + } Image _=Image.FromFile(r.FileName); - logger.Debug("Loaded image " + r.FileName); - r.Dispose(); - logger.Debug("Disposed of dialog"); + logger.Debug("Loaded image " + r.FileName); + r.Dispose(); + logger.Debug("Disposed of dialog"); bimg=new Bitmap(_, (printer.ImageWidth*8), (int)((double)(printer.ImageWidth*8)*(double)((double)_.Height/(double)_.Width))); - logger.Debug("Loaded image as Bitmap"); - _.Dispose(); - logger.Debug("Disposed of Image"); + logger.Debug("Loaded image as Bitmap"); + _.Dispose(); + logger.Debug("Disposed of Image"); bimg=CopyToBpp(bimg); - logger.Debug("Converted Bitmap to Bitmap with 1-bit colour depth"); + logger.Debug("Converted Bitmap to Bitmap with 1-bit colour depth"); //BitArray img = new BitArray(bimg.Height*96*8); byte[] iimg = new byte[bimg.Height*printer.ImageWidth]; byte[] img; @@ -68,20 +65,20 @@ namespace sharperang { bimg.Save(s, ImageFormat.Bmp); img=s.ToArray(); } - logger.Debug("Got bitmap's bytes"); - int startoffset=img.Length-((bimg.Width/8)+(bimg.Height*printer.ImageWidth)); - logger.Debug("Processing bytes with offset " + startoffset); + logger.Debug("Got bitmap's bytes"); + int startoffset=img.Length-(bimg.Height*printer.ImageWidth); + logger.Debug("Processing bytes with offset " + startoffset); for(int h=0;h ((x & 0x55555555u) << 1) | ((x & (~0x55555555u)) >> 1); diff --git a/sharperang/sharperang.csproj b/sharperang/sharperang.csproj index 5c295e5..3077dc0 100644 --- a/sharperang/sharperang.csproj +++ b/sharperang/sharperang.csproj @@ -50,12 +50,6 @@ 4 - - ..\packages\LibUsbDotNet.2.2.29\lib\net45\LibUsbDotNet.LibUsbDotNet.dll - - - ..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll - ..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll @@ -198,6 +192,7 @@ {93203f87-29d0-4cde-b2ee-156488e30186} libsharperang + False