Yet another useless but fun hack: a Mandelbrot engine on a 1.4$ Blue Pill :-)
(Click on picture to play the video)
Things worthy of note:
-
The screen is a 16K IPS color one, driven by an ST7735 controller.
-
The calculation obviously uses fixed-point. The STM32F103C8 is a 32-bit machine, doing single-cycle 32-bit integer multiplication. It can therefore be used to perform nice 6.26 fixed point, which allows us to zoom in real-time in the Mandelbrot set. The FRACT_BITS macro defines the number of fractional bits used (out of a total of 32).
-
The STM32F103C8 has only 20K of SRAM. This means that a full screen page, containing 160x80x2 = 25600 bytes, doesn't fit in memory; and therefore we cannot perform fast memory-to-screen SPI transfers for a full screen.
-
There is a workaround (template parameter entireScreen), where the two screen parts are computed in sequence, and are "blit"-ed in turn to the screen. The visual effect of that is a bit disturbing, though - so by default a smaller 80x80 resolution is used, that does fit in memory. The smaller size helps with the frame rate, too ;-)
-
The number of iterations of the Mandelbrot computation, after which the pixel is considered as belonging in the "lake", is set in the macro ITERATIONS.
-
Adafruit_GFX
'sdrawRGBBitmap
is used - which blasts the buffer's contents over high-speed SPI. This dramatically improved both speed and perceptual quality (no "tearing"). -
The
entireScreen
template parameter is evaluated at compile-time; themandel
function basically exists conceptually in two forms: one computing 2 80x80 windows and SPI-ing them in turn to render on the entire screen, and one with a single 80x80. To decide which form to build, theMakefile
has two targets:make small_screen
(default) andmake big_screen
. -
In the
small_screen
mode, there was enough room to add a frame rate counter. In the video you can see that we start at around 10 frames per second (FPS) and after zooming 1600 times in the middle of a Mandelbrot lake, we end up with 1FPS. -
The Blue Pill is programmed via OpenOCD - which is also used to flash it; the
make openocd
sets things up, after which (a)make upload
will just load and run, where as (b)make flash
will permanently write into flash memory. After that, powering up the microcontroller with 3.3V (as shown in the video) suffices.
Enjoy - and keep tinkering!
P.S. If you want to, you can also checkout my FPGA/VHDL version of Mandelbrot - as well as my SSE / OpenMP / CUDA / XaoS one.