Tom Willemse
b86754cb92
There seems to be magic going on here. Once the speed has been set for the device once the OS (at least GNU/Linux) remembers the setting and it doesn't have to happen again after. Since I was porting from my Emacs module, I kept running Emacs and it kept setting the speed, which meant that my tests with Guile kept working. After a reboot, it stopped. This change makes sure that the speed is set. I'm not sure if the raw is necessary, but it's in the example, and it seems to work for now, so I'll keep it around.
298 lines
11 KiB
Scheme
298 lines
11 KiB
Scheme
(define-module (inkplate)
|
||
#:use-module ((ice-9 format) #:select (format))
|
||
#:use-module ((srfi srfi-9) #:select (define-record-type))
|
||
#:use-module ((termios system) #:select (termios-B115200))
|
||
#:use-module ((termios with-exceptions)
|
||
#:select (make-termios-struct
|
||
tc-get-attr!
|
||
tc-set-attr
|
||
cf-make-raw!
|
||
cf-set-speed!))
|
||
|
||
#: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+"))
|
||
(termios (make-termios-struct)))
|
||
(tc-get-attr! port termios)
|
||
(cf-make-raw! termios)
|
||
(cf-set-speed! termios termios-B115200)
|
||
(tc-set-attr port termios)
|
||
(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)))
|