Mandelbrot set viewer for the ARM Mbed platform

Dependencies:   mbed DmTftLibrary

Mbed Mandelbrot Viewer

Touch-based mandelbrot set viewer for the ARM Mbed platform. Designed with the NXP LPC1768 and the DisplayModule DM-TFT28-116. It should be easy to adapt for any DisplayModule product, especially if it has an I2C touch controller.

On screen options allow the user to switch between 256*(2^n) maxiters up to 4096, and three rendering kernels using floats, integers, and integers in ARMv7 ASM.

Committer:
ofrasier
Date:
Fri Dec 07 01:00:54 2018 +0000
Revision:
3:835c035b8b1c
Parent:
1:a1d80c69e1f0
Combined ADD-LSL

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ofrasier 1:a1d80c69e1f0 1 #ifndef MANDELBROT_CPP
ofrasier 1:a1d80c69e1f0 2 #define MANDELBROT_CPP
ofrasier 1:a1d80c69e1f0 3
ofrasier 1:a1d80c69e1f0 4 #include "kernels.h"
ofrasier 1:a1d80c69e1f0 5
ofrasier 1:a1d80c69e1f0 6 // Fixed point arithmetic in ASM
ofrasier 1:a1d80c69e1f0 7 void drawASM(Mandelbrot* brot, DmTftBase* screen)
ofrasier 1:a1d80c69e1f0 8 {
ofrasier 1:a1d80c69e1f0 9 int32_t cx; // Original x-coord
ofrasier 1:a1d80c69e1f0 10 int32_t cy; // Original y-coord
ofrasier 1:a1d80c69e1f0 11 uint32_t n; // Iterations
ofrasier 1:a1d80c69e1f0 12
ofrasier 1:a1d80c69e1f0 13 for (uint16_t i = 0; i < brot->width; ++i) {
ofrasier 1:a1d80c69e1f0 14 for (uint16_t j = 0; j < brot->height; ++j) {
ofrasier 1:a1d80c69e1f0 15
ofrasier 1:a1d80c69e1f0 16 // = (([-wh/2 .. wh/2]) / ((wh/4)) = [-2 .. 2] / zoom
ofrasier 1:a1d80c69e1f0 17 cx = ((i-brot->width/2) / ((float)brot->width/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 18 // then add center point and multiply
ofrasier 1:a1d80c69e1f0 19 + brot->centerX) * (1 << 28);
ofrasier 1:a1d80c69e1f0 20 cy = ((j-brot->height/2) / ((float)brot->height/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 21 + brot->centerY) * (1 << 28);
ofrasier 1:a1d80c69e1f0 22
ofrasier 1:a1d80c69e1f0 23 n = escapeTime(cx, cy, brot->maxiters);
ofrasier 1:a1d80c69e1f0 24
ofrasier 1:a1d80c69e1f0 25 uint16_t color = brot->getColor(n);
ofrasier 1:a1d80c69e1f0 26 screen->setPixel(i + brot->x, j + brot->y, color);
ofrasier 1:a1d80c69e1f0 27 }
ofrasier 1:a1d80c69e1f0 28 }
ofrasier 1:a1d80c69e1f0 29 }
ofrasier 1:a1d80c69e1f0 30
ofrasier 1:a1d80c69e1f0 31 // Fixed point arithmetic
ofrasier 1:a1d80c69e1f0 32 void drawCInt(Mandelbrot* brot, DmTftBase* screen)
ofrasier 1:a1d80c69e1f0 33 {
ofrasier 1:a1d80c69e1f0 34 int32_t cx; // Original x-coord
ofrasier 1:a1d80c69e1f0 35 int32_t cy; // Original y-coord
ofrasier 1:a1d80c69e1f0 36 int32_t zx; // Current x-coord
ofrasier 1:a1d80c69e1f0 37 int32_t zy; // Current y-coord
ofrasier 1:a1d80c69e1f0 38 int64_t zxzx; // Squares
ofrasier 1:a1d80c69e1f0 39 int64_t zyzy;
ofrasier 1:a1d80c69e1f0 40 uint32_t n; // Iterations
ofrasier 1:a1d80c69e1f0 41
ofrasier 1:a1d80c69e1f0 42 for (uint16_t i = 0; i < brot->width; ++i) {
ofrasier 1:a1d80c69e1f0 43 for (uint16_t j = 0; j < brot->height; ++j) {
ofrasier 1:a1d80c69e1f0 44
ofrasier 1:a1d80c69e1f0 45 // = (([-wh/2 .. wh/2]) / ((wh/4)) = [-2 .. 2] / zoom
ofrasier 1:a1d80c69e1f0 46 cx = ((i-brot->width/2) / ((float)brot->width/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 47 // then add center point and multiply
ofrasier 1:a1d80c69e1f0 48 + brot->centerX) * (1 << 28);
ofrasier 1:a1d80c69e1f0 49 cy = ((j-brot->height/2) / ((float)brot->height/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 50 + brot->centerY) * (1 << 28);
ofrasier 1:a1d80c69e1f0 51 zx = cx;
ofrasier 1:a1d80c69e1f0 52 zy = cy;
ofrasier 1:a1d80c69e1f0 53
ofrasier 1:a1d80c69e1f0 54 for (n = 0; n < brot->maxiters; ++n) {
ofrasier 1:a1d80c69e1f0 55 zxzx = (int64_t)zx*zx;
ofrasier 1:a1d80c69e1f0 56 zyzy = (int64_t)zy*zy;
ofrasier 1:a1d80c69e1f0 57 if (zxzx + zyzy >= (288230376151711744LL)) {
ofrasier 1:a1d80c69e1f0 58 break;
ofrasier 1:a1d80c69e1f0 59 }
ofrasier 1:a1d80c69e1f0 60 zy = (2*(int64_t)zx*zy) >> 28;
ofrasier 1:a1d80c69e1f0 61 zy += cy;
ofrasier 1:a1d80c69e1f0 62 zx = (zxzx - zyzy) >> 28;
ofrasier 1:a1d80c69e1f0 63 zx += cx;
ofrasier 1:a1d80c69e1f0 64 }
ofrasier 1:a1d80c69e1f0 65
ofrasier 1:a1d80c69e1f0 66 uint16_t color = brot->getColor(n);
ofrasier 1:a1d80c69e1f0 67 screen->setPixel(i + brot->x, j + brot->y, color);
ofrasier 1:a1d80c69e1f0 68 }
ofrasier 1:a1d80c69e1f0 69 }
ofrasier 1:a1d80c69e1f0 70 }
ofrasier 1:a1d80c69e1f0 71
ofrasier 1:a1d80c69e1f0 72 // Floating point arithmetic
ofrasier 1:a1d80c69e1f0 73 void drawCFlt(Mandelbrot* brot, DmTftBase* screen)
ofrasier 1:a1d80c69e1f0 74 {
ofrasier 1:a1d80c69e1f0 75 float cx; // Original x-coord
ofrasier 1:a1d80c69e1f0 76 float cy; // Original y-coord
ofrasier 1:a1d80c69e1f0 77 float zx; // Current x-coord
ofrasier 1:a1d80c69e1f0 78 float zy; // Current y-coord
ofrasier 1:a1d80c69e1f0 79 float zxzx; // Squares
ofrasier 1:a1d80c69e1f0 80 float zyzy;
ofrasier 1:a1d80c69e1f0 81 uint32_t n; // Iterations
ofrasier 1:a1d80c69e1f0 82
ofrasier 1:a1d80c69e1f0 83 for (uint16_t i = 0; i < brot->width; ++i) {
ofrasier 1:a1d80c69e1f0 84 for (uint16_t j = 0; j < brot->height; ++j) {
ofrasier 1:a1d80c69e1f0 85
ofrasier 1:a1d80c69e1f0 86 cx = ((i-brot->width/2) / ((float)brot->width/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 87 // then add center point
ofrasier 1:a1d80c69e1f0 88 + brot->centerX);
ofrasier 1:a1d80c69e1f0 89 cy = ((j-brot->height/2) / ((float)brot->height/4 * brot->zoom)
ofrasier 1:a1d80c69e1f0 90 + brot->centerY);
ofrasier 1:a1d80c69e1f0 91 zx = cx;
ofrasier 1:a1d80c69e1f0 92 zy = cy;
ofrasier 1:a1d80c69e1f0 93
ofrasier 1:a1d80c69e1f0 94 for (n = 0; n < brot->maxiters; ++n) {
ofrasier 1:a1d80c69e1f0 95 zxzx = zx*zx;
ofrasier 1:a1d80c69e1f0 96 zyzy = zy*zy;
ofrasier 1:a1d80c69e1f0 97 if (zxzx + zyzy > 4) {
ofrasier 1:a1d80c69e1f0 98 break;
ofrasier 1:a1d80c69e1f0 99 }
ofrasier 1:a1d80c69e1f0 100 zy = 2*zx*zy + cy;
ofrasier 1:a1d80c69e1f0 101 zx = zxzx - zyzy + cx;
ofrasier 1:a1d80c69e1f0 102 }
ofrasier 1:a1d80c69e1f0 103
ofrasier 1:a1d80c69e1f0 104 uint16_t color = brot->getColor(n);
ofrasier 1:a1d80c69e1f0 105 screen->setPixel(i + brot->x, j + brot->y, color);
ofrasier 1:a1d80c69e1f0 106 }
ofrasier 1:a1d80c69e1f0 107 }
ofrasier 1:a1d80c69e1f0 108 }
ofrasier 1:a1d80c69e1f0 109
ofrasier 1:a1d80c69e1f0 110 #endif