Skip to content

Instantly share code, notes, and snippets.

@todbot
Created March 1, 2022 20:57
Show Gist options
  • Save todbot/6c43fd7d8fc1661372312ab667e29fb5 to your computer and use it in GitHub Desktop.
Save todbot/6c43fd7d8fc1661372312ab667e29fb5 to your computer and use it in GitHub Desktop.
Real-time fractals on ESP32 and composite video out
/*
Real-time fractals on ESP32 and composite video out
1 Mar 2022 - @todbot
Basically just combined this sketch:
https://create.arduino.cc/projecthub/picass01/fractal-mandelbrot-with-arduino-72a2b6
and the "GFX_HelloWorld" sketch from
https://github.com/Roger-random/ESP_8_BIT_composite
Uses ESP_8_BIT_composite color composite video generator library on ESP32.
Connect GPIO25 to signal line, usually the center of composite video plug.
Copyright (c) Roger Cheng
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <ESP_8_BIT_GFX.h>
// A list of 8-bit color values that work well in a cycle.
uint8_t colorCycle[] = {
0xFF, // White
0xFE, // Lowering blue
0xFD,
0xFC, // No blue
0xFD, // Raising blue
0xFE,
0xFF, // White
0xF3, // Lowering green
0xE7,
0xE3, // No green
0xE7, // Raising green
0xF3,
0xFF, // White
0x9F, // Lowering red
0x5F,
0x1F, // No red
0x5F, // Raising red
0x9F,
0xFF
};
// Create an instance of the graphics library
ESP_8_BIT_GFX videoOut(true /* = NTSC */, 8 /* = RGB332 color */);
void setup() {
Serial.begin(115200);
// Initial setup of graphics library
videoOut.begin();
}
double realMin = -2;
double realMax = 1.0;
double imagMin = -1.0;
double imagMax = 1.0;
void loop() {
// Wait for the next frame to minimize chance of visible tearing
videoOut.waitForFrame();
// Clear screen
videoOut.fillScreen(0);
myMandel( realMin, realMax, imagMin, imagMax, 10, 255, 255);
imagMin += 0.01;
imagMax -= 0.01;
}
long startTime = 0;
void myMandel(double realMin, double realMax, double imagMin, double imagMax, int maxIterations, double ySize, double xSize) {
// http://rosettacode.org/wiki/Mandelbrot_set#AWK
startTime = millis();
String myString = "\n\n\n\nrealMin=" + String(realMin) + ", realMax=" + String(realMax) + ", imagMin=" + String(imagMin) + ", imagMax=" + String(imagMax) + ", maxIterations=" + String(maxIterations) + ", startTime=" + String((startTime / 1000.0)) + "s";
Serial.print(myString);
//================================================================
double xStep = (realMax - realMin) / xSize;
double yStep = (imagMax - imagMin) / ySize;
//char* colorChar[] = {"#", "-", ":", "=", "o"}; // darker to lighter?
uint16_t colors[] = { 0xF800, 0x07E0, 0x07FF, 0xF81F, 0x001F, };
int colorsLength = (sizeof(colors) / sizeof(colors[0])) - 1;
//int colorsLength = (sizeof(colorCycle) / sizeof(colorCycle[0])) - 1;
int color = 0;
for (int y = 0; y < ySize; y++) {
//Serial.print("\n");
//switchLED();
double imagY = imagMin + yStep * y;
for (int x = 0; x < xSize; x++) {
double realX = realMin + xStep * x;
double realZ = realX;
double imagZ = imagY;
for (int n = 0; n <= maxIterations; n++) {
color = n;
double a = realZ * realZ;
double b = imagZ * imagZ;
if (a + b > 4.0) break;
imagZ = 2 * realZ * imagZ + imagY;
realZ = a - b + realX;
}
(color == maxIterations ) ? color = 0 : color = color % colorsLength + 1;
videoOut.fillRect(x,y, 2,2, colors[color]);
//videoOut.fillRect(x,y, 2,2, colorCycle[color]);
}
}
//================================================================
long elapseTime = millis() - startTime;
myString = "\nelapseTime=" + String((elapseTime / 1000.0)) + "s";
Serial.print(myString);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment