Skip to content

Instantly share code, notes, and snippets.

@agrif
Created September 20, 2024 02:21
Show Gist options
  • Save agrif/1a5ee58959c20b32973b1682054b1f4a to your computer and use it in GitHub Desktop.
Save agrif/1a5ee58959c20b32973b1682054b1f4a to your computer and use it in GitHub Desktop.
#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