Interfacing an LCD with an SBC - with Zig! #1
embeddedIntro
When one looks up how to add a display to an SBC (such as a Raspberry PI), most of the examples/tutorials just say to use this or that kernel module, or library.
Since I’m a DIY person, I refused this approach when it came to this parallel I/O I randomly got my hands on.
This can shed some light, more on how easy it is to bootstrap a cross platform embedded program, than how to read documentation/a datasheet.
___________
|| || _______
||ASCII ART|| | _____ |
|| || ||_____||
||_________|| | ___ |
| + + + + | | |___| |
_|_|_ \ | |
(_____) \ | |
\ ___ | |
______ \__/ \_| |
| _ | _/ | |
| ( ) | / |_______|
|___|__| / CA15
\_____/
Materials
SBC
Since I, most of the time, use an ODroid, I decided to write it for that platform. I’m sure the project, once finished, will easily be ported for any other SBC.
Display
The display I got my hands on is an RG12864B-BIW-V from Raystar. It features 20 pins, out of which 8 are for sending/receiving data. You can power it with 5V, but for communication, 3.3V will work as well for the output-only pins.
I have estimated a maximum of 300mA, so the ODroid pins will be able to handle it with no issue.
Components & assembly
Pretty basic:
- two 3.3V to 5V bidirectional translator (for data)
- resistors for contrast an backlight
- an NPN transistor
- a switch (of course)
Connecting them is quite trivial.
I used hand-cutâ„¢ male pin connectors for interfacing with the computer, with a post-it to reference each pin.
For the display, two female connectors allow sufficient height for the other components. Double-adhesive tape is a must so I make sure I don’t bend the pins.
Bootstrapping the project
I maintained the following project structure:
+ display-project
|
|- build.zig
|- src <- my Zig files
\- external +- .bazelrc \
|- BUILD |<- Bazel rules
|- WORKSPACE /
|- libgpiod <- a kernel-provided library for GPIO
\- fb <- a lightweight framebuffer library
Zig’s build.zig
For this, the default build file is a good starting point. It takes few minutes to add a CrossTarget
. For any external, non-Zig project, one just has to addIncludeDir
and addObjectFile
, and they’re good to go!
Bazel’s BUILD
Since I tried to take as much as I can from toying around, I used Bazel, as it’s quite a no-brainer to add simple dependencies.
For my WORKSPACE
, the rules_foreign_cc
is sufficient to compile the external dependencies. Since a toolchain is needed and I’m using Zig, why not use the Zig C compiler?
For the BUILD
file, add a platform, the filegroups, and follow the rules’ documentation. CAREFUL: if you’re using musl, as I am, make sure to configure with ac_cv_func_malloc_0_nonnull=yes
to avoid compilation problems.
How will it work?
Well, writing kernel modules seems like a total overkill for this. And since I got a bit into microkernels lately, I decided the best way would be if this is a daemon in userspace, which is fed data (text or images) through a socket.
Current status
I will put the code online once it’s finished.
I have to finish my high-precision soldering job and hope I got it right, before I can move on to testing. :}