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.
src/kernels.cpp@3:835c035b8b1c, 2018-12-07 (annotated)
- 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?
User | Revision | Line number | New 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 |