(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 ( 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 (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)))