feat(*): inkless app for the mxw01 thermal printer

This commit is contained in:
hh committed 2026-09-19 23:28:18 +02:00
commit 0c36cc115e
50 files changed
+4028

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
import Foundation
@testable import Inkless
import Testing
struct ImagingTests {
@Test func packsLeftmostDotIntoLowestBit() {
var dots = [UInt8](repeating: 0, count: 16)
dots[0] = 1
dots[9] = 1
let bitmap = DotBitmap(width: 16, height: 1, dots: dots)
#expect([UInt8](bitmap.packedRows()) == [0b0000_0001, 0b0000_0010])
}
@Test func packsGrayAsInvertedNibblesHighFirst() {
let bitmap = GrayBitmap(width: 4, height: 1, luma: [255, 0, 128, 16])
#expect([UInt8](bitmap.packedNibbles()) == [0x0F, 0x7E])
}
@Test func padsShortJobsWithPaper() {
let raster = PrintRaster.dots(.blank(rows: 10)).padded(toMinimumHeight: 90)
#expect(raster.height == 90)
#expect(raster.blackRatio == 0)
}
@Test(arguments: DitherAlgorithm.allCases)
func ditherKeepsExtremesAndAverageTone(algorithm: DitherAlgorithm) {
let side = 64
let white = algorithm.apply(to: .init(repeating: 1, count: side * side), width: side, height: side)
let black = algorithm.apply(to: .init(repeating: 0, count: side * side), width: side, height: side)
#expect(white.allSatisfy { $0 == 0 })
#expect(black.allSatisfy { $0 == 1 })
guard algorithm != .threshold else { return }
let grey = algorithm.apply(to: .init(repeating: 0.5, count: side * side), width: side, height: side)
let ratio = Double(grey.reduce(0) { $0 + Int($1) }) / Double(grey.count)
#expect(abs(ratio - 0.5) < 0.15)
}
@Test func textRendersToHeadWidth() throws {
let raster = try #require(TextRenderer.render("Milk\nBread", style: TextStyle()))
#expect(raster.width == PrintHead.dots)
#expect(raster.blackRatio > 0)
}
}
+59
View File
@@ -0,0 +1,59 @@
import Foundation
@testable import Inkless
import Testing
struct ProtocolTests {
@Test func crcMatchesVendorFrames() {
#expect(MXW.crc8([0x5D]) == 0x94)
#expect(MXW.crc8([0x00]) == 0x00)
}
@Test func framesMatchVendorBytes() {
#expect(MXW.density(93).hexString == "2221A20001005D94FF")
#expect(MXW.startPrint(rows: 384, mode: .dots).hexString == "2221A9000400800130000000")
#expect(MXW.startPrint(rows: 384, mode: .gray).hexString == "2221A9000400800130020000")
#expect(MXW.flush().hexString == "2221AD000100000000")
#expect(MXW.cancel().hexString == "2221AC0001000000FF")
#expect(MXW.versionRequest().hexString == "2221B10001000000FF")
}
@Test func challengeReplyMatchesReferenceEncoder() throws {
let challenge: [UInt8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99]
let reply = try #require(MXW.challengeResponse(to: challenge, now: Date(timeIntervalSince1970: 1_234_567_895.678)))
#expect(reply.hexString == "2221B3002200834EF9578D0451A26B80DAD95BAEDFC6352026B9F2D7C0D3CB1702488E5738E4868D00FF")
}
@Test func parsesStatus() throws {
let data = try #require(Data(hexString: "2221A1010900" + "01" + "0000" + "57" + "1F" + "00" + "01" + "04" + "00" + "00FF"))
let expected = MXW.Status(activity: .printing, battery: 87, temperature: 31, fault: .overheated)
#expect(MXW.parse(data) == .status(expected))
}
@Test func parsesBothFlowControlForms() throws {
#expect(try MXW.parse(#require(Data(hexString: "2221AE0101001070FF"))) == .flowPause)
#expect(try MXW.parse(#require(Data(hexString: "2221AE0101000000FF"))) == .flowResume)
#expect(try MXW.parse(#require(Data(hexString: "2221AE0001000000"))) == .flowPause)
#expect(try MXW.parse(#require(Data(hexString: "2221AE0001001000"))) == .flowResume)
}
@Test func parsesFirmwareAndHeadType() throws {
let text = "MXW 2.1 2"
let payload = text.utf8.map { String(format: "%02X", $0) }.joined()
let data = try #require(Data(hexString: "2221B1010900" + payload + "00FF"))
#expect(MXW.parse(data) == .version(text, .highVoltage))
}
@Test func grayDepthFollowsFirmware() {
#expect(MXW.usesFourBitGray(firmware: nil))
#expect(MXW.usesFourBitGray(firmware: "MXW 2.1 2"))
#expect(!MXW.usesFourBitGray(firmware: "MXW 1.9 1"))
#expect(!MXW.usesFourBitGray(firmware: "MXW 2.0 1"))
}
@Test func densityDropsOnlyWhenHot() {
let cool = MXW.compensatedDensity(requested: 93, temperature: 40, blackRatio: 0.8, head: .highVoltage, mode: .dots)
let hot = MXW.compensatedDensity(requested: 93, temperature: 66, blackRatio: 0.8, head: .highVoltage, mode: .dots)
#expect(cool == 93)
#expect(hot == 5)
}
}