← Back to Reference Manual Index
VESC
Vesc Express Display

Documentation for graphics library and display drivers

Introduction

The graphics library provides a set of functions for drawing onto rectangular images, called Image-buffers, from LispBM.

Drivers for a specific display is loaded with the associated disp-load function:

  1. disp-load-sh8501b
  2. disp-load-ili9341
  3. disp-load-ssd1306

Each disp-load function takes arguments specific to the display. These are explained below.

Each display driver provides a "rendering", "clearing" and "reset" function that is connected to the LispBM extensions disp-render, disp-clear and disp-reset upon loading. The render, clear and reset functions are the display dependent interface that must be implemented per display.

Image-buffers

The graphics library is based on image-buffers, that are rectangular arrays of pixels where all pixels are of a certain format. The formats we support in image-buffers are:

  1. indexed2 - 2 colors (1 bit per pixel)
  2. indexed4 - 4 colors (2 bits per pixel)
  3. indexed16 - 16 colors (4 bits per pixel)
  4. rgb332 - 8Bit color
  5. rgb565 - 16Bit color
  6. rgb888 - 24Bit color

Image-buffers can be created in two ways using the graphics library:

  1. img-buffer - allocates a blank image-buffer in lbm memory.
  2. img-buffer-from-bin - creates an image-buffer from an image imported into the script.

For example, creating a 100x100 image-buffer of indexed2 colors is done as:

