aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2023-06-03 00:29:04 -0700
committerGravatar Tom Willemse2023-06-03 00:29:04 -0700
commit4f1b559f1c3a3ec72b659959447144d2fb872aae (patch)
tree119c267d882e9eabed9366cdd22135474b478910
downloadguile-inkplate-4f1b559f1c3a3ec72b659959447144d2fb872aae.tar.gz
guile-inkplate-4f1b559f1c3a3ec72b659959447144d2fb872aae.zip
Initial commit
-rw-r--r--.gitignore1
-rw-r--r--README.org4
-rw-r--r--examples/date.scm22
-rw-r--r--inkplate/lowlevel.scm286
-rw-r--r--tests/inkplate.scm286
5 files changed, 599 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bfe3d57
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+Inkplate.log
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..cf51cd8
--- /dev/null
+++ b/README.org
@@ -0,0 +1,4 @@
+#+title: Guile Inkplate
+#+subtitle: A port of my Emacs Lisp Inkplate library to Guile
+
+This is a simple port of my Emacs Lisp Inkplate library to Guile.
diff --git a/examples/date.scm b/examples/date.scm
new file mode 100644
index 0000000..0f34145
--- /dev/null
+++ b/examples/date.scm
@@ -0,0 +1,22 @@
+(use-modules ((inkplate lowlevel) #:prefix inkplate:)
+ (srfi srfi-19))
+
+(let ((my-dev (inkplate:open "/dev/ttyUSB0")))
+ (inkplate:clear-screen my-dev)
+ (inkplate:set-cursor my-dev 280 100)
+
+ (inkplate:set-text-size my-dev 10)
+ (inkplate:print my-dev (inkplate:convert-string-to-hex (date->string (current-date) "~Y")))
+
+ (inkplate:set-cursor my-dev 275 180)
+ (inkplate:set-text-size my-dev 8)
+ (inkplate:print my-dev (inkplate:convert-string-to-hex (date->string (current-date) "~m-~d")))
+
+ (inkplate:draw-rectangle my-dev 270 90 250 155 3)
+ (inkplate:draw-rectangle my-dev 269 89 252 157 3)
+ (inkplate:draw-rectangle my-dev 268 88 254 159 3)
+
+ (inkplate:update my-dev)
+ (inkplate:send my-dev)
+
+ (inkplate:close my-dev))
diff --git a/inkplate/lowlevel.scm b/inkplate/lowlevel.scm
new file mode 100644
index 0000000..c26daa7
--- /dev/null
+++ b/inkplate/lowlevel.scm
@@ -0,0 +1,286 @@
+(define-module (inkplate lowlevel)
+ #:use-module ((ice-9 format) #:select (format))
+ #:use-module ((srfi srfi-9) #:select (define-record-type))
+
+ #:export (<inkplate>
+ make-inkplate
+ inkplate?
+ inkplate-input-port
+ inkplate-output-port
+
+ convert-string-to-hex
+
+ open
+ close
+ echo
+ draw-pixel
+ draw-line
+ draw-fast-vertical-line
+ draw-fast-horizontal-line
+ draw-rectangle
+ draw-circle
+ draw-triangle
+ draw-rounded-rectangle
+ fill-rectangle
+ fill-circle
+ fill-triangle
+ fill-rounded-rectangle
+ print
+ set-text-size
+ set-cursor
+ set-text-wrap
+ set-rotation
+ draw-bitmap
+ set-display-mode
+ get-display-mode
+ clear-screen
+ update
+ partial-update
+ read-temperature
+ read-touchpad
+ read-battery
+ panel-supply
+ get-panel-state
+ draw-image
+ draw-thick-line
+ draw-ellipse
+ fill-ellipse
+ send))
+
+(define-record-type <inkplate>
+ (make-inkplate input-port output-port)
+ inkplate?
+ (input-port inkplate-input-port)
+ (output-port inkplate-output-port))
+
+(define (convert-string-to-hex string)
+ "Convert STRING to a hexadecimal representation of the text."
+ (string-join
+ (map (lambda (x) (format #f "~2,'0x" (char->integer x)))
+ (string->list string))
+ ""))
+
+(define (open device-path)
+ "Open a connection to an Inkplate on the named DEVICE-PATH."
+ (let ((port (open-file device-path "r+")))
+ (make-inkplate port port)))
+
+(define (close device)
+ "Close a connection to an Inkplate in DEVICE."
+ (close-port (inkplate-output-port device))
+ (close-port (inkplate-input-port device)))
+
+(define (echo device)
+ "Send a command to check if the DEVICE is receiving commands."
+ (display "#?*" (inkplate-output-port device)))
+
+(define (draw-pixel device x y color)
+ "Draw a pixel on DEVICE at coordinates X and Y in COLOR."
+ (format (inkplate-output-port device) "#0(~3,'0d,~3,'0d,~2,'0d)*" x y color))
+
+(define (draw-line device x1 y1 x2 y2 color)
+ "Draw a line on DEVICE from coordinates X1,Y1 to X2,Y2 in COLOR."
+ (format (inkplate-output-port device)
+ "#1(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x1 y1 x2 y2 color))
+
+(define (draw-fast-vertical-line device x y length color)
+ "Draw a vertical line on DEVICE from X,Y for LENGTH pixels in COLOR."
+ (format (inkplate-output-port device)
+ "#2(~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y length color))
+
+(define (draw-fast-horizontal-line device x y length color)
+ "Draw a horizontal line on DEVICE from X,Y for LENGTH pixels in COLOR."
+ (format (inkplate-output-port device)
+ "#3(~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y length color))
+
+(define (draw-rectangle device x y width height color)
+ "Draw a rectangle on DEVICE at X,Y WIDTH wide by HEIGHT high in COLOR.
+This function draws an outline of a rectangle whereas ‘fill-rectangle’ fills the
+rectangle with the specified color."
+ (format (inkplate-output-port device)
+ "#4(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y width height color))
+
+(define (draw-circle device x y radius color)
+ "Draw a circle on DEVICE at X,Y with RADIUS in COLOR.
+This function draws an outline of a circle whereas ‘fill-circle’ fills the
+circle with the specified color."
+ (format (inkplate-output-port device)
+ "#5(~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y radius color))
+
+(define (draw-triangle device x1 y1 x2 y2 x3 y3 color)
+ "Draw a triangle on DEVICE at points X1,Y1, X2,Y2, and X3,Y3 in COLOR.
+This function draws an outline of a triangle whereas ‘fill-triangle’ fills the
+triangle with the specified color."
+ (format (inkplate-output-port device)
+ "#6(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*"
+ x1 y1 x2 y2 x3 y3 color))
+
+(define (draw-rounded-rectangle device x y width height radius color)
+ "Draw a rounded rectangle on DEVICE at X,Y WIDTH wide by HEIGHT high.
+RADIUS is the radius of the rounded corners. Draw the rectangle in COLOR."
+ (format (inkplate-output-port device)
+ "#7(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*"
+ x y width height radius color))
+
+(define (fill-rectangle device x y width height color)
+ "Draw a rectangle on DEVICE at X,Y WIDTH wide by HEIGHT high in COLOR.
+This function fills the entire rectangle with COLOR while ‘draw-rectangle’ only
+draws an outline."
+ (format (inkplate-output-port device)
+ "#8(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y width height color))
+
+(define (fill-circle device x y radius color)
+ "Draw a circle on DEVICE at X,Y with RADIUS.
+This function fills the entire circle with COLOR while ‘draw-circle’ only draws
+an outline."
+ (format (inkplate-output-port device)
+ "#9(~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y radius color))
+
+(define (fill-triangle device x1 y1 x2 y2 x3 y3 color)
+ "Draw a triangle on DEVICE at points X1,Y1, X2,Y2, and X3,Y3 in COLOR.
+This function fills the entire triangle with COLOR while ‘draw-triangle’ only
+draws an outline."
+ (format (inkplate-output-port device)
+ "#A(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*"
+ x1 y1 x2 y2 x3 y3 color))
+
+(define (fill-rounded-rectangle device x y width height radius color)
+ "Draw a rounded rectangle on DEVICE at X,Y WIDTH wide by HEIGHT high.
+CORNER-RADIUS is the radius of the rounded corners. Fill the rectangle with
+COLOR."
+ (format (inkplate-output-port device)
+ "#B(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*"
+ x y width height radius color))
+
+(define (print device text)
+ "Print the TEXT onto the screen of DEVICE.
+TEXT should be a hex string as produced by ‘convert-string-to-hex’."
+ (format (inkplate-output-port device) "#C(~s)*" text))
+
+(define (set-text-size device size)
+ "Set the text size for the next print command to SIZE for DEVICE."
+ (format (inkplate-output-port device) "#D(~2,'0d)*" size))
+
+(define (set-cursor device x y)
+ "Move the cursor on DEVICE to the X and Y coordinates."
+ (format (inkplate-output-port device) "#E(~3,'0d,~3,'0d)*" x y))
+
+(define (set-text-wrap device enable)
+ "Enable or disable text wrapping on DEVICE depending on the value of ENABLE.
+If ENABLE is #t, enable text wrapping. Otherwise disable it."
+ (format (inkplate-output-port device) "#F(~a)*" (if enable "T" "F")))
+
+(define (set-rotation device rotation)
+ "Set the screen rotation on DEVICE.
+ROTATION can be one of:
+- 0: 0 degrees rotation
+- 1: 90 degrees rotation
+- 2: 180 degrees rotation
+- 3: 270 degrees rotation"
+ (format (inkplate-output-port device) "#G(~3,'0d)*" rotation))
+
+(define (draw-bitmap device x y path)
+ "Draw a bitmap on DEVICE at coordinates X,Y.
+PATH should be a path on the SD card and should be a hex string
+as produced by ‘inkplate--convert-string-to-hex’. This command
+puts a response in the output buffer. It should be one of:
+
+- #H(0)*: Image load failed
+- #H(1)*: Image loaded successfully
+- #H(-1)*: SD Card Init Error"
+ (format (inkplate-output-port device) "#H(~3,'0d,~3,'0d,~s)*" x y path))
+
+(define (set-display-mode device mode)
+ "Set the display mode for DEVICE to MODE.
+Mode can be one of:
+- 1: 1-bit mode
+- 3: 3-bit mode"
+ (format (inkplate-output-port device) "#I(~d)*" mode))
+
+(define (get-display-mode device)
+ "Query the DEVICE for which display mode is active.
+
+This puts one of the following responses into the output buffer:
+- #J(0): 1-bit mode
+- #J(1): 3-bit mode"
+ (display "#J(?)*" (inkplate-output-port device)))
+
+(define (clear-screen device)
+ "Send the command to clear the screen to DEVICE."
+ (display "#K(1)*" (inkplate-output-port device)))
+
+(define (update device)
+ "Send the command to update the display to DEVICE."
+ (display "#L(1)*" (inkplate-output-port device)))
+
+(define (partial-update device yy1 xx2 yy2)
+ "Send the command to update the display to DEVICE.
+Tell it to only do a partial update."
+ ;; I guess that xx1 is implicitly 0? It's not mentioned in the documentation.
+ (format (inkplate-output-port device) "#M(~3,'0d,~3,'0d,~3,'0d)*" yy1 xx2 yy2))
+
+(define (read-temperature device)
+ "Query DEVICE for its current temperature.
+This will produce a response in the output buffer in the form or #N(22)* which
+means its temperature is 22 degrees Celsius."
+ (display "#N(?)*" (inkplate-output-port device)))
+
+(define (read-touchpad device touchpad)
+ "Query DEVICE for the state of TOUCHPAD.
+TOUCHPAD can be 1, 2, or 3. This will produce a response in the
+output buffer which can be read with ‘inkplate-read-output’.
+Possible responses are:
+- #O(1)*: The touch pad is in the high state
+- #O(0)*: The touch pad is in the low state"
+ (format (inkplate-output-port device) "#O(~d)*" touchpad))
+
+(define (read-battery device)
+ "Query DEVICE for the current voltage on the battery.
+This produces a response in the output buffer which can be read using
+‘read-output’. The response is in the form of #P(3.65)* meaning the measured
+voltage on the battery is 3.65VDC."
+ (display "#P(?)*" (inkplate-output-port device)))
+
+(define (panel-supply device enable)
+ "Turn DEVICE on or off depending on the value of ENABLE.
+If ENABLE is #t turn DEVICE on, otherwise turn it off."
+ (format (inkplate-output-port device) "#Q(~d)*" (if enable 1 0)))
+
+(define (get-panel-state device)
+ "Query DEVICE for the state of the panel.
+This command produces a response in the output buffer which can be read using
+‘read-output’. The response can be one of:
+
+- #R(1)*: Panel has power
+- #R(0)*: Panel has no power"
+ (display "#R(?)*" (inkplate-output-port device)))
+
+(define (draw-image device x y path)
+ "Draw an image on DEVICE at coordinates X,Y.
+PATH should be a path on the SD card and a hex string as produced by
+‘convert-string-to-hex’."
+ (format (inkplate-output-port device) "#S(~3,'0d,~3,'0d,~s)*" x y path))
+
+(define (draw-thick-line device x1 y1 x2 y2 thickness color)
+ "Draw a line on DEVICE from X1,Y1 to X2,Y2 in THICKNESS and COLOR."
+ (format (inkplate-output-port device)
+ "#T(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d,~2,'0d)*"
+ x1 y1 x2 y2 thickness color))
+
+(define (draw-ellipse device x y x-radius y-radius color)
+ "Draw an ellipse on DEVICE at coordinates X,Y.
+X-RADIUS and Y-RADIUS specify the x and y radius of the ellipse. Draw it in
+COLOR."
+ (format (inkplate-output-port device)
+ "#U(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y x-radius y-radius color))
+
+(define (fill-ellipse device x y x-radius y-radius color)
+ "Draw and fill an ellipse on DEVICE at coordinates X,Y.
+X-RADIUS and Y-RADIUS specify the x and y radius of the ellipse. Draw it in
+COLOR."
+ (format (inkplate-output-port device)
+ "#V(~3,'0d,~3,'0d,~3,'0d,~3,'0d,~2,'0d)*" x y x-radius y-radius color))
+
+(define (send device)
+ "Send the accumulated commands to DEVICE."
+ (force-output (inkplate-output-port device)))
diff --git a/tests/inkplate.scm b/tests/inkplate.scm
new file mode 100644
index 0000000..fb18199
--- /dev/null
+++ b/tests/inkplate.scm
@@ -0,0 +1,286 @@
+(use-modules (srfi srfi-64)
+ (inkplate lowlevel))
+
+(define* (call-with-test-device func #:key (input-string ""))
+ (let ((device (make-inkplate (open-input-string input-string) (open-output-string))))
+ (func device)
+ (close device)))
+
+(test-begin "Inkplate")
+(test-equal "Convert hello" "48656c6c6f" (convert-string-to-hex "Hello"))
+(test-equal "Convert zero-pads result" "0a" (convert-string-to-hex "\n"))
+(test-equal "Convert a path" "2f696d616765312e626d70" (convert-string-to-hex "/image1.bmp"))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw pixel command zero-padds coordinates and color"
+ "#0(005,005,01)*"
+ (begin
+ (draw-pixel test-device 5 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw line command zero-padds coordinates and color"
+ "#1(005,010,005,010,01)*"
+ (begin
+ (draw-line test-device 5 10 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw fast vertical line command zero-padds coordinates and color"
+ "#2(005,010,005,01)*"
+ (begin
+ (draw-fast-vertical-line test-device 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw fast horizontal line command zero-padds coordinates and color"
+ "#3(005,010,005,01)*"
+ (begin
+ (draw-fast-horizontal-line test-device 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw rectangle command zero-padds coordinates and color"
+ "#4(005,010,005,010,01)*"
+ (begin
+ (draw-rectangle test-device 5 10 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw circle command zero-padds coordinates and color"
+ "#5(005,010,005,01)*"
+ (begin
+ (draw-circle test-device 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw triangle command zero-padds coordinates and color"
+ "#6(005,010,005,010,005,010,01)*"
+ (begin
+ (draw-triangle test-device 5 10 5 10 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw rounded rectangle command zero-padds coordinates and color"
+ "#7(005,010,005,010,005,01)*"
+ (begin
+ (draw-rounded-rectangle test-device 5 10 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Fill rectangle command zero-padds coordinates and color"
+ "#8(005,010,005,010,01)*"
+ (begin
+ (fill-rectangle test-device 5 10 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Fill circle command zero-padds coordinates and color"
+ "#9(005,010,005,01)*"
+ (begin
+ (fill-circle test-device 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Fill triangle command zero-padds coordinates and color"
+ "#A(005,010,005,010,005,010,01)*"
+ (begin
+ (fill-triangle test-device 5 10 5 10 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Fill rounded rectangle command zero-padds coordinates and color"
+ "#B(005,010,005,010,005,01)*"
+ (begin
+ (fill-rounded-rectangle test-device 5 10 5 10 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Print command quotes its argument"
+ "#C(\"48656c6c6f\")*"
+ (begin
+ (print test-device "48656c6c6f")
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set text size command zero-padds size"
+ "#D(05)*"
+ (begin
+ (set-text-size test-device 5)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set cursor command zero-padds coordinates"
+ "#E(005,010)*"
+ (begin
+ (set-cursor test-device 5 10)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set test wrap #t becomes T"
+ "#F(T)*"
+ (begin
+ (set-text-wrap test-device #t)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set test wrap #f becomes F"
+ "#F(F)*"
+ (begin
+ (set-text-wrap test-device #f)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set rotation command zero-padds the rotation"
+ "#G(000)*"
+ (begin
+ (set-rotation test-device 0)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw bitmap command zero-padds the coordinates and quotes the path"
+ "#H(005,010,\"48656c6c6f\")*"
+ (begin
+ (draw-bitmap test-device 5 10 "48656c6c6f")
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Set display mode command inserts a number"
+ "#I(1)*"
+ (begin
+ (set-display-mode test-device 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Get display mode command gets created"
+ "#J(?)*"
+ (begin
+ (get-display-mode test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Clear screen command gets created"
+ "#K(1)*"
+ (begin
+ (clear-screen test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Update display command gets created"
+ "#L(1)*"
+ (begin
+ (update test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Partial update command zero-padds coordinates"
+ "#M(005,010,100)*"
+ (begin
+ (partial-update test-device 5 10 100)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Read temperature command gets created"
+ "#N(?)*"
+ (begin
+ (read-temperature test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Read touchpad command gets created"
+ "#O(1)*"
+ (begin
+ (read-touchpad test-device 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Read battery command gets created"
+ "#P(?)*"
+ (begin
+ (read-battery test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Panel supply command #t becomes 1"
+ "#Q(1)*"
+ (begin
+ (panel-supply test-device #t)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Panel supply command #f becomes 0"
+ "#Q(0)*"
+ (begin
+ (panel-supply test-device #f)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Get panel state command gets created"
+ "#R(?)*"
+ (begin
+ (get-panel-state test-device)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw image zero-padds coordinates and quotes path"
+ "#S(005,010,\"2f696d616765312e626d70\")*"
+ (begin
+ (draw-image test-device 5 10 "2f696d616765312e626d70")
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw thick line zero-padds arguments"
+ "#T(005,010,100,005,10,01)*"
+ (begin
+ (draw-thick-line test-device 5 10 100 5 10 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Draw ellipse zero-padds arguments"
+ "#U(005,010,100,005,01)*"
+ (begin
+ (draw-ellipse test-device 5 10 100 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(call-with-test-device
+ (lambda (test-device)
+ (test-equal "Fill ellipse zero-padds arguments"
+ "#V(005,010,100,005,01)*"
+ (begin
+ (fill-ellipse test-device 5 10 100 5 1)
+ (get-output-string (inkplate-output-port test-device))))))
+
+(test-end "Inkplate")