One predominant opinion about the block based languages is that they are mainly for introductory projects meant to teach young kids how to program. Scratch, Makecode, and the various Make-family products come to mind.
This project demonstrates that the right kind of block language can be used to achieve tasks normally attributed to the C-family of languages - namely, writing a display hardware device driver.
I came across these 0.96in and 2.42in OLED displays based on the SDD1306 and SDD1309 chips and thought it would be fun project to make them work with the micro:bit v2. Sporting only a 5x5 LED display panel, micro:bit's display capabilities are very rudimentary when large amounts of data display is needed. The displays provide 128x64 monochrome panels with plenty of real-estate. They also support both I2C and SPI connectivity.
Connecting the micro:bit and the OLED displays
Depending on the model, the displays may provide either I2C or SPI connectivity, and sometimes both. Here is a summary of how to connect them to the micro:bit with the help of a edge breakout board.
Some displays can be configured for both I2C or SPI connectivity, others support only I2C. I2C requires fewer connections and shares the I2C pins with other I2C devices, but SPI is faster.
NOTE: The displays that work with both I2C or SPI come configured for SPI by default. They require a hardware modification to use I2C connectivity. Users not comfortable making those hardware modifications can stick with SPI.
You'll need Edge Expander board to connect to the micro:bit's I2C or SPI pins. Here are some examples:
The first thing that must be done is to connect the display to the micro:bit v2 using the Edge Expander boards. These boards have both the I2C and the SPI pins already separated and labeled (examples are shown below).
Since there are two different connectivity types (I2C and SPI), we will describe how to connect each one separately.I2C Connections
The micro:bit uses pins 19 and 20 for the I2C bus. The display also needs to be connected to power and ground. For example, on the Keyestudio Edge Expander, the pins are labeled:
G - GroundV2 - 3.3VP19 - Clock (SCK or SCL)P20 - Data (SDA)
NOTE: Different Edge Expander boards label their pins differently:
Ground Pin may be labeled as G, GND; and Voltage Pin may be labeled as V, V1, V2, Vcc, 3.3V, 5V. Some Edge Expanders support both 5V and 3.3V. These displays can operate on either voltage, but 3.3V is preferred.Connections for an I2C only display
An I2C only display (4-pin connector), has these pins:
Make the following connections:
NOTE: You need to obtain FOUR jumper cables of suitable size to reach from the Edge Expander board to the pins on the Display. They also need to be of the correct type (male/female) to provide connectivity between the devices.I2C connections for a combined I2C and SPI display
Displays that support both connectivity types can be identified by a 7-pin connector.
The pins will be labeled:
CS - Chip SelectDC - Data/CommandRES - ResetSDA - DataSCL - ClockVcc - 3.3VGND - Ground
Displays that come with this type of connector are configured to operate in SPI mode by default. They can optionally be controlled using I2C instead by making some a hardware modifications (moving a surface-mount resistor). That process is described in the display hardware documentation.
If you've modified your display to use I2C, make the following connections:
not used CS
not used DC
PIN-8 * RES
(*) While I2C itself uses only 4 wires, displays with 7-pin connectors require an additional connection to the RESET pin of the display to perform a hardware reset of the display.
NOTE: Here, PIN-8 is used as the RESET pin, but any available micro:bit pin can be used instead by changing the reset pin parameter in OLED display initialization command. You need to obtain FOUR jumper cables of suitable size to reach from the Edge Expander board to the pins on the Display. They also need to be of the correct type (male/female) to provide connectivity between the devices.SPI Connection
The micro:bit uses pins 13, 14, and 15 for the SPI bus. On the Keyestudio Edge Expander, for example, the SPI pins are labeled:
G - GroundV2 - 3.3VP13 - Clock (SCK or SCL)P14 - MISO (not used)P15 - MOSIP16 - not used
Make the following connections:
any G CS
PIN-8 * RES
NOTE: Here, PIN-8 is used as the RESET pin, but any available micro:bit pin can be used instead by changing the reset pin parameter in OLED display initialization command.
Standard SPI uses 3 wires to perform a bi-directional data exchange: Clock, MISO (Master-In Slave-Out), MOSI (Master-Out Slave-In). Since this OLED display is an input-only device, the MISO pin is not used. However, the display uses the Data/Control (DC) pin to distinguish between command and data bytes and the RESET pin to perform a hardware reset. Since this project uses only one SPI device, the Chip Select (CS) pin is simply grounded (i.e. the display is always selected).Software
MicroBlocks is a free, Scratch-like blocks programming language for learning physical computing with educational microcontroller boards such as the micro:bit, Adafruit Circuit Playground Express, and many others
While there are other blocks languages for microcontrollers, what really sets MicroBlocks apart is its combination of live programming and autonomous operation. Other blocks languages support one or the other of those features but not both..
Since this project has pretty steep requirements for performance, I chose this platform to do the work. Plus, the platform has built-in communications support for both I2C and SPI, which enabled me to write one set of code to support both display types.
The core requirement and uniqueness of this project is that all the code for the driver will be written in the standard blocks available in MicroBlocks. No other low level pre-compiled libraries are involved, other than the actual IDE and its VM.
To showcase the the functionalities of the OLED driver library, I have written a demo program, OLEDDemoPgm.ubp. This program, another code written in blocks, makes use of the OLED library and demonstrates how to use the various text and graphics capabilities.
Here is a list of the blocks provided by the OLED library:
There are additional advanced functionalities that deal with the lower level hardware and software details. SDD1306 and SDD1309 Reference Guides describe the hardware capabilities implemented in these two display types. This projects materializes most of the main functions, as well as some extra ones that I have decided to include to make things more fun for the target audience.
The OLED library provides support for:
- I2C and SPI connectivity
- Display constrains to any column range
- Horizontal and vertical scrolling by column boundaries
- Brightness adjustments
- Character displays and pixel level graphics displays
- Built-in simple geometric shapes: pixel, lines, circles, rectangles that are generated using the Bresenham algorithm
- Ability to display any image in the conforming hex display format
- Ability to generate, store, and manipulate Sprites by simply clicking on a template
- Normal and inverse video
- Zoom mode (double high display of characters)
- 8x8 character and line-draw set and micro:block's 5x5 characters set are included.
While working on the project, I discovered that the SDD130n chipset did not allow read operations on the display hardware. This presented a problem that did not allow me to create composite images and do simple animations for the games. To overcome this limitation, I decided to implement a virtual graphics buffer in the software, and use it to deposit images, text, and sprites in any combination, as well as have the ability to animate them. The result was a very surprising and highly performant driver that is much fun to use.
To give an idea on the types of performance I have seen:
- 1024 byte display refresh is 4ms (200+ fps)
- Sprite animations are easy at 60+ fps rates
I hope that this project will serve as an example of sophisticated tasks that can be coded using a performant blocks development environment like MicroBlocks.