(def my-img (img-buffer 'indexed2 100 100))

When drawing on indexed2 or indexed4 image-buffers, colors are expressed as an integer. 0,1 for indexed2, 0,1,2,3 for indexed4 and 0 to 15 for indexed16. For rgb332, rgb565 and rgb888 image-buffers a color is given in hex notation 0xRRGGBB.

Example that draws a line from pos (0,0) to pos (90,90) in color 1 on an indexed2 image-buffer:

(img-line my-img 10 10 90 90 1)

When an image-buffer is rendered onto the display (using the disp-render function) the colors of the image-buffer are mapped to the color space of the display. In the case of indexed2, indexed4 and indexed16 this mapping is performed using a list of target colors expressed in RGB888 format.

Note that the RAM requirement of a 100x100 image is:

  1. at indexed2: 1250 Bytes
  2. at indexed4: 2500 Bytes
  3. at indexed16: 5000 Bytes
  4. at rgb332: 10000 Bytes
  5. at rgb565: 20000 Bytes
  6. at rgb888: 30000 Bytes

There are a number of function for drawing onto an image-buffer:

  1. img-setpix
  2. img-line
  3. img-text
  4. img-clear
  5. img-circle
  6. img-arc
  7. img-circle-sector
  8. img-circle-segment
  9. img-rectangle
  10. img-triangle
  11. img-blit

The purpose of most of these are given by their names. img-blit draws an image onto another image and can while doing so rotate and scale the image it is drawing. More details on each of these functions are available in the later reference sections.

The functions that draw onto an image-buffer takes optional arguments that specify extra attributes to apply when drawing. These attributes are:

  1. '(thickness w): Line thickness w. For most shapes, the thickness extends inwards. But for img-triangle and img-line, it extends equal outwards and inwards, so the total line thickness is actually equal to two times w.
  2. '(dotted d-len d-space-len): Dotted or dashed lines with d-len long line segments separated by d-space-len.
  3. '(filled): Specifies that the shape should be filled.
  4. '(rounded radius): Specifies that the shape should have rounded corners. Additionally, the img-arc function can take this argument in the form '(rounded) to specify that, when the arc isn't filled or dotted, the line ends should be rounded. Sadly, this is the only function that can draw lines with square ends right now.
  5. '(scale scale-f): Scale the image by factor scale-f
  6. '(rotate rx ry deg): Rotate an image around point (rx,ry), deg degrees.
  7. '(resolution steps): How many lines dotted arcs are simplified into when drawn. Non-dotted arcs use a newer algorithm that's pixel perfect. When drawing dotted arcs, they are simplified into a series of lines where the actual amount of steps is scaled from 0 to steps based on the arc angle span. Note that this isn't just limited to img-arc, but every function that draws any kind of arc, like actual arcs, circle segments and sectors, rounded shapes, or dotted circles. The default is 80.

Not all attributes are applicable to all drawing functions. The applicable attributes for each drawing-function is listed in the description of the function in the reference section.

Rendering and color mapping

An image-buffer can be rendered to the display using disp-render. If the image is an indexed2, indexed4 or indexed16 color image, it is when rendering the image you decide what color each index in the image represents.

For example you can draw an indexed2 image using a very red and a green color as:

(disp-render my-img 10 10 '(0x00FF00 0xFF0000))

The code above draws my-img at location (10,10). Zeroes in the image will be drawn using color 0x00FF00, maximum green, and ones will be drawn as 0xFF0000 maximum red.

For rgb332, rgb565 and rgb888 formats the color mapping list is ignored and can be empty.

More advanced color mapping schemes can be represented using a color type that is created using the img-color or img-color-setpre functions. The color type can represent normal colors, such as 0xFF0000, but can also represent gradients to be applied to the image in x or y direction upon rendering.

Displays

sh8501b

Compatible with all image formats supported by the graphics library.

disp-load-sh8501b

(disp-load-sh8501b gpio-sd0 gpio-clk gpio-cs gpio-reset spi-mhz)

Loads the sh8501b driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins.

Example using GPIO pins 6,5,7 and 8 for sd0,clk,cs and reset running the SPI clock at 40MHz:

(disp-load-sh8501b 6 5 7 8 40)

ili9341

Compatible with all image formats supported by the graphics library.

disp-load-ili9341

(disp-load-ili9341 gpio-sd0 gpio-clk gpio-cs gpio-reset gpio-dc spi-mhz)

Loads the ili9341 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins. In addition, the ili9341 uses a data/command signal to discern between commands and data. The data/command signal is mapped to GPIO gpio-cs.

Example using GPIO pins 6,5,19,18 and 7 for sd0,clk,cs,reset and dc. The SPI clock is set to 40MHz.

(disp-load-ili9341 6 5 19 18 7 40)

ssd1306

Can display images of indexed2 format and is limited to displaying only full screen images starting at position (0, 0).

disp-load-ssd1306

(disp-load-ssd1306 gpio-sda gpio-scl i2c-hz)

Load the ssd1306 driver. The ssd1306 talks I2C over the GPIOs gpio-sda (serial data) and gpio-scl (clock).

Example using GPIO pins 7 and 6 for serial data and clock.

(disp-load-ssd1306 7 6 700000)

st7789

Compatible with all image formats supported by the graphics library.

disp-load-st7789

(disp-load-st7789 gpio-sd0 gpio-clk gpio-cs gpio-reset gpio-dc spi-mhz)

Loads the st7789 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins. In addition, the st7789 uses a data/command signal to discern between commands and data. The data/command signal is mapped to GPIO gpio-cs.

Example using GPIO pins 6,5,19,18 and 7 for sd0,clk,cs,reset and dc. The SPI clock is set to 40MHz.

(disp-load-st7789 6 5 19 18 7 40)

Note Many st7789-based displays do not have the full resolution that the driver supports in the panel. Some of them also have an offset where the panel starts. The panel size and offset has to be taken into account when using disp-render.

st7735

Compatible with all image formats supported by the graphics library.

disp-load-st7735

(disp-load-st7735 gpio-sd0 gpio-clk gpio-cs gpio-reset gpio-dc spi-mhz)

Loads the st7735 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins. In addition, the st7789 uses a data/command signal to discern between commands and data. The data/command signal is mapped to GPIO gpio-cs.

Example using GPIO pins 6,5,19,18 and 7 for sd0,clk,cs,reset and dc. The SPI clock is set to 40MHz.

(disp-load-st7789 6 5 19 18 7 40)

Note Many st7735-based displays do not have the full resolution that the driver supports in the panel. Some of them also have an offset where the panel starts. The panel size and offset has to be taken into account when using disp-render.

ili9488

Compatible with all image formats supported by the graphics library.

disp-load-ili9488

(disp-load-ili9488 gpio-sd0 gpio-clk gpio-cs gpio-reset gpio-dc spi-mhz)

Loads the ili9488 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins. In addition, the ili9488 uses a data/command signal to discern between commands and data. The data/command signal is mapped to GPIO gpio-cs.

Example using GPIO pins 6,5,19,18 and 7 for sd0,clk,cs,reset and dc. The SPI clock is set to 40MHz.

(disp-load-ili9488 6 5 19 18 7 40)

ssd1351

Compatible with all image formats supported by the graphics library.

disp-load-ssd1351

(disp-load-ssd1351 gpio-sd0 gpio-clk gpio-cs gpio-reset gpio-dc spi-mhz)

Loads the ssd1351 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins. In addition, the ssd1351 uses a data/command signal to discern between commands and data. The data/command signal is mapped to GPIO gpio-cs.

Example using GPIO pins 6,5,19,18 and 7 for sd0,clk,cs,reset and dc. The SPI clock is set to 40MHz.

(disp-load-ssd1351 6 5 19 18 7 40)

icna3306

Compatible with all image formats supported by the graphics library.

disp-load-icna3306

(disp-load-icna3306 gpio-sd0 gpio-clk gpio-cs gpio-reset spi-mhz)

Loads the icna3306 driver. The driver uses hardware-SPI at rate spi-mhz on the gpio-sd0 and gpio-clk GPIO pins.

Example using GPIO pins 6,5,7 and 8 for sd0,clk,cs and reset running the SPI clock at 40MHz:

(disp-load-icna3306 6 5 7 8 40)

Common display operations

disp-reset

(disp-reset)

Resets and clears the display.

disp-clear

(disp-clear)

Clears the display by writing zero to all pixel locations.

(disp-clear color)

Clears the display to the given color. The color is expressed in hex rgb888 format 0xRRGGBB.

disp-render

(disp-render img px py colors)

Renders an image img at position (px, py). If the picture is of 'indexed2, 'indexed4 or indexed16 format the colors argument is used to map the values of the image to colors on the display.

colors can be a list of numbers expressed int hex rgb888 format. For example:

'(0x000000 0xFFFFFF)

Or for a 4 color image (`'indexed4):

'(0x000000 0xFF0000 0x00FF00 0x0000FF)

The colors argument can also be made up of colors created using the img-color function.

As an example, the two programs below render an image using colors black and red:

using a list of numbers representing colors

(disp-render img 0 0 '(0x000000 0xFF0000))

using a list of colors

(disp-render img 0 0 (list (img-color 'regular 0x000000)
                           (img-color 'regular 0xFF0000)))

A gradient can be applied to the picture when rendering. This is done using the arguments 'gradient_x, 'gradient_y to img-color. look up img-color for more information.

disp-render-jpg

(disp-render-jpg img-jpg px py)

Decodes and displays a jpg at position (px, py).

Example that imports and displays a jpg image.

(import "img_test_jpg.jpg" 'img-jpg)
(disp-render-jpg img-jpg 0 0)

Graphics library

img-arc

(img-arc img cx cy r ang-s ang-e color opt-attr1 ... opt-attrN)

Draws an arc with its center at (cx, cy) and radius r. The arc extends from angle ang-s to ang-e. Additional attributes are optional.

Applicable attributes:

  1. dotted
  2. filled
  3. thickness
  4. resolution
  5. rounded

Example drawing an arc with square corners

(img-arc img 100 100 50 160 320 1)

Example drawing an arc with rounded corners

(img-arc img 100 100 50 160 320 1 '(rounded))

Example drawing a dashed (dotted) arc:

(img-arc img 100 100 50 160 320 1 '(dotted 15 15))

img-blit

(img-blit img-dst img-src px py tc opt-attr1 ... opt-attrN)

Draws the source image img-src onto the destination image img-dst starting with the top left corner of source at position (px, py) of the destination image. Additional attributes are optional.

Applicable attributes:

  1. rotate
  2. scale

Example drawing a scaled and rotated image onto an image-buffer.

(img-blit img img2 60 100 -1 '(rotate 50 10 60) '(scale 2.2))

In the example, img2 is drawn onto img1 at position (60, 100). img2 is rotated around point (50,10), 60 degrees and scaled by a factor 2.2.

img-buffer

(img-buffer color-fmt width height)

Creates an image-buffer of size width * height of colors of format color-fmt.

color-fmt can be one of the following symbols:

  1. indexed2
  2. indexed4
  3. indexed16
  4. rgb332
  5. rgb565
  6. rgb888

Image-buffers are allocated from the lbm-memory, not heap.

Example that creates and names an image-buffer:

(def img (img-buffer 'indexed2 100 100))

img-buffer-from-bin

(img-buffer-from-bin bin-data)

Creates an image-buffer from an imported bin file. The binary data must be a valid representation of a picture and must contain a header indicating the width, height and color format of the image. The bin files exported by "Display Tool" in VESC tool follows this format.

Example that imports a bin file and creates an image-buffer:

(import "llama.bin" 'llama-data)
(def llama (img-buffer-from-bin llama-data))

img-circle

test-op (img-circle img cx cy r color opt-attr1 ... opt-attrN)

Draws a circle with its center at (cx, cy) and radius r in color color. Additional attributes are optional.

Applicable attributes:

  1. dotted
  2. filled
  3. thickness
  4. resolution

Example drawing a filled circle with radius 80:

(img-circle img 100 100 80 1 '(filled))

img-circle-sector

(img-circle-sector img cx cy r ang-s ang-e color opt-attr1 ... opt-attrN)

Draw a circle-sector, a piece of pie. Draws a piece of a circle positioned at (cx, cy) with radius r. The piece drawn extends across the angles ang-s to and-e.

Applicable attributes:

  1. dotted
  2. filled
  3. thickness
  4. resolution

Example drawing a thick circle-sector of 45 degrees and radius 80.

(img-circle-sector img 220 40 40 90 200 1 '(thickness 3))

img-circle-segment

(img-circle-segment img cx cy r ang-s ang-e color opt-attr1 ... opt-attrN)

Draw a circle-segment. Imagine a line (chord) drawn between the points of the circle at angle ang-s and ang-e cutting off a circle segment. The segment is the part of the circle that is enclosed by the arc from ang-s to ang-e and the line drawn between those points on the circle.

Applicable attributes:

  1. dotted
  2. filled
  3. thickness
  4. resolution

Example drawing a filled circle segment.

(img-circle-segment img 100 100 80 0 100 1 '(filled))

img-clear

(img-clear img opt-color)

Clears an image-buffer to zero or optionally to a color value given as argument.

img-color

(img-color kind arg1 opt-arg2 ... opt-arg4)

Create a color object for use with disp-render. img-color takes between 2 and 5 arguments depending on what kind of color-mapping that is being set up.

regular

(img-color 'regular 0xRRGGBB)

Creates a regular color for 1-1 mapping between values of an indexed image and the display color space.

gradient_x

(img-color 'gradient_x c0 c1 width offset repeat-type)

Creates a color gradient in the horizontal direction across the image. The pixel x position will influence the final color displayed on the screen. width dictates the amount of pixels it takes to go from c0 to c1 (after which the pattern repeats). offset applies an offset to the starting point of the interval c0 to c1. repeat-type controls how the gradient repeats outside the normal range specified by width and offset. Is either 'repeat or 'mirrored.

gradient_y

(img-color 'gradient_y c0 c1 width offset repeat-type)

Creates a color gradient in the vertical direction across the image. The pixel y position will influence the final color displayed on the screen. width dictates the amount of pixels it takes to go from c0 to c1 (after which the pattern repeats). offset applies an offset to the starting point of the interval c0 to c1. repeat-type controls how the gradient repeats outside the normal range specified by width and offset. Is either 'repeat or 'mirrored.

gradient_x_pre

(img-color 'gradient_x_pre c0 c1 width offset repeat-type)

See gradient_x. gradient_x_pre precalculates and buffers the color mapping. This buffer can be modified using img-color-setpre.

If the repeat-type is 'mirrored, the internal buffer is double in width to store the mirrored half. Width may not be larger than 512. Larger values will be clamped.

gradient_y_pre

(img-color 'gradient_y_pre c0 c1 width offset repeat-type)

See gradient_y. gradient_y_pre precalculates and buffers the color mapping. This buffer can be modified using img-color-setpre

If the repeat-type is 'mirrored, the internal buffer is double in width to store the mirrored half. Width may not be larger than 512. Larger values will be clamped.

img-color-setpre

(img-color-setpre color pos new-color)

Changes the color at a position in a precalculated color mapping. The color should be created by img-color and using one of the precalculated gradient formats (gradient_x_pre or gradient_y_pre).

The position is relative to the start of the gradient, or in other words, the offset that the gradient was configured with doesn't effect how pos is interpreted. pos must be in the range 0 to width (exclusive) where width is the width given to img-color.

The mirrored part of the gradient (if present) is not part of the precalculated buffer, but generated from the normal buffer.

img-color-getpre

(img-color-getpre color pos)

Get the color from a precalculated color mapping. See img-color-setpre.

img-color-set

(img-color-set color prop value)

Set some property of a color generated by img-color. prop is a symbol (see table below for valid values), and some properties are only relevant with certain kinds of colors. | Property | valid values | color kind | | -------------- | ------------------------ | ------------------------------ | | 'color-0 | Any integers | regular, gradient_* | | 'color-1 | Any integers | gradient_* | | 'width | Any integers | gradient_* | | 'offset | Any integers | gradient_*, gradient_*_pre | | 'repeat-type | 'repeat or 'mirrored | gradient_*, gradient_*_pre | (rgb colors are just integers, e.g. what you would get after typing 0xffffff)

Invalid properties or values result in type errors.

img-color-get

(img-color-get color prop)

Get some property of a color generated by img-color. Only certain properties are valid for different color kinds, see img-color-set. An exception is the properties color-0, color-1, and width, which precalculated gradients are allowed to read, but not write. Note that this only reads the values which were given when the gradient was created. The actual colors of the buffer may have been set to different colors using img-color-setpre.

img-dims

(img-dims img)

Returns the dimensions of the image, its width and height, as a list.

img-line

(img-line img x1 y1 x2 y2 color opt-attr1 ... opt-attrN)

Draws a line between points (x1, y1) and (x2, y2) in color color.

Applicable attributes:

  1. dotted
  2. thickness

Example that draws a thick dashed (dotted) line:

(img-line img 10 10 120 220 1 '(dotted 15 15) '(thickness 3))

img-rectangle

(img-rectangle img x y width height color opt-attr1 ... opt-attrN)

Draws a rectangle with its upper left corner in point (x,y) and width width and height height in color color.

Applicable attributes:

  1. dotted
  2. filled
  3. rounded
  4. thickness
  5. resolution

Example drawing a filled rectangle with rounded corners:

(img-rectangle img 10 10 120 180 1 '(filled) '(rounded 45) )

Note that the argument to rounded should be at most 45 degrees.

img-setpix

(img-setpix x y color)

Set pixel (x,y) in image img to color color.

example that sets a pixel:

(img-setpix 10 10 1)

img-text

(img-text img x y fg bg font str)
(img-text img x y colors font str)

Draws the text from the string str at position (x,y) using font-data font with foreground color fg and background color bg. Alternatively, a list of colors can be provided instead of the foreground and background. The color-list is needed for 2-bit antialiased fonts and should contain 4 colors then.

fonts can be loaded using the import facility.

Example that imports a font and draws some text to an image-buffer:

(import "font_16_24_all.bin" 'font-small)
(img-text img 10 10 1 0 font-small "LispBM")

img-triangle

(img-triangle img x1 y1 x2 y2 x3 y3 color opt-attr1 ... opt-attrN)

Draws the triangle (x1,y1), (x2,y2), (x3,y3) in color color.

Applicable attributes:

  1. dotted
  2. filled
  3. thickness

Example that draws a filled triangle:

(img-triangle img 30 60 160 120 10 220 1 '(filled))

Attribute reference

Lines

(img-line img 10 10 300 50 1)
(img-line img 10 30 300 70 1 '(dotted 15 15))
(img-line img 10 50 300 90 1 '(thickness 3))
(img-line img 10 70 300 110 1 '(thickness 3) '(dotted 15 15))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Lines with different attributes

Cirlces

(img-circle img 40 40 40 1)
(img-circle img 130 40 40 1 '(dotted 15 15))
(img-circle img 220 40 40 1 '(thickness 3))
(img-circle img 40 130 40 1 '(dotted 15 15) '(thickness 3))
(img-circle img 130 130 40 1 '(filled))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Circles with different attributes

Circle sectors

(img-circle-sector img 40 40 40 90 200 1)
(img-circle-sector img 130 40 40 90 200 1 '(dotted 15 15))
(img-circle-sector img 220 40 40 90 200 1 '(thickness 3))
(img-circle-sector img 40 130 40 90 200 1 '(dotted 15 15) '(thickness 3))
(img-circle-sector img 130 130 40 90 200 1 '(filled))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Circle-sectors with different attributes

Circle segments

(img-circle-segment img 40 40 40 90 200 1)
(img-circle-segment img 130 40 40 90 200 1 '(dotted 15 15))
(img-circle-segment img 220 40 40 90 200 1 '(thickness 3))
(img-circle-segment img 40 130 40 90 200 1 '(dotted 15 15) '(thickness 3))
(img-circle-segment img 130 130 40 90 200 1 '(filled))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Circle-segments with different attributes

Triangles

(img-triangle img 10 10 80 20 40 80 1)
(img-triangle img 100 10 170 20 130 80 1 '(dotted 15 15))
(img-triangle img 190 10 260 20 220 80 1 '(thickness 3))
(img-triangle img 10 100 80 110 40 170 1 '(dotted 15 15) '(thickness 3))
(img-triangle img 100 100 170 110 130 170 1 '(filled))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Triangles with different attributes

Rectangles

(img-rectangle img 10 10 70 70 1)
(img-rectangle img 90 10 70 70 1 '(dotted 15 15))
(img-rectangle img 170 10 70 70 1 '(thickness 3))
(img-rectangle img 10 90 70 70 1 '(dotted 15 15) '(thickness 3))
(img-rectangle img 90 90 70 70 1 '(filled))
(img-rectangle img 170 90 70 70 1 '(rounded 10))
(img-rectangle img 10 170 70 60 1 '(rounded 10) '(filled))
(disp-render img 0 0 (list 0x000000 0xFF0000))

Rectangles with different attributes

Bliting

(import "llama.bin" 'llama-data)
(def llama (img-buffer-from-bin llama-data))

(def llama-dims (img-dims llama))
(def llama-w (first llama-dims))
(def llama-h (second llama-dims))

(img-blit img llama 10 10 -1)
(img-blit img llama 120 10 -1 `(rotate ,(/ llama-w 2) ,(/ llama-h 2) 45))
(img-blit img llama 10 120 -1 '(scale 0.5))
(img-blit img llama 120 120 -1 '(scale 1.5))
(img-blit img llama 20 60 -1 '(scale 1.5) `(rotate ,(/ llama-w 2) ,(/ llama-h 2) 45)) 
(disp-render img 0 0 (list 0x000000 0xFF0000))

Bliting with different attributes