Created
September 20, 2024 02:21
-
-
Save agrif/1a5ee58959c20b32973b1682054b1f4a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
extern void busy_loop(void); | |
extern volatile uint32_t LEDS; | |
extern volatile struct { | |
struct { | |
bool tx_ready : 1; | |
} control; | |
uint32_t input; | |
uint32_t output; | |
} UART; | |
void uart_send_c(char c) { | |
while (!UART.control.tx_ready); | |
UART.output = c; | |
} | |
void uart_send(const char* s) { | |
for (size_t i = 0; s[i]; i++) { | |
uart_send_c(s[i]); | |
} | |
} | |
#define FIX_POINT 8 | |
#define FIX(v) ((fix16)((v) * (1 << FIX_POINT))) | |
typedef int16_t fix16; | |
fix16 fix_mul(fix16 a, fix16 b) { | |
return ((uint32_t)(a) * (uint32_t)(b)) >> FIX_POINT; | |
} | |
#define DIV_EXTRA FIX_POINT | |
fix16 fix_div(fix16 a, fix16 b) { | |
int32_t r = ((int32_t)(a) << DIV_EXTRA) / (int32_t)(b); | |
if (FIX_POINT > DIV_EXTRA) { | |
return r << (FIX_POINT - DIV_EXTRA); | |
} else { | |
return r >> (DIV_EXTRA - FIX_POINT); | |
} | |
} | |
fix16 fix_pow(fix16 a, unsigned int b) { | |
if (b > 1) { | |
return fix_mul(a, fix_pow(a, b - 1)); | |
} else if (b == 1) { | |
return a; | |
} else { | |
return FIX(1); | |
} | |
} | |
unsigned int mandel(fix16 x, fix16 y, unsigned int max_iter) { | |
fix16 zx = x; | |
fix16 zy = y; | |
for (unsigned int i = 0; i < max_iter; i++) { | |
fix16 zxx = fix_mul(zx, zx); | |
fix16 zyy = fix_mul(zy, zy); | |
if (zxx + zyy > FIX(4)) { | |
unsigned int iter = max_iter - i; | |
return iter > max_iter - 1 ? max_iter - 1 : iter; | |
} | |
zy = 2 * fix_mul(zx, zy) + y; | |
zx = zxx - zyy + x; | |
} | |
return 0; | |
} | |
const char* COLORMAP_PLAIN[] = { | |
" ", "@", "#", "%", | |
"x", "o", ";", ":", | |
",", ".", | |
}; | |
const char* COLORMAP_ANSI[] = { | |
" ", | |
"\033[31;96m@\033[0m", | |
"\033[31;95m#\033[0m", | |
"\033[31;94m%\033[0m", | |
"\033[31;93mx\033[0m", | |
"\033[31;92mo\033[0m", | |
"\033[31;91m;\033[0m", | |
"\033[31;36m:\033[0m", | |
"\033[31;35m,\033[0m", | |
"\033[31;34m.\033[0m", | |
//"\033[31;33m.\033[0m", | |
//"\033[31;32m.\033[0m", | |
//"\033[31;31m.\033[0m", | |
}; | |
#define COLORMAP COLORMAP_ANSI | |
void main(void) { | |
// code assumes width > height | |
const uint8_t width = 160; | |
const uint8_t height = 40; | |
while (true) { | |
uart_send("\r\nRendering...\r\n\r\n"); | |
for (uint8_t yi = 0; yi < height; yi++) { | |
fix16 y = FIX(yi - height / 2); | |
y = fix_div(y, FIX(height / 2)); | |
for (uint8_t xi = 0; xi < width; xi++) { | |
fix16 x = FIX(xi - width / 2); | |
x = fix_div(x, FIX(height / 2)); | |
// compensate for aspect ratio somewhat | |
x = fix_mul(x, FIX(0.5)); | |
// move the whole thing to the right a bit | |
x -= FIX(0.7); | |
unsigned int iters = mandel(x, y, sizeof(COLORMAP) / sizeof(COLORMAP[0])); | |
uart_send(COLORMAP[iters]); | |
} | |
uart_send("\r\n"); | |
} | |
for (int i = 0; i < 100; i++) { | |
busy_loop(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment