Xling v4.0 - a plugin for GIMP, improved graphic functions and updated PCB

A project log for Xling

A pocket demon named Exy. Luci? Haven't heard about him.

dsldsl 01/13/2021 at 14:040 Comments


It's been quiet here for a while and it might be a good moment to provide an update describing what's been done during previous months.

I've been working on Xlingtool, a plugin for GIMP based on LCD Image Converter and a new way to draw and export scenes for Xling, which is essential to finish firmware part of the project. There are several improvements in the graphic functions which allow to draw a visible part of an image on the canvas when it's top-left corner has negative coordinates. PCB itself has received several updates including new switches with ground terminals (hopefully, more robust) and a battery socket to prevent a short of its wires during soldering.


GIMP has an attractive user interface and allows to modify an image with many layers. It supports plugins which can be written in C or Python and usually used to implement various raster effects and filters. Plugins have an access to the whole image including its layers and raw data. This can be used together with the image converter to prepare and export a whole scene composed of several static images and animations directly into C code.

Xlingtool does exactly this. Moreover, it uses SHA-1 hash as a name of the exported file which is calculated based on the image data. This feature allows to use layers with duplicated images in a scene construction process, but prevents a scarce flash memory of ATmega1284P to be occupied by duplicated image data.

Once scene is ready, it can be exported into a set of C header files by pressing Filters > Tools > xlingtool... Scene in the example above contains 100 layers, but only visible ones and layers without !ignore() tag will be exported. You'll find similar files generated by Xlingtool in the repository. Let's take a closer look at the scenes.h:

The most important part here is XG_SCNL_smoking_02, an array of scene layers which will be used by the graphic functions to draw a whole scene on a canvas which will be transferred to the display memory once the scene painting process is finished.

Order of the layers in scenes.h is the same as in GIMP, i.e. layer with the smallest index will be placed on top of the others.

There's a special !kbd() tag which tells the plugin to generate a prototype of the keyboard callback function. For example, scene on the picture above contains a dedicated layer with the tag used as a name which forces the plugin to add XG_SCNKBD_smoking_02(XG_ButtonState_e, void *) to the scenes header file. Obviously, there should be an implementation of the function provided. This keyboard function is called right before the next iteration of the scene drawing loop in the display task.

Two types of the layer objects are available at the moment: images and animations with XG_IMG and XG_ANM prefixes accordingly. Xlingtool also generates an anim.h file where each scene animations are defined:

Each animation has its own array of frames defined with XG_ANMF prefix, and each animation frame has a chance to select an alternative frame to be drawn next instead of the frame which goes right after the current one, i.e. XG_ANMF_RightEye[0] has a 98% chance for XG_ANMF_RightEye[8] to be drawn next instead of XG_ANMF_RightEye[1].

This mechanism helps to create non-linear, complex and interesting animations.

The plugin may produce a lot of files with SHA-1 hashes in their names depending on a number of layers in a particular scene and only two human-readable files described above. Scene itself can be drawn on a canvas using a simple function from xling/graphics.h which is designed to be called in a loop in order to update animation frames:

Improved graphic functions

I've already had a function to draw images on a canvas at the non-negative coordinates. It worked quite well when only a part of the image was visible due to its placement and size. However, it was impossible to use negative coordinates there.

I'm talking about XG_Draw_PF() function which uses a new CALC_AUX_POINT() macro added to calculate an auxiliary point with non-negative coordinates (x, y) which will be used as a new top-left corner to draw a visible part of the original image only. In addition, an "idx" offset in the image data array, width and height of the new image will be provided:

You'll find more details in this commit. Don't be afraid of many changes there. All of the scene files have been generated by Xlingtool. The rest of the XG_Draw_PF() function hasn't been changed at all.

4th revision of the board

Noticeable changes here include a low-profile Pico-EZmate header and TVCU11BB switches with ground terminal. According to @Marianne Primeau Breton, it was hard to solder battery pins without shorting them on a previous version of the board, but new header should help with these troubles. New buttons should be a bit more durable comparing to the ones I used previously (even during a manual PCB assembling).


Let me show a complex, animated and interactive scene up and running. Enjoy!

Happy New Year and have a good time!