begin rewriting libsharperang into libpaperang

This commit is contained in:
Maff 2019-09-12 00:10:28 +01:00
parent 09d9ccb628
commit 46012df5d5
11 changed files with 212 additions and 45 deletions

View File

@ -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<T>(IEnumerable<T> 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<T>(IEnumerable<T> data) => BitConverter.GetBytes(GetChecksumUint(data));
public uint GetCrcIv() => iv == mv
? iv
: iv ^ mv;
public byte[] GetCrcIvBytes() => BitConverter.GetBytes(GetCrcIv());
}
}

View File

@ -0,0 +1,5 @@

namespace libpaperang.Helpers {
class Media {
}
}

View File

@ -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;
}
}
}

60
libpaperang/IPrinter.cs Normal file
View File

@ -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();
}
}

23
libpaperang/USB.cs Normal file
View File

@ -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();
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibUsbDotNet" Version="2.2.29" />
</ItemGroup>
</Project>

View File

@ -8,7 +8,6 @@ namespace libsharperang {
Bluetooth Bluetooth
} }
internal DataTransforms transform=new DataTransforms(); internal DataTransforms transform=new DataTransforms();
//public Printer printer;
public string Model { get; internal set; } public string Model { get; internal set; }
public string FirmwareVer { get; internal set; } public string FirmwareVer { get; internal set; }
public int Battery { get; internal set; } public int Battery { get; internal set; }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using LibUsbDotNet; using LibUsbDotNet;
using LibUsbDotNet.Main; using LibUsbDotNet.Main;
@ -31,7 +32,7 @@ namespace libsharperang {
private byte[] ResolveOpcode(Opcode opcode) { private byte[] ResolveOpcode(Opcode opcode) {
switch (opcode) { switch (opcode) {
case Opcode.SessionBegin: return new byte[] { 0x06, 0x00, 0x02, 0x00 }; 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 }; case Opcode.CrcTransmit: return new byte[] { 0x18, 0x01, 0x04, 0x00 };
default: throw new NullReferenceException(); default: throw new NullReferenceException();
} }
@ -73,7 +74,7 @@ namespace libsharperang {
public USBPrinter() { public USBPrinter() {
ActiveConnectionType=ConnectionType.USB; ActiveConnectionType=ConnectionType.USB;
ImageWidth=48; ImageWidth=72;
} }
~USBPrinter() { ~USBPrinter() {
Close(); Close();
@ -156,15 +157,16 @@ namespace libsharperang {
} }
public void PollPrinter() { public void PollPrinter() {
StartSession(); StartSession();
NoOp(); NoOp();
} }
public void Feed() => Feed(100); 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 //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 NoOp() => Feed(0);
public void Feed(int milliseconds) => WriteBytes(builder.Build(Frame.Opcode.Feed, BitConverter.GetBytes(transform.SwapEndianness( public void Feed(int milliseconds) => WriteBytes(
0x00000000 | ((((( builder.Build(Frame.Opcode.Feed, BitConverter.GetBytes(
(uint)milliseconds & 0xFFU) << 16) | transform.SwapEndianness(0x00000000 | (((((
(uint)milliseconds) & 0xFFFF00U) >> 8))).Skip(2).ToArray())); (uint)milliseconds & 0xFFU) << 16) |
(uint)milliseconds) & 0xFFFF00U) >> 8))).Skip(2).ToArray()));
public void PrintBytes(byte[] data, bool autofeed=true) { public void PrintBytes(byte[] data, bool autofeed=true) {
List<byte[]> datas = data List<byte[]> datas = data
.Select((b, i) => new {Index = i, Value = b }) .Select((b, i) => new {Index = i, Value = b })
@ -172,7 +174,7 @@ namespace libsharperang {
.Select(b => b.Select(bb => bb.Value).ToArray()) .Select(b => b.Select(bb => bb.Value).ToArray())
.ToList(); .ToList();
datas.ForEach(b => WriteBytes(builder.Build(transform.GeneratePrintOpcode(b), b))); 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); public bool IsPrinterPresent() => (Devices != null && Devices.Count > 0);
bool IPrinter.Initialised() => Initialised(); bool IPrinter.Initialised() => Initialised();
@ -186,8 +188,13 @@ namespace libsharperang {
return bRead; return bRead;
} }
public bool WriteBytes(byte[] Frame) { 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); 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;
} }
} }
} }

View File

@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharperang", "sharperang\sharperang.csproj", "{677A8867-809E-4476-A9AE-7BEB5CE02F96}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharperang", "sharperang\sharperang.csproj", "{677A8867-809E-4476-A9AE-7BEB5CE02F96}"
EndProject 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution 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}.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.ActiveCfg = Release|Any CPU
{93203F87-29D0-4CDE-B2EE-156488E30186}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -8,9 +8,6 @@ using System.Drawing.Imaging;
using System.IO; using System.IO;
namespace sharperang { namespace sharperang {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window { public partial class MainWindow : Window {
private LogBridge logger; private LogBridge logger;
private USBPrinter printer=new USBPrinter(); private USBPrinter printer=new USBPrinter();
@ -26,7 +23,7 @@ namespace sharperang {
logger.ClearBuffer(); logger.ClearBuffer();
private void BtInitUSB_Click(object sender, RoutedEventArgs e) { private void BtInitUSB_Click(object sender, RoutedEventArgs e) {
logger.Info("USB Initialising"); logger.Info("USB Initialising");
printer.Initialise(); printer.Initialise();
//printer = new LibSharperang(logger); //printer = new LibSharperang(logger);
logger.Debug("IsPrinterPresent => "+printer.IsPrinterPresent()); logger.Debug("IsPrinterPresent => "+printer.IsPrinterPresent());
logger.Debug("FoundPrinterGuids => "+printer.FoundPrinterGuids()); logger.Debug("FoundPrinterGuids => "+printer.FoundPrinterGuids());
@ -37,30 +34,30 @@ namespace sharperang {
printer.InitPrinter(); printer.InitPrinter();
logger.Debug("Printer initialised and ready"); 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) { private void BtLoadImage_Click(object sender, RoutedEventArgs e) {
logger.Debug("Loading image for print"); logger.Debug("Loading image for print");
OpenFileDialog r = new OpenFileDialog { OpenFileDialog r = new OpenFileDialog {
Title="Select 1 (one) image file", Title="Select 1 (one) image file",
Multiselect=false, 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", 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 AutoUpgradeEnabled=true
}; };
if (r.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) { if (r.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) {
logger.Debug("Image load cancelled"); logger.Debug("Image load cancelled");
return; return;
} }
Image _=Image.FromFile(r.FileName); Image _=Image.FromFile(r.FileName);
logger.Debug("Loaded image " + r.FileName); logger.Debug("Loaded image " + r.FileName);
r.Dispose(); r.Dispose();
logger.Debug("Disposed of dialog"); logger.Debug("Disposed of dialog");
bimg=new Bitmap(_, bimg=new Bitmap(_,
(printer.ImageWidth*8), (int)((double)(printer.ImageWidth*8)*(double)((double)_.Height/(double)_.Width))); (printer.ImageWidth*8), (int)((double)(printer.ImageWidth*8)*(double)((double)_.Height/(double)_.Width)));
logger.Debug("Loaded image as Bitmap"); logger.Debug("Loaded image as Bitmap");
_.Dispose(); _.Dispose();
logger.Debug("Disposed of Image"); logger.Debug("Disposed of Image");
bimg=CopyToBpp(bimg); 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); //BitArray img = new BitArray(bimg.Height*96*8);
byte[] iimg = new byte[bimg.Height*printer.ImageWidth]; byte[] iimg = new byte[bimg.Height*printer.ImageWidth];
byte[] img; byte[] img;
@ -68,20 +65,20 @@ namespace sharperang {
bimg.Save(s, ImageFormat.Bmp); bimg.Save(s, ImageFormat.Bmp);
img=s.ToArray(); img=s.ToArray();
} }
logger.Debug("Got bitmap's bytes"); logger.Debug("Got bitmap's bytes");
int startoffset=img.Length-((bimg.Width/8)+(bimg.Height*printer.ImageWidth)); int startoffset=img.Length-(bimg.Height*printer.ImageWidth);
logger.Debug("Processing bytes with offset " + startoffset); logger.Debug("Processing bytes with offset " + startoffset);
for(int h=0;h<bimg.Height;h++) { for(int h=0;h<bimg.Height;h++) {
for (int w=0;w<printer.ImageWidth;w++) { for (int w=0;w<printer.ImageWidth;w++) {
iimg[(printer.ImageWidth*(bimg.Height-1-h))+(printer.ImageWidth-1-w)]=(byte)~ iimg[(printer.ImageWidth*(bimg.Height-1-h))+(printer.ImageWidth-1-w)]=(byte)~
(img[startoffset+(printer.ImageWidth*h)+(printer.ImageWidth-1-w)]); (img[startoffset+(printer.ImageWidth*h)+(printer.ImageWidth-1-w)]);
} }
} }
logger.Debug("Have print data of length " + iimg.Length); logger.Debug("Have print data of length " + iimg.Length);
bimg.Dispose(); bimg.Dispose();
logger.Debug("Disposed of Bitmap"); logger.Debug("Disposed of Bitmap");
printer.PrintBytes(iimg, false); printer.PrintBytes(iimg, false);
logger.Debug("Feeding for 200ms"); logger.Debug("Feeding for 200ms");
printer.Feed(200); printer.Feed(200);
} }
static uint BitSwap1(uint x) => ((x & 0x55555555u) << 1) | ((x & (~0x55555555u)) >> 1); static uint BitSwap1(uint x) => ((x & 0x55555555u) << 1) | ((x & (~0x55555555u)) >> 1);

View File

@ -50,12 +50,6 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="LibUsbDotNet.LibUsbDotNet, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c677239abe1e02a9, processorArchitecture=MSIL">
<HintPath>..\packages\LibUsbDotNet.2.2.29\lib\net45\LibUsbDotNet.LibUsbDotNet.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Collections.Specialized, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Collections.Specialized, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll</HintPath> <HintPath>..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll</HintPath>
@ -198,6 +192,7 @@
<ProjectReference Include="..\libsharperang\libsharperang.csproj"> <ProjectReference Include="..\libsharperang\libsharperang.csproj">
<Project>{93203f87-29d0-4cde-b2ee-156488e30186}</Project> <Project>{93203f87-29d0-4cde-b2ee-156488e30186}</Project>
<Name>libsharperang</Name> <Name>libsharperang</Name>
<EmbedInteropTypes>False</EmbedInteropTypes>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>