guile-inkplate/inkplate/lowlevel.scm

287 lines
11 KiB
Scheme
Raw Normal View History

2023-06-03 09:29:04 +02:00
(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)))