Helms Display
Background
So, I'll try to make a somewhat decent Openplotter setup on a Raspberry PI 3; not the + version, just 3. It's fairly powerful whilst not consuming too much power. I have various peripherals lying around, such as a cheap NEO-M6 GPS chip, an MPU-9250 compass and more, and rtlsdr -- I even have an HDMI monitor that I'm gonna try and fit to 12V, but I'd like a small display for the helmsman. Thus this project.
The idea is to find a cheap, small, GPIO connected monitor and have it display useful data; not necessarily full-blown maps and pictures, but navigational help. I found an ili9488 display on Ebay, and this project is about making this small display show stuff from Openplotter (basically SignalK).
Hardware considerations
- Very cheap cockpit display software for Openplotter on the Raspberry PI.
- Bought on eBay, for size, and use of less GPIO pins. Thus ended up buying an ili9488 based 3.5 inch TFT LCD. I would love to get something transflective in the future. It turned out the ili9488 is very poorly supported in the linux fb world; I've ordered a 2.8 inch ili9341 based display to try that one out too.
- Reference platform is the Raspberry PI 3 Model B; reasons being:
- It seems to be powerful enough, it's a 1.2 GHz 64 bit quad-core ARM Cortex-A53 processor and 1 GiB of memory. Furthermore is has 4 USB ports, making it less likely that I'll need a USB hub; also, it has WiFi should I want to play around with that. Newer, more powerful models are very neat, but they also have a significantly higher power consumption, model B idles at about 230 mA (1.2 W) where the B+, for example, idles at 350 mA (1.7 W)
Software considerations
- It seems like the ili9488 display is very hard to make work as a linux framebuffer device, at least when connected over SPI (this display has this weird feature that 3, 16 and 18 bit colordepth is supported, but only 3 and 18 over SPI -- and these 18 bit must be transferred at 6 bits in three independent bytes. It's very easy to just shove 24 bit pixel at the device and then not care that the lower 2 bits of every color is lost in translation - but it seems to be very hard to make the fbtft stack refrain from sending rgb565 16 bit pixels. After having googled to the very end of the internet trying to make fbtft work with the display, I ended up gathering a bunch of the byte init sequences into a python script and using python spidev I managed to display nice and neat figures on the screen just communicating directly with it.
- Performance and reliability; the python script was working fine, but also spending a fair amount of CPU cycles to just update this darn little display -- whilst easy to work with, something more powerful was surely needed. In comes Rust; primarily for one reason: it's the best.
- It's compiled, thus fast and efficient, and strongly typed; the compiler is very thorough and the LLVM backend is optimizing.
- It's secure, in that strict borrow and bounds checking make usual caveats a thing of the past
- It has all the low level libraries needed to speak SPI, to render graphics into memory
- The compass rose is constructed of a few vector objects, they're stored in SVG. Currently only single pixel width lines and polylines are supported, of different color though. The SVG parser is very basic. Each object is to be placed in a 1000 by 1000 pixel drawing, center is 500, 500.
- compass-rose.svg: 8 major markers, 8 minor markers, and major heading: N, E, S and W; the letters are written in the Hershey vector font: http://paulbourke.net/dataformats/hershey/
- boat.svg: just a simple boat shape :-)
- cog.svg: Course Over Ground - a blue line ending in the letters: COG -- will be rendered first, i.e. below all other items, and only if signalk has course over ground data
- wind.svg: Yellow inbound arrow -- will be rendered second -- and only if signalk has any wind data
- The text fields are rendered using rusttype and the DejaVu font: https://dejavu-fonts.github.io/ -- freely available truetype font. There is great room for improvements in the rendering parts, such as the text justification code.
- Tungstenite-rs, https://github.com/snapview/tungstenite-rs, was chosen as the WebSocket crate -- it was chosen over websocket-rs, https://github.com/websockets-rs/rust-websocket, and doing my own implementation over TCPStream as it seems simple enough for my taste; I'm not really interested in making this application use Tokio or friends for being async, when I can just spin up a thread, the throughput of network messaging is considered minimal.
Description
Languages
Rust
100%