pre-readme
BIN
datasheets/SMD291AX50T3.pdf
Normal file
BIN
imgs/twopaths.png
Normal file
After Width: | Height: | Size: 489 B |
1
kicad/stm32card/#auto_saved_files#
Normal file
@ -0,0 +1 @@
|
|||||||
|
/home/indigo/projects/stm32_buisnesscard/kicad/stm32card/_autosave-stm32card.kicad_sch
|
17475
kicad/stm32card/_autosave-stm32card.kicad_sch
Normal file
@ -11,7 +11,7 @@
|
|||||||
"images": 1.0,
|
"images": 1.0,
|
||||||
"pads": 1.0,
|
"pads": 1.0,
|
||||||
"shapes": 1.0,
|
"shapes": 1.0,
|
||||||
"tracks": 1.0,
|
"tracks": 0.27000001072883606,
|
||||||
"vias": 1.0,
|
"vias": 1.0,
|
||||||
"zones": 0.7099999785423279
|
"zones": 0.7099999785423279
|
||||||
},
|
},
|
||||||
|
@ -459,6 +459,7 @@
|
|||||||
"single_global_label": "ignore",
|
"single_global_label": "ignore",
|
||||||
"unannotated": "error",
|
"unannotated": "error",
|
||||||
"unconnected_wire_endpoint": "warning",
|
"unconnected_wire_endpoint": "warning",
|
||||||
|
"undefined_netclass": "error",
|
||||||
"unit_value_mismatch": "error",
|
"unit_value_mismatch": "error",
|
||||||
"unresolved_variable": "error",
|
"unresolved_variable": "error",
|
||||||
"wire_dangling": "error"
|
"wire_dangling": "error"
|
||||||
@ -528,10 +529,10 @@
|
|||||||
"gencad": "",
|
"gencad": "",
|
||||||
"idf": "",
|
"idf": "",
|
||||||
"netlist": "",
|
"netlist": "",
|
||||||
"plot": "../../v3_career_fair/",
|
"plot": "../stm32card_stencil/",
|
||||||
"pos_files": "",
|
"pos_files": "",
|
||||||
"specctra_dsn": "",
|
"specctra_dsn": "",
|
||||||
"step": "",
|
"step": "stm32card.step",
|
||||||
"svg": "",
|
"svg": "",
|
||||||
"vrml": ""
|
"vrml": ""
|
||||||
},
|
},
|
||||||
|
@ -5259,6 +5259,16 @@
|
|||||||
)
|
)
|
||||||
(uuid "3002dedb-2703-489f-882f-bab25b7dda33")
|
(uuid "3002dedb-2703-489f-882f-bab25b7dda33")
|
||||||
)
|
)
|
||||||
|
(text "I finished this in a rush and I'm not sure why I did this.\nR21 should be a short and there needs to be a resistor instead of a diode."
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(at 84.074 149.352 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(uuid "5473d214-3849-47a5-8b2b-db0b7c7e51f5")
|
||||||
|
)
|
||||||
(text "double check voltage diviers, maybe push higher - LCSC!"
|
(text "double check voltage diviers, maybe push higher - LCSC!"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 43.434 -3.556 0)
|
(at 43.434 -3.556 0)
|
||||||
@ -15482,13 +15492,12 @@
|
|||||||
(dnp no)
|
(dnp no)
|
||||||
(uuid "b24b357b-0b8d-43fe-933c-61bdb6083d63")
|
(uuid "b24b357b-0b8d-43fe-933c-61bdb6083d63")
|
||||||
(property "Reference" "R21"
|
(property "Reference" "R21"
|
||||||
(at 104.648 140.97 0)
|
(at 104.902 142.24 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
)
|
)
|
||||||
(justify right)
|
(justify right)
|
||||||
(hide yes)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "10k"
|
(property "Value" "10k"
|
||||||
@ -15498,6 +15507,7 @@
|
|||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
)
|
)
|
||||||
(justify right)
|
(justify right)
|
||||||
|
(hide yes)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0603_1608Metric"
|
(property "Footprint" "Resistor_SMD:R_0603_1608Metric"
|
||||||
|
1
kicad/stm32card/~stm32card.kicad_sch.lck
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"hostname":"indigosDesktop","username":"indigo"}
|
56
kicad/stm32card_stencil/pcb_stencil_gen/kicadExportDxf.py
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Based on https://github.com/KiCad/kicad-source-mirror/blob/master/demos/python_scripts_examples/gen_gerber_and_drill_files_board.py
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from pcbnew import *
|
||||||
|
|
||||||
|
def help():
|
||||||
|
print("Usage: kicadExportDxf.py <board file> [<output dir>]")
|
||||||
|
print(" Default output dir same as the board directory'")
|
||||||
|
|
||||||
|
if len(sys.argv) == 1 or len(sys.argv) > 3:
|
||||||
|
print("Invalid number of arguments.")
|
||||||
|
help()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
filename = sys.argv[1]
|
||||||
|
basename = os.path.dirname(filename)
|
||||||
|
if len(sys.argv) == 3:
|
||||||
|
plotDir = sys.argv[2]
|
||||||
|
else:
|
||||||
|
plotDir = basename
|
||||||
|
plotDir = os.path.abspath(plotDir)
|
||||||
|
|
||||||
|
board = LoadBoard(filename)
|
||||||
|
|
||||||
|
pctl = PLOT_CONTROLLER(board)
|
||||||
|
popt = pctl.GetPlotOptions()
|
||||||
|
|
||||||
|
popt.SetOutputDirectory(plotDir)
|
||||||
|
popt.SetAutoScale(False)
|
||||||
|
popt.SetScale(1)
|
||||||
|
popt.SetMirror(False)
|
||||||
|
popt.SetExcludeEdgeLayer(True)
|
||||||
|
popt.SetScale(1)
|
||||||
|
popt.SetDXFPlotUnits(DXF_PLOTTER.DXF_UNIT_MILLIMETERS)
|
||||||
|
popt.SetDXFPlotPolygonMode(False)
|
||||||
|
|
||||||
|
plot_plan = [
|
||||||
|
# name, id, comment
|
||||||
|
("PasteBottom", B_Paste, "Paste Bottom"),
|
||||||
|
("PasteTop", F_Paste, "Paste top"),
|
||||||
|
("EdgeCuts", Edge_Cuts, "Edges"),
|
||||||
|
]
|
||||||
|
|
||||||
|
for name, id, comment in plot_plan:
|
||||||
|
pctl.SetLayer(id)
|
||||||
|
pctl.OpenPlotfile(name, PLOT_FORMAT_DXF, comment)
|
||||||
|
print('plot {}'.format(pctl.GetPlotFileName()))
|
||||||
|
if pctl.PlotLayer() == False:
|
||||||
|
print("plot error")
|
||||||
|
pctl.ClosePlot()
|
||||||
|
|
||||||
|
sys.exit(0)
|
48
kicad/stm32card_stencil/pcb_stencil_gen/pcbStencilGenerator.scad
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
module stencilFrame(outlineDxf, height, width, clearance) {
|
||||||
|
linear_extrude(height = height)
|
||||||
|
difference() {
|
||||||
|
offset(r = width + clearance) import(file = outlineDxf);
|
||||||
|
offset(r = clearance) import(file = outlineDxf);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module stencilSubstrate(outlineDxf, thickness, frameHeight,
|
||||||
|
frameWidth, frameClearance)
|
||||||
|
{
|
||||||
|
difference() {
|
||||||
|
linear_extrude(height = thickness + frameHeight)
|
||||||
|
offset(r = frameWidth + frameClearance)
|
||||||
|
import(file = outlineDxf);
|
||||||
|
translate([0, 0, thickness])
|
||||||
|
linear_extrude(height = thickness + frameHeight)
|
||||||
|
offset(r = frameClearance)
|
||||||
|
import(file = outlineDxf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module stencil(outlineDxf, holesDxf, thickness = 0.2, frameHeight = 1,
|
||||||
|
frameWidth = 1, frameClearance = 0.1, enlargeHoles = 0.05, front = true)
|
||||||
|
{
|
||||||
|
zScale = front ? -1 : 1;
|
||||||
|
xRotate = front ? 180 : 0;
|
||||||
|
rotate(a = xRotate, v = [1, 0, 0])
|
||||||
|
difference() {
|
||||||
|
scale([1, 1, zScale]) stencilSubstrate(outlineDxf, thickness,
|
||||||
|
frameHeight, frameWidth, frameClearance);
|
||||||
|
linear_extrude(height = 4 * thickness, center = true)
|
||||||
|
offset(delta = enlargeHoles) import(file = holesDxf);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$fa = 0.4;
|
||||||
|
$fs = 0.4;
|
||||||
|
thickness = 0.2;
|
||||||
|
frameHeight = 1;
|
||||||
|
frameWidth = 2;
|
||||||
|
enlargeHoles = 0.0;
|
||||||
|
frameClearance = 0;
|
||||||
|
|
||||||
|
front = true;
|
||||||
|
|
||||||
|
stencil("../stm32card-Edge_Cuts.dxf", "../stm32card-F_Paste.dxf", thickness = thickness, frameHeight = frameHeight,
|
||||||
|
frameWidth = frameWidth, frameClearance = frameClearance, front=front);
|
2570
kicad/stm32card_stencil/stm32card-Edge_Cuts.dxf
Normal file
36
kicad/stm32card_stencil/stm32card-Edge_Cuts.svg
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
width="297.0022mm" height="210.0072mm" viewBox="0.0000 0.0000 297.0022 210.0072">
|
||||||
|
<title>SVG Image created as stm32card-Edge_Cuts.svg date 2025/09/11 14:25:54 </title>
|
||||||
|
<desc>Image generated by PCBNEW </desc>
|
||||||
|
<g style="fill:#000000; fill-opacity:1.0000;stroke:#000000; stroke-opacity:1.0000;
|
||||||
|
stroke-linecap:round; stroke-linejoin:round;"
|
||||||
|
transform="translate(0 0) scale(1 1)">
|
||||||
|
</g>
|
||||||
|
<g style="fill:none;
|
||||||
|
stroke:#000000; stroke-width:0.0500; stroke-opacity:1;
|
||||||
|
stroke-linecap:round; stroke-linejoin:round;">
|
||||||
|
<path d="M137.5645 132.3355
|
||||||
|
L216.4645 132.3355
|
||||||
|
" />
|
||||||
|
<path d="M132.5645 127.3355 A5.0000 5.0000 0.0 0 0 137.5645 132.3355" />
|
||||||
|
<path d="M132.5645 86.5355
|
||||||
|
L132.5645 127.3355
|
||||||
|
" />
|
||||||
|
<path d="M221.4645 86.5355 A5.0000 5.0000 0.0 0 0 216.4645 81.5355" />
|
||||||
|
<path d="M221.4645 127.3355
|
||||||
|
L221.4645 86.5355
|
||||||
|
" />
|
||||||
|
<path d="M216.4645 81.5355
|
||||||
|
L137.5645 81.5355
|
||||||
|
" />
|
||||||
|
<path d="M137.5645 81.5355 A4.9999 4.9999 0.0 0 0 132.5645 86.5355" />
|
||||||
|
<path d="M216.4645 132.3356 A5.0001 5.0001 0.0 0 0 221.4645 127.3355" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
5748
kicad/stm32card_stencil/stm32card-F_Cu.svg
Normal file
After Width: | Height: | Size: 124 KiB |
44570
kicad/stm32card_stencil/stm32card-F_Paste.dxf
Normal file
3696
kicad/stm32card_stencil/stm32card-F_Paste.svg
Normal file
After Width: | Height: | Size: 79 KiB |
@ -1,256 +1,256 @@
|
|||||||
|
c
|
||||||
|
p unoptimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
p unoptimized_times
|
||||||
|
print optimized_times
|
||||||
|
run
|
||||||
|
print optimized_times
|
||||||
|
p unoptimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
p unoptimized_times
|
||||||
|
quit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
qut
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print unoptimized_times
|
||||||
|
print optimized_times
|
||||||
|
print unoptimized_times
|
||||||
|
load
|
||||||
|
c
|
||||||
|
print unoptimized_times
|
||||||
|
print optimized_times
|
||||||
|
dump mod8
|
||||||
|
disassemble
|
||||||
|
disassemble mod8
|
||||||
|
context
|
||||||
|
b mod8
|
||||||
|
b mandelbrot.c:67
|
||||||
|
load
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
b mandelbrot_bordertrace
|
||||||
|
load
|
||||||
|
c
|
||||||
|
print mod8
|
||||||
|
print mod8(1)
|
||||||
|
print mod(1)
|
||||||
|
print mod8(1)
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
b get_neighbor_index
|
||||||
|
c
|
||||||
load
|
load
|
||||||
c
|
c
|
||||||
next
|
next
|
||||||
n
|
print from_pixel + neighbor_index_accl[direction]
|
||||||
print borders
|
print direction
|
||||||
n
|
print from_pixel - win.w
|
||||||
print nei_dir
|
print from_pixel - (win.w + 1)
|
||||||
n
|
print from_pixel + neighbor_index_accl[1]
|
||||||
n
|
print from_pixel - win.w + 1
|
||||||
print nei_dir
|
quit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
b get_neighbor_index
|
||||||
|
c
|
||||||
|
load
|
||||||
|
c
|
||||||
|
next
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print optimized_times
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
print pin
|
||||||
|
print/x pin
|
||||||
|
print/b pin
|
||||||
|
print/x pin
|
||||||
|
c
|
||||||
|
quyit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
print GPIO_EXTI_REG->IDR & BUTTON_MASK
|
||||||
|
print GPIO_EXTI_REG->IDR
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
quit
|
||||||
|
make
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
print pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
p BUTTON_REG_1
|
||||||
|
print/x pin_mult
|
||||||
|
c
|
||||||
|
print/x pin_mult
|
||||||
|
print pin_mult & (pin_mult - 1)
|
||||||
|
print pin
|
||||||
|
print button_reg_1
|
||||||
|
print GPIO_B
|
||||||
|
print BUTTON_R1_MASK
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print fuck1
|
||||||
|
print fuck2
|
||||||
|
print pin_mult
|
||||||
|
next
|
||||||
|
c
|
||||||
|
c
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
print pin_mult
|
||||||
|
print fuck1
|
||||||
|
print fuck1 & BUTTON_R1_MASK
|
||||||
|
c
|
||||||
|
print pin_mult
|
||||||
|
print/x pin_mult
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
c
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
b mandelbrot.c:447
|
||||||
|
c
|
||||||
|
b 55
|
||||||
|
b 372-55
|
||||||
|
b 317
|
||||||
|
c
|
||||||
|
c
|
||||||
|
print GET_X(this_index, win)
|
||||||
|
print x
|
||||||
print this_index
|
print this_index
|
||||||
print pixels[this_index]
|
|
||||||
print framebuffer[this_index]
|
|
||||||
print framebuffer[this_index] & G_MASK
|
|
||||||
print framebuffer[this_index+1] & G_MASK
|
|
||||||
next
|
next
|
||||||
print gchan_info
|
|
||||||
next
|
next
|
||||||
print i
|
|
||||||
print this_coord
|
|
||||||
print get_neighbor_coord(this_coord, nei_dir, scale)
|
|
||||||
print FIXED_TO_DOUBLE(this_coord.r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, nei_dir, scale))
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, nei_dir, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 0, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 0, scale).r) 1
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 0, scale).r), 1
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 0, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 1, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 2, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 3, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 4, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 5, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 6, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 7, scale).r)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 0, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 1, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 2, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 3, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 4, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 5, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 6, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(get_neighbor_coord(this_coord, 7, scale).i)
|
|
||||||
print FIXED_TO_DOUBLE(this_coord.i)
|
|
||||||
c
|
c
|
||||||
c
|
c
|
||||||
|
d
|
||||||
|
d
|
||||||
|
c
|
||||||
|
quit
|
||||||
quit
|
quit
|
||||||
c
|
|
||||||
c
|
c
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
|
quit
|
||||||
c
|
c
|
||||||
quit
|
quit
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
c
|
|
||||||
quit
|
|
||||||
next
|
|
||||||
qiot
|
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
quit
|
quit
|
||||||
|
c
|
||||||
|
print unoptimized_times
|
||||||
|
cat optimized_times
|
||||||
|
|
||||||
|
print optimized_times
|
||||||
|
exit()
|
||||||
|
quit
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
quit
|
||||||
|
c
|
||||||
|
context
|
||||||
|
quit
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
c
|
c
|
||||||
f 2
|
f 2
|
||||||
context
|
print cam
|
||||||
quit
|
quit
|
||||||
c
|
c
|
||||||
quit
|
f 2
|
||||||
c
|
print cam
|
||||||
quit
|
c
|
||||||
'c
|
f 2
|
||||||
c
|
print cam
|
||||||
c
|
c
|
||||||
quit
|
f 2
|
||||||
c
|
print cam
|
||||||
HAL_GPIO_TogglePin
|
c
|
||||||
print HAL_GPIO_TogglePin()
|
print cam
|
||||||
b idle
|
f 2
|
||||||
c
|
print cam
|
||||||
print HAL_GPIO_TogglePin()
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
b idle
|
|
||||||
c
|
|
||||||
next
|
|
||||||
print charging_bat
|
|
||||||
print charging_bat()
|
|
||||||
print charging_batt()
|
|
||||||
b charging_batt
|
|
||||||
c
|
|
||||||
print HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN)
|
|
||||||
print ~HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN)
|
|
||||||
print ~(HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN))
|
|
||||||
print !(HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN))
|
|
||||||
print (HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN))
|
|
||||||
print GPIO_PIN_SET
|
|
||||||
ptype GPIO_PIN_SET
|
|
||||||
quit
|
|
||||||
print HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN)
|
|
||||||
b charging_batt
|
|
||||||
c
|
|
||||||
step
|
|
||||||
quit
|
|
||||||
b idle
|
|
||||||
c
|
|
||||||
next
|
|
||||||
print charing_batt()
|
|
||||||
print charging_batt()
|
|
||||||
print event_peek()
|
|
||||||
next
|
|
||||||
next
|
|
||||||
c
|
|
||||||
next
|
|
||||||
next
|
|
||||||
next
|
|
||||||
b idle
|
|
||||||
d
|
|
||||||
c
|
|
||||||
b idle
|
|
||||||
c
|
|
||||||
next
|
|
||||||
print event_peek
|
|
||||||
print event_peek()
|
|
||||||
print ST7735_wake()
|
|
||||||
b ST7735_wake
|
|
||||||
c
|
|
||||||
c
|
|
||||||
next
|
|
||||||
next
|
|
||||||
next
|
|
||||||
c
|
|
||||||
next
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
b idle.c:23
|
|
||||||
c
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
c
|
|
||||||
print ST7735_sleep()
|
|
||||||
c
|
|
||||||
print ST7735_wake()
|
|
||||||
quit
|
|
||||||
b main
|
|
||||||
c
|
|
||||||
next
|
|
||||||
print ST7735_sleep()
|
|
||||||
print ST7735_wake()
|
|
||||||
exit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
next
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
print on_pixel
|
|
||||||
next
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
next
|
|
||||||
quit
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
print y
|
|
||||||
print x
|
|
||||||
next
|
|
||||||
next
|
|
||||||
print framebuffer[on_pixel] & G_MASK
|
|
||||||
print framebuffer[on_pixel]
|
|
||||||
print framebuffer[on_pixel] & ~G_MASK
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
next
|
|
||||||
next
|
|
||||||
quit
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
step
|
|
||||||
print on_pixel
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
next
|
|
||||||
print border
|
|
||||||
print borders
|
|
||||||
next
|
|
||||||
print iterate(this_coord)
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
print framebuffer[this_index]
|
|
||||||
print framebuffer[this_index] & GCHAN
|
|
||||||
print framebuffer[this_index] & G_MASK
|
|
||||||
print framebuffer[nei_i] & G_MASK
|
|
||||||
print nei_i
|
|
||||||
print framebuffer[nei_i] & G_MASK
|
|
||||||
next
|
|
||||||
print i
|
|
||||||
print colorscheme[i]
|
|
||||||
print ITERS
|
|
||||||
quit
|
|
||||||
c
|
|
||||||
c
|
|
||||||
c
|
|
||||||
c
|
|
||||||
quit
|
|
||||||
quit
|
quit
|
||||||
|
@ -2,6 +2,4 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
void benchmark();
|
||||||
void benchmark_start();
|
|
||||||
void benchmark_stop();
|
|
||||||
|
@ -7,15 +7,26 @@
|
|||||||
TODO move to gpio.h or somethin
|
TODO move to gpio.h or somethin
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define GPIO_EXTI_REG GPIOB
|
#define EVENT_NONE 0
|
||||||
|
|
||||||
|
#define BUTTON_REG_1 GPIOA
|
||||||
|
#define BUTTON_REG_2 GPIOB
|
||||||
|
#define BUTTON_R1_MASK (BUTTON_UP | BUTTON_DOWN | BUTTON_RIGHT | BUTTON_LEFT)
|
||||||
|
#define BUTTON_R2_MASK (BUTTON_A | BUTTON_B)
|
||||||
|
|
||||||
#define BUTTON_UP GPIO_PIN_3
|
#define BUTTON_UP GPIO_PIN_3
|
||||||
#define BUTTON_RIGHT GPIO_PIN_2
|
#define BUTTON_RIGHT GPIO_PIN_2
|
||||||
#define BUTTON_DOWN GPIO_PIN_0
|
#define BUTTON_DOWN GPIO_PIN_0
|
||||||
#define BUTTON_LEFT GPIO_PIN_1
|
#define BUTTON_LEFT GPIO_PIN_1
|
||||||
#define BUTTON_A GPIO_PIN_13
|
#define BUTTON_A GPIO_PIN_13
|
||||||
#define BUTTON_B GPIO_PIN_14
|
#define BUTTON_B GPIO_PIN_14
|
||||||
|
|
||||||
|
#define CHARGING_PORT GPIOB
|
||||||
#define CHARGING_PIN GPIO_PIN_12
|
#define CHARGING_PIN GPIO_PIN_12
|
||||||
#define EVENT_NONE 0
|
|
||||||
|
#define DEMO_NEXTVIEW BUTTON_A | BUTTON_B | BUTTON_RIGHT
|
||||||
|
#define DEMO_LASTVIEW BUTTON_A | BUTTON_B | BUTTON_LEFT
|
||||||
|
#define DEMO_BORDER BUTTON_A | BUTTON_B | BUTTON_UP
|
||||||
|
|
||||||
extern int button;
|
extern int button;
|
||||||
void HAL_GPIO_EXTI_Callback(uint16_t pin);
|
void HAL_GPIO_EXTI_Callback(uint16_t pin);
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void draw_mandelbrot();
|
#define RES_X 160
|
||||||
|
#define RES_Y 80
|
||||||
|
|
||||||
|
struct camera {
|
||||||
|
double min_r, min_i, max_r, max_i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window {
|
||||||
|
unsigned int x0, y0, w, h;
|
||||||
|
};
|
||||||
|
|
||||||
|
void render_loop();
|
||||||
|
void init_colorscheme(uint16_t *scheme);
|
||||||
|
unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, const uint16_t *colorscheme, const struct camera cam, const struct window win);
|
||||||
|
unsigned int mandelbrot_unoptimized(uint16_t *framebuffer, const uint16_t *colorscheme, const struct camera cam, const struct window win);
|
||||||
|
@ -30,138 +30,7 @@ extern SPI_HandleTypeDef ST7735_SPI_PORT;
|
|||||||
#define BACKLIGHT_PORT GPIOB
|
#define BACKLIGHT_PORT GPIOB
|
||||||
#define BACKLIGHT_PIN GPIO_PIN_15
|
#define BACKLIGHT_PIN GPIO_PIN_15
|
||||||
|
|
||||||
// AliExpress/eBay 1.8" display, default orientation
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 160
|
|
||||||
#define ST7735_XSTART 0
|
|
||||||
#define ST7735_YSTART 0
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// AliExpress/eBay 1.8" display, rotate right
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 160
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 0
|
|
||||||
#define ST7735_YSTART 0
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// AliExpress/eBay 1.8" display, rotate left
|
|
||||||
/*
|
|
||||||
shutdown command invoked
|
|
||||||
|
|
||||||
1 indigo@indigosDesktop ~/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1 main ● make && openocd -f i
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 160
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 0
|
|
||||||
#define ST7735_YSTART 0
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// AliExpress/eBay 1.8" display, upside down
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 160
|
|
||||||
#define ST7735_XSTART 0
|
|
||||||
#define ST7735_YSTART 0
|
|
||||||
#define ST7735_ROTATION (0)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// WaveShare ST7735S-based 1.8" display, default orientation
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 160
|
|
||||||
#define ST7735_XSTART 2
|
|
||||||
#define ST7735_YSTART 1
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_RGB)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// WaveShare ST7735S-based 1.8" display, rotate right
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 160
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 1
|
|
||||||
#define ST7735_YSTART 2
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_RGB)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// WaveShare ST7735S-based 1.8" display, rotate left
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 160
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 1
|
|
||||||
#define ST7735_YSTART 2
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_RGB)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// WaveShare ST7735S-based 1.8" display, upside down
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 160
|
|
||||||
#define ST7735_XSTART 2
|
|
||||||
#define ST7735_YSTART 1
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_RGB)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 1.44" display, default orientation
|
|
||||||
/**
|
|
||||||
#define ST7735_IS_128X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 2
|
|
||||||
#define ST7735_YSTART 3
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR)
|
|
||||||
**/
|
|
||||||
|
|
||||||
// 1.44" display, rotate right
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_128X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 3
|
|
||||||
#define ST7735_YSTART 2
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 1.44" display, rotate left
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_128X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 1
|
|
||||||
#define ST7735_YSTART 2
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 1.44" display, upside down
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_128X128 1
|
|
||||||
#define ST7735_WIDTH 128
|
|
||||||
#define ST7735_HEIGHT 128
|
|
||||||
#define ST7735_XSTART 2
|
|
||||||
#define ST7735_YSTART 1
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_BGR)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// mini 160x80 display (it's unlikely you want the default orientation)
|
|
||||||
/*
|
|
||||||
#define ST7735_IS_160X80 1
|
|
||||||
#define ST7735_XSTART 26
|
|
||||||
#define ST7735_YSTART 1
|
|
||||||
#define ST7735_WIDTH 80
|
|
||||||
#define ST7735_HEIGHT 160
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// mini 160x80, rotate left
|
// mini 160x80, rotate left
|
||||||
#define ST7735_IS_160X80 1
|
#define ST7735_IS_160X80 1
|
||||||
@ -171,18 +40,6 @@ shutdown command invoked
|
|||||||
#define ST7735_HEIGHT 80
|
#define ST7735_HEIGHT 80
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
|
#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
|
||||||
|
|
||||||
// mini 160x80, rotate right
|
|
||||||
|
|
||||||
/**
|
|
||||||
#define ST7735_IS_160X80 1
|
|
||||||
#define ST7735_XSTART 1
|
|
||||||
#define ST7735_YSTART 26
|
|
||||||
#define ST7735_WIDTH 160
|
|
||||||
#define ST7735_HEIGHT 80
|
|
||||||
#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR)
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
|
|
||||||
#define ST7735_NOP 0x00
|
#define ST7735_NOP 0x00
|
||||||
|
@ -1,20 +1,77 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include "mandelbrot.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "st7735.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
static float time __attribute__((used));
|
//static float time __attribute__((used));
|
||||||
|
|
||||||
|
//whatever I'm tired of using hal
|
||||||
void benchmark_start() {
|
void benchmark_start() {
|
||||||
TIM4->CNT = 0;
|
TIM4->CNT = 0;
|
||||||
TIM4->CR1 |= TIM_CR1_CEN;
|
TIM4->CR1 |= TIM_CR1_CEN;
|
||||||
}
|
}
|
||||||
void benchmark_stop() {
|
|
||||||
|
float benchmark_stop() {
|
||||||
TIM4->CR1 ^= TIM_CR1_CEN;
|
TIM4->CR1 ^= TIM_CR1_CEN;
|
||||||
time = (float)(TIM4->CNT + 1) * (TIM4->PSC + 1) / HAL_RCC_GetSysClockFreq();
|
return (float)(TIM4->CNT + 1) * (TIM4->PSC + 1) / HAL_RCC_GetSysClockFreq();
|
||||||
BENCHMARK_CHECKTIME:
|
|
||||||
__NOP();
|
|
||||||
// __BKPT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void benchmark() {
|
void benchmark() {
|
||||||
|
uint16_t scheme[256]; //yeah eyah yeah constant scope balalse';hjf v'wef
|
||||||
|
init_colorscheme(scheme);
|
||||||
|
|
||||||
|
const struct camera cases[] = {
|
||||||
|
//shows child mandelbrot at about 1/4th of the screen
|
||||||
|
(struct camera) {1.511138965827779623297, -0.000099833545397436595, 1.513299500557251375810, 0.000980433819429512915},
|
||||||
|
|
||||||
|
//main set taking up most of screen
|
||||||
|
(struct camera) {-1.006631762350983283483, 0.033264514201812478422, 0.159212948008334742589, 0.616186869452269969649},
|
||||||
|
|
||||||
|
//main set taking up a little bit of the screen
|
||||||
|
(struct camera) {-3.860919485929509509248, -1.895171233654595388529, 4.122278116347564136390, 2.096427567968737193382},
|
||||||
|
|
||||||
|
//zoomed in far, set taking up half of screen
|
||||||
|
(struct camera) {0.250175465354113391037, -0.000006169573538442441, 0.250185172171380920680, -0.000001316164904004028},
|
||||||
|
|
||||||
|
//zoomed in far, set taking up none of screen
|
||||||
|
(struct camera) {0.250177970233267155109, -0.000003445496138560340, 0.250181935207702044188, -0.000001463008920807711},
|
||||||
|
|
||||||
|
//half and half, complex border
|
||||||
|
(struct camera) {3.530034617447952438596, -0.011581384229626515842, 3.530490903206738639852, -0.011353241350196253967},
|
||||||
|
|
||||||
|
//complete blackness
|
||||||
|
(struct camera) {-1.097044987707582519576, 0.142802338676453366428, -1.000760853479837342306, 0.190944405713568132743}
|
||||||
|
};
|
||||||
|
|
||||||
|
const int case_cnt = sizeof(cases) / sizeof(*cases);
|
||||||
|
|
||||||
|
static float unoptimized_times[7] __attribute__((used));
|
||||||
|
static float optimized_times[7] __attribute__((used));
|
||||||
|
|
||||||
|
uint16_t framebuffer[(RES_X/2) * RES_Y] = {0};
|
||||||
|
const struct window left_half = {0, 0, 80, 80};
|
||||||
|
const struct window right_half = {80, 0, 80, 80};
|
||||||
|
|
||||||
|
|
||||||
|
for(int case_i = 0; case_i < case_cnt; case_i++) {
|
||||||
|
|
||||||
|
benchmark_start();
|
||||||
|
mandelbrot_bordertrace(framebuffer, scheme, cases[case_i], left_half);
|
||||||
|
ST7735_DrawImage(0, 0, 80, 80, framebuffer);
|
||||||
|
mandelbrot_bordertrace(framebuffer, scheme, cases[case_i], right_half);
|
||||||
|
ST7735_DrawImage(80, 0, 80, 80, framebuffer);
|
||||||
|
optimized_times[case_i] = benchmark_stop();
|
||||||
|
// while(!event_get());
|
||||||
|
|
||||||
|
benchmark_start();
|
||||||
|
mandelbrot_unoptimized(framebuffer, scheme, cases[case_i], left_half);
|
||||||
|
ST7735_DrawImage(0, 0, 80, 80, framebuffer);
|
||||||
|
mandelbrot_unoptimized(framebuffer, scheme, cases[case_i], right_half);
|
||||||
|
ST7735_DrawImage(80, 0, 80, 80, framebuffer);
|
||||||
|
unoptimized_times[case_i] = benchmark_stop();
|
||||||
|
// while(!event_get());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
__BKPT();
|
||||||
|
}
|
||||||
|
@ -2,8 +2,20 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
int gpio_event = EVENT_NONE;
|
int gpio_event = EVENT_NONE;
|
||||||
void HAL_GPIO_EXTI_Callback(uint16_t pin) { gpio_event = pin; }
|
|
||||||
|
void HAL_GPIO_EXTI_Callback(uint16_t pin) {
|
||||||
|
//implimented demo functionality last second; maybe consider moving to a different interrupt
|
||||||
|
uint32_t pin_mult = (((BUTTON_REG_1->IDR) & BUTTON_R1_MASK) | ((BUTTON_REG_2->IDR) & BUTTON_R2_MASK));
|
||||||
|
uint32_t fuck1 = BUTTON_REG_1 -> IDR;
|
||||||
|
uint32_t fuck2 = BUTTON_REG_2 -> IDR;
|
||||||
|
if((pin_mult & (pin_mult - 1))) {
|
||||||
|
gpio_event = pin_mult;
|
||||||
|
}
|
||||||
|
else gpio_event = pin;
|
||||||
|
}
|
||||||
|
|
||||||
int event_get() {
|
int event_get() {
|
||||||
int event = gpio_event;
|
int event = gpio_event;
|
||||||
gpio_event = EVENT_NONE;
|
gpio_event = EVENT_NONE;
|
||||||
@ -12,5 +24,4 @@ int event_get() {
|
|||||||
|
|
||||||
int event_peek() { return gpio_event; }
|
int event_peek() { return gpio_event; }
|
||||||
|
|
||||||
bool charging_batt() { return !HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN); }
|
bool charging_batt() { return HAL_GPIO_ReadPin(CHARGING_PORT, CHARGING_PIN); }
|
||||||
//bool charging_batt() { return ~HAL_GPIO_ReadPin(GPIO_EXTI_REG, CHARGING_PIN); }
|
|
||||||
|
@ -125,9 +125,11 @@ int main(void)
|
|||||||
|
|
||||||
/* Infinite loop */
|
/* Infinite loop */
|
||||||
/* USER CODE BEGIN WHILE */
|
/* USER CODE BEGIN WHILE */
|
||||||
|
// benchmark();
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
draw_mandelbrot();
|
render_loop();
|
||||||
|
// benchmark();
|
||||||
/* USER CODE END WHILE */
|
/* USER CODE END WHILE */
|
||||||
|
|
||||||
/* USER CODE BEGIN 3 */
|
/* USER CODE BEGIN 3 */
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
|
#include "stm32f1xx_hal_spi.h"
|
||||||
|
|
||||||
#define RES_X 160
|
#define RES_X 160
|
||||||
#define RES_Y 80
|
#define RES_Y 80
|
||||||
@ -24,12 +25,6 @@
|
|||||||
#define ITERS 255
|
#define ITERS 255
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
||||||
|
|
||||||
//TODO move to some hardware.h or somethin
|
|
||||||
//channel order: B, G, R
|
|
||||||
#define R_BITS 5
|
|
||||||
#define G_BITS 6
|
|
||||||
#define B_BITS 5
|
|
||||||
|
|
||||||
#define G_MASK 0xe007
|
#define G_MASK 0xe007
|
||||||
|
|
||||||
//imaginary axis set automatically
|
//imaginary axis set automatically
|
||||||
@ -59,24 +54,24 @@ typedef struct {
|
|||||||
int32_t r; int32_t i;
|
int32_t r; int32_t i;
|
||||||
} FixedCord;
|
} FixedCord;
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct window {
|
|
||||||
unsigned int x0, y0, w, h;
|
|
||||||
};
|
|
||||||
|
|
||||||
//C does remainder, not modulo.
|
int mod8(int n) {
|
||||||
//TODO optimize for mod 8. Benchmark
|
//I don't understand how, but somehow just anding the result is slower...?
|
||||||
inline int mod(int n, int d) {
|
//I've got too many things on my plate to disassemble this, but feel free to look into it yourself
|
||||||
int r = n % d;
|
int r = n % 8;
|
||||||
return (r < 0) ? r + d : r;
|
return (r < 0) ? r + 8 : r;
|
||||||
}
|
}
|
||||||
int mod(int n, int d);
|
/**
|
||||||
|
inline __attribute__((forced_inline)) int mod8(int n) {
|
||||||
|
return (n + 8) & 0b111;
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
int mod8(int n);
|
||||||
|
|
||||||
|
|
||||||
inline FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
|
||||||
|
FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
||||||
if((direction == NW) || (direction < E)) from_coord.i += step.i; //up
|
if((direction == NW) || (direction < E)) from_coord.i += step.i; //up
|
||||||
if((direction > N) && (direction < S)) from_coord.r += step.r; //right
|
if((direction > N) && (direction < S)) from_coord.r += step.r; //right
|
||||||
if((direction > E) && (direction < W)) from_coord.i -= step.i; //down
|
if((direction > E) && (direction < W)) from_coord.i -= step.i; //down
|
||||||
@ -87,11 +82,17 @@ FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step
|
|||||||
|
|
||||||
|
|
||||||
size_t get_neighbor_index(size_t from_pixel, int direction, struct window win) {
|
size_t get_neighbor_index(size_t from_pixel, int direction, struct window win) {
|
||||||
//TODO gross since window is no longer constant
|
switch(direction) {
|
||||||
int neighbor_index_accl[8] =
|
case N: return from_pixel - win.w;
|
||||||
{-win.w, -win.w + 1, 1, win.w + 1, win.w, win.w - 1, -1, -win.w - 1};
|
case NE: return from_pixel - win.w + 1;
|
||||||
from_pixel += neighbor_index_accl[direction];
|
case E: return from_pixel + 1;
|
||||||
return from_pixel;
|
case SE: return from_pixel + win.w + 1;
|
||||||
|
case S: return from_pixel + win.w;
|
||||||
|
case SW: return from_pixel + win.w - 1;
|
||||||
|
case W: return from_pixel - 1;
|
||||||
|
case NW: return from_pixel - win.w - 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void detect_borders(bool borders[8], size_t i, struct window win) {
|
void detect_borders(bool borders[8], size_t i, struct window win) {
|
||||||
@ -117,8 +118,6 @@ void detect_borders(bool borders[8], size_t i, struct window win) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum VIEW_MODES { VIEW_UNINIT, VIEW_MANDREL, VIEW_SHIP };
|
|
||||||
|
|
||||||
void init_colorscheme(uint16_t *scheme) {
|
void init_colorscheme(uint16_t *scheme) {
|
||||||
uint16_t *tc = scheme;
|
uint16_t *tc = scheme;
|
||||||
for(unsigned int i = 0; i <= ITERS; i++) {
|
for(unsigned int i = 0; i <= ITERS; i++) {
|
||||||
@ -132,15 +131,6 @@ void init_colorscheme(uint16_t *scheme) {
|
|||||||
scheme[ITERS] = 0;
|
scheme[ITERS] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_colorscheme_ship(uint16_t *scheme) {
|
|
||||||
uint16_t *tc = scheme;
|
|
||||||
for(unsigned int i = 0; i < ITERS; i++) {
|
|
||||||
if((i == 0) || (i == ITERS)) *tc = 0;
|
|
||||||
else *tc = (((i - (128)) << 1)+0x1f) << (5+6);
|
|
||||||
tc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cam_shift(struct camera *cam, double step_r, double step_i) {
|
void cam_shift(struct camera *cam, double step_r, double step_i) {
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
||||||
@ -159,7 +149,7 @@ void cam_zoom(struct camera *cam, double zoom) {
|
|||||||
cam->max_r -= r_scale;
|
cam->max_r -= r_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int __attribute__((always_inline)) iterate(FixedCord c) {
|
int iterate(FixedCord c) {
|
||||||
int32_t z_i = 0;
|
int32_t z_i = 0;
|
||||||
int32_t z_r = 0;
|
int32_t z_r = 0;
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
||||||
@ -182,7 +172,12 @@ inline int __attribute__((always_inline)) iterate(FixedCord c) {
|
|||||||
|
|
||||||
int iterate(FixedCord c);
|
int iterate(FixedCord c);
|
||||||
|
|
||||||
unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme, struct camera cam, const struct window win) {
|
#define GET_X(index, win) (((index) % win.w) + win.x0) //TODO organize
|
||||||
|
#define GET_Y(index, win) ((this_index / (double)win.w) + win.y0)
|
||||||
|
//no reason this needs to be global, this is just a last second addition and I'm in a hurry
|
||||||
|
static bool demo = false;
|
||||||
|
|
||||||
|
unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, const uint16_t *colorscheme, const struct camera cam, const struct window win) {
|
||||||
unsigned int total_iters = 0;
|
unsigned int total_iters = 0;
|
||||||
size_t on_pixel = 0;
|
size_t on_pixel = 0;
|
||||||
bool border_scanning = false;
|
bool border_scanning = false;
|
||||||
@ -214,7 +209,8 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
int i = iterate(c);
|
int i = iterate(c);
|
||||||
total_iters += i;
|
total_iters += i;
|
||||||
framebuffer[on_pixel] = colorscheme[i];
|
framebuffer[on_pixel] = colorscheme[i];
|
||||||
if(i == ITERS) {
|
if(i != ITERS) { framebuffer[on_pixel] |= GCHAN_EXTERNAL; }
|
||||||
|
else {
|
||||||
FixedCord this_coord = c;
|
FixedCord this_coord = c;
|
||||||
size_t this_index = on_pixel;
|
size_t this_index = on_pixel;
|
||||||
bool seperated_from_start = false;
|
bool seperated_from_start = false;
|
||||||
@ -237,11 +233,16 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(nei_dir < 8) {
|
if(nei_dir >= 8) border_scanning = true;
|
||||||
|
else {
|
||||||
while(true) {
|
while(true) {
|
||||||
bzero(nei_presort, sizeof(nei_presort));
|
bzero(nei_presort, sizeof(nei_presort));
|
||||||
bzero(nei_canidate, sizeof(nei_canidate));
|
bzero(nei_canidate, sizeof(nei_canidate));
|
||||||
detect_borders(borders, this_index, win);
|
detect_borders(borders, this_index, win);
|
||||||
|
if(demo) {
|
||||||
|
ST7735_DrawPixel(GET_X(this_index, win), GET_Y(this_index, win), ST7735_GREEN);
|
||||||
|
HAL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
//step 1: check pixels around us, fill in neighbors.
|
//step 1: check pixels around us, fill in neighbors.
|
||||||
|
|
||||||
@ -288,7 +289,7 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(nei_edge_i = -2; nei_edge_i <= 2; nei_edge_i++) {
|
for(nei_edge_i = -2; nei_edge_i <= 2; nei_edge_i++) {
|
||||||
int nei_edge_mod = mod((nei_dir + nei_edge_i), 8);
|
int nei_edge_mod = mod8(nei_dir + nei_edge_i);
|
||||||
if((nei_presort[nei_edge_mod] == GCHAN_EXTERNAL) || borders[nei_edge_mod]) break;
|
if((nei_presort[nei_edge_mod] == GCHAN_EXTERNAL) || borders[nei_edge_mod]) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +297,7 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
if(nei_edge_i > 2) continue;
|
if(nei_edge_i > 2) continue;
|
||||||
|
|
||||||
//narrow bridge scenario
|
//narrow bridge scenario
|
||||||
if(nei_presort[mod((nei_dir + 1), 8)] & nei_presort[mod((nei_dir - 1), 8)] & GCHAN_EXTERNAL)
|
if(nei_presort[mod8(nei_dir + 1)] & nei_presort[mod8(nei_dir - 1)] & GCHAN_EXTERNAL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
edge_cnt++;
|
edge_cnt++;
|
||||||
@ -321,9 +322,7 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else border_scanning = true;
|
|
||||||
}
|
}
|
||||||
else framebuffer[on_pixel] |= GCHAN_EXTERNAL;
|
|
||||||
}
|
}
|
||||||
on_pixel++;
|
on_pixel++;
|
||||||
c.r += scale.r;
|
c.r += scale.r;
|
||||||
@ -334,20 +333,19 @@ unsigned int mandelbrot_bordertrace(uint16_t *framebuffer, uint16_t *colorscheme
|
|||||||
return total_iters;
|
return total_iters;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO rename
|
unsigned int mandelbrot_unoptimized(uint16_t *framebuffer, const uint16_t *colorscheme, const struct camera cam, const struct window win) {
|
||||||
unsigned int render_mandelbrot(uint16_t *framebuffer, uint16_t *colorscheme, struct camera cam, int x0, int y0, int w, int h) {
|
|
||||||
int32_t scale_i = DOUBLE_TO_FIXED((cam.max_i - cam.min_i) / (double)RES_Y);
|
int32_t scale_i = DOUBLE_TO_FIXED((cam.max_i - cam.min_i) / (double)RES_Y);
|
||||||
int32_t scale_r = DOUBLE_TO_FIXED((cam.max_r - cam.min_r) / (double)RES_X);
|
int32_t scale_r = DOUBLE_TO_FIXED((cam.max_r - cam.min_r) / (double)RES_X);
|
||||||
int32_t c_i = DOUBLE_TO_FIXED((((cam.max_i - cam.min_i) * (RES_Y - y0)) / RES_Y) + cam.min_i);
|
int32_t c_i = DOUBLE_TO_FIXED((((cam.max_i - cam.min_i) * (RES_Y - win.y0)) / RES_Y) + cam.min_i);
|
||||||
int32_t c_r0 = DOUBLE_TO_FIXED((((cam.max_r - cam.min_r) * x0) / RES_X) + cam.min_r);
|
int32_t c_r0 = DOUBLE_TO_FIXED((((cam.max_r - cam.min_r) * win.x0) / RES_X) + cam.min_r);
|
||||||
int32_t c_r, z_i, z_r, zn_r, z_r_2, z_i_2;
|
int32_t c_r, z_i, z_r, zn_r, z_r_2, z_i_2;
|
||||||
size_t fb_index = 0;
|
size_t fb_index = 0;
|
||||||
int i;
|
int i;
|
||||||
unsigned int total_iters = 0;
|
unsigned int total_iters = 0;
|
||||||
|
|
||||||
for(int y = y0; y < y0 + h; y++) {
|
for(int y = win.y0; y < win.y0 + win.h; y++) {
|
||||||
c_r = c_r0;
|
c_r = c_r0;
|
||||||
for(int x = x0; x < x0 + w; x++) {
|
for(int x = win.x0; x < win.x0 + win.w; x++) {
|
||||||
z_i = 0;
|
z_i = 0;
|
||||||
z_r = 0;
|
z_r = 0;
|
||||||
for(i = 0; i < ITERS; i++) {
|
for(i = 0; i < ITERS; i++) {
|
||||||
@ -376,36 +374,39 @@ unsigned int render_mandelbrot(uint16_t *framebuffer, uint16_t *colorscheme, str
|
|||||||
#define FB_SIZE_X RES_X/2
|
#define FB_SIZE_X RES_X/2
|
||||||
#define FB_SIZE_Y RES_Y
|
#define FB_SIZE_Y RES_Y
|
||||||
|
|
||||||
//TODO rename
|
|
||||||
void draw_mandelbrot() {
|
void render_loop() {
|
||||||
uint16_t framebuffer[FB_SIZE_X * FB_SIZE_Y];
|
uint16_t framebuffer[FB_SIZE_X * FB_SIZE_Y];
|
||||||
uint16_t columnbuffer[(size_t)(STEP_SIZE * RES_X * RES_Y)];
|
uint16_t columnbuffer[(size_t)(STEP_SIZE * RES_X * RES_Y)];
|
||||||
uint16_t left_line = 0;
|
uint16_t left_line = 0;
|
||||||
//program flow is awful atm becuase I was planning something different; will be improved soon.
|
|
||||||
/**
|
|
||||||
static struct camera cam = {
|
|
||||||
.min_r = CAM_DEF_MIN_R,
|
|
||||||
.max_r = CAM_DEF_MAX_R,
|
|
||||||
.min_i = ((double)RES_Y / RES_X) * CAM_DEF_MIN_R,
|
|
||||||
.max_i = ((double)RES_Y / RES_X) * CAM_DEF_MAX_R,
|
|
||||||
};
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
uint16_t on_slide = 0; //for demo locations
|
||||||
|
struct camera demo_cams[] = {
|
||||||
|
(struct camera) {-1.422917204962495851817, -0.000225276304707995275, -1.422016598199103754041, 0.000225027077043296207},
|
||||||
|
(struct camera) {-1.438263106924943857123, -0.000223747558519589895, -1.436086818463690795156, 0.000864396672238325900},
|
||||||
|
(struct camera) {-0.090225435380407282, -0.64998091931263191, -0.088768020367418904, -0.64925221180605341},
|
||||||
|
(struct camera) {-1.438799496517434883813, -0.001121122635241165663, -1.434096351603858066071, 0.001230449821984478309},
|
||||||
|
(struct camera) {0.281321953633743959688, 0.485607916741705558650, 0.282220985515896194418, 0.486057432682865053764},
|
||||||
|
(struct camera) {1.463643582778787255450, -0.000020491662036057693, 1.463725101406749828925, 0.000020267651948646491}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//TODO change before gifting any cards
|
||||||
struct camera cam = {
|
struct camera cam = {
|
||||||
.min_r = 1.511138965827779623297, .min_i = -0.000099833545397436595, .max_r = 1.513299500557251375810, .max_i = 0.000980433819429512915
|
.min_r = -0.090225435380407282,
|
||||||
|
.min_i = -0.64998091931263191,
|
||||||
|
.max_r = -0.088768020367418904,
|
||||||
|
.max_i = -0.64925221180605341
|
||||||
};
|
};
|
||||||
uint16_t colorscheme[ITERS + 1];
|
uint16_t colorscheme[ITERS + 1];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** yes, I know the following is disgusting. Before I clean it, I just wanna get the general idea out,
|
|
||||||
it's more efficient in that order
|
|
||||||
TODO once you get your idea ironed out, clean code **/
|
|
||||||
|
|
||||||
init_colorscheme(colorscheme);
|
init_colorscheme(colorscheme);
|
||||||
bzero(framebuffer, sizeof(framebuffer));
|
bzero(framebuffer, sizeof(framebuffer));
|
||||||
bzero(columnbuffer, sizeof(columnbuffer));
|
bzero(columnbuffer, sizeof(columnbuffer));
|
||||||
|
|
||||||
|
//ggyaaaagh!!!
|
||||||
|
//I will clean this up later.
|
||||||
while(true) {
|
while(true) {
|
||||||
const int y_offset = STEP_SIZE * FB_SIZE_Y;
|
const int y_offset = STEP_SIZE * FB_SIZE_Y;
|
||||||
const int x_offset = STEP_SIZE * RES_X;
|
const int x_offset = STEP_SIZE * RES_X;
|
||||||
@ -446,14 +447,27 @@ void draw_mandelbrot() {
|
|||||||
cam_zoom(&cam, -ZOOM_SIZE);
|
cam_zoom(&cam, -ZOOM_SIZE);
|
||||||
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
||||||
break;
|
break;
|
||||||
|
case DEMO_NEXTVIEW:
|
||||||
|
cam = demo_cams[(++on_slide % (sizeof(demo_cams) / sizeof(*demo_cams)))];
|
||||||
|
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
||||||
|
break;
|
||||||
|
case DEMO_LASTVIEW:
|
||||||
|
cam = demo_cams[(--on_slide % (sizeof(demo_cams) / sizeof(*demo_cams)))];
|
||||||
|
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
||||||
|
break;
|
||||||
|
case DEMO_BORDER:
|
||||||
|
demo = true;
|
||||||
default:
|
default:
|
||||||
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
||||||
}
|
}
|
||||||
ST7735_DrawImage(left_line, 0, FB_SIZE_X, FB_SIZE_Y, framebuffer);
|
|
||||||
|
if(!demo) ST7735_DrawImage(left_line, 0, FB_SIZE_X, FB_SIZE_Y, framebuffer);
|
||||||
|
|
||||||
left_line = left_line ? 0 : FB_SIZE_X;
|
left_line = left_line ? 0 : FB_SIZE_X;
|
||||||
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
mandelbrot_bordertrace(framebuffer, colorscheme, cam, (struct window){left_line, 0, FB_SIZE_X, FB_SIZE_Y});
|
||||||
ST7735_DrawImage(left_line, 0, FB_SIZE_X, FB_SIZE_Y, framebuffer);
|
if(!demo) ST7735_DrawImage(left_line, 0, FB_SIZE_X, FB_SIZE_Y, framebuffer);
|
||||||
|
|
||||||
|
demo = false;
|
||||||
idle();
|
idle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffuncti
|
|||||||
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
||||||
|
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
CFLAGS += -ggdb -g3
|
CFLAGS += -ggdb -g3 -DNAME=DEBUG_BUILD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# delete file
|
||||||
file build/stm32f1_buisnesscard_v1.elf
|
file build/stm32f1_buisnesscard_v1.elf
|
||||||
target extended localhost:3333
|
target extended localhost:3333
|
||||||
|
|
||||||
|
@ -1,531 +0,0 @@
|
|||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$3 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$4 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be detached.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) [answered Y; input not from terminal]
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = 1.31749451
|
|
||||||
$3 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$4 = 0.183570281
|
|
||||||
$5 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$6 = 0.217522398
|
|
||||||
$7 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
$8 = 0.761290252
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be detached.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) [answered Y; input not from terminal]
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = 1.31749451
|
|
||||||
$3 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$4 = 0.183570281
|
|
||||||
$5 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$6 = 0.217522398
|
|
||||||
$7 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
$8 = 0.761290252
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be detached.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) [answered Y; input not from terminal]
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = 1.31749451
|
|
||||||
$3 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$4 = 0.183570281
|
|
||||||
$5 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$6 = 0.217522398
|
|
||||||
$7 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
$8 = 0.761290252
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be detached.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) [answered Y; input not from terminal]
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = 1.31749451
|
|
||||||
$3 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$4 = 0.183570281
|
|
||||||
$5 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$6 = 0.217522398
|
|
||||||
$7 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
$8 = 0.761290252
|
|
||||||
A debugging session is active.
|
|
||||||
|
|
||||||
Inferior 1 [Remote target] will be detached.
|
|
||||||
|
|
||||||
Quit anyway? (y or n) [answered Y; input not from terminal]
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
benchmark.gdb:49: Error in sourced command file:
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
------- tip of the day (disable with set show-tips off) -------
|
|
||||||
The set show-flags on setting will display CPU flags register in the regs context panel
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
R0 0
|
|
||||||
R1 0x42420000
|
|
||||||
R2 0x12c0c0
|
|
||||||
R3 0x4b03
|
|
||||||
R4 0
|
|
||||||
R5 0x40021000
|
|
||||||
R6 0
|
|
||||||
R7 0x80000000
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0xf8ff
|
|
||||||
SP 0x20005000
|
|
||||||
LR 0xffffffff
|
|
||||||
PC 0x80038e4
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x80038e4 <Reset_Handler> movs r0, r0
|
|
||||||
0x80038e6 <Reset_Handler+2> movs r0, r0
|
|
||||||
0x80038e8 <Reset_Handler+4> movs r0, r0
|
|
||||||
0x80038ea <Reset_Handler+6> movs r0, r0
|
|
||||||
0x80038ec <Reset_Handler+8> movs r0, r0
|
|
||||||
0x80038ee <Reset_Handler+10> movs r0, r0
|
|
||||||
0x80038f0 <Reset_Handler+12> movs r0, r0
|
|
||||||
0x80038f2 <Reset_Handler+14> movs r0, r0
|
|
||||||
0x80038f4 <Reset_Handler+16> movs r0, r0
|
|
||||||
0x80038f6 <Reset_Handler+18> movs r0, r0
|
|
||||||
0x80038f8 <Reset_Handler+20> movs r0, r0
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/startup_stm32f103xb.s:64
|
|
||||||
59 .weak Reset_Handler
|
|
||||||
60 .type Reset_Handler, %function
|
|
||||||
61 Reset_Handler:
|
|
||||||
62
|
|
||||||
63 /* Call the clock system initialization function.*/
|
|
||||||
► 64 bl SystemInit
|
|
||||||
65
|
|
||||||
66 /* Copy the data segment initializers from flash to SRAM */
|
|
||||||
67 ldr r0, =_sdata
|
|
||||||
68 ldr r1, =_edata
|
|
||||||
69 ldr r2, =_sidata
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20005000
|
|
||||||
... ↓ 7 skipped
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x80038e4 Reset_Handler
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Continuing.
|
|
||||||
target not halted
|
|
||||||
target stm32f1x.cpu was not halted when resume was requested
|
|
||||||
Halt timed out, wake up GDB.
|
|
||||||
|
|
||||||
Program received signal SIGINT, Interrupt.
|
|
||||||
Reset_Handler () at startup_stm32f103xb.s:64
|
|
||||||
64 bl SystemInit
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
R0 0
|
|
||||||
R1 0x42420000
|
|
||||||
R2 0x12c0c0
|
|
||||||
R3 0x4b03
|
|
||||||
R4 0
|
|
||||||
R5 0x40021000
|
|
||||||
R6 0
|
|
||||||
R7 0x80000000
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0xf8ff
|
|
||||||
SP 0x20005000
|
|
||||||
LR 0xffffffff
|
|
||||||
PC 0x80038e4
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x80038e4 <Reset_Handler> movs r0, r0
|
|
||||||
0x80038e6 <Reset_Handler+2> movs r0, r0
|
|
||||||
0x80038e8 <Reset_Handler+4> movs r0, r0
|
|
||||||
0x80038ea <Reset_Handler+6> movs r0, r0
|
|
||||||
0x80038ec <Reset_Handler+8> movs r0, r0
|
|
||||||
0x80038ee <Reset_Handler+10> movs r0, r0
|
|
||||||
0x80038f0 <Reset_Handler+12> movs r0, r0
|
|
||||||
0x80038f2 <Reset_Handler+14> movs r0, r0
|
|
||||||
0x80038f4 <Reset_Handler+16> movs r0, r0
|
|
||||||
0x80038f6 <Reset_Handler+18> movs r0, r0
|
|
||||||
0x80038f8 <Reset_Handler+20> movs r0, r0
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/startup_stm32f103xb.s:64
|
|
||||||
59 .weak Reset_Handler
|
|
||||||
60 .type Reset_Handler, %function
|
|
||||||
61 Reset_Handler:
|
|
||||||
62
|
|
||||||
63 /* Call the clock system initialization function.*/
|
|
||||||
► 64 bl SystemInit
|
|
||||||
65
|
|
||||||
66 /* Copy the data segment initializers from flash to SRAM */
|
|
||||||
67 ldr r0, =_sdata
|
|
||||||
68 ldr r1, =_edata
|
|
||||||
69 ldr r2, =_sidata
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20005000
|
|
||||||
... ↓ 7 skipped
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x80038e4 Reset_Handler
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Continuing.
|
|
||||||
target not halted
|
|
||||||
target stm32f1x.cpu was not halted when resume was requested
|
|
||||||
The target is not running when halt was requested, stopping GDB.
|
|
||||||
|
|
||||||
Program received signal SIGINT, Interrupt.
|
|
||||||
Reset_Handler () at startup_stm32f103xb.s:64
|
|
||||||
64 bl SystemInit
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
R0 0
|
|
||||||
R1 0x42420000
|
|
||||||
R2 0x12c0c0
|
|
||||||
R3 0x4b03
|
|
||||||
R4 0
|
|
||||||
R5 0x40021000
|
|
||||||
R6 0
|
|
||||||
R7 0x80000000
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0xf8ff
|
|
||||||
SP 0x20005000
|
|
||||||
LR 0xffffffff
|
|
||||||
PC 0x80038e4
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x80038e4 <Reset_Handler> movs r0, r0
|
|
||||||
0x80038e6 <Reset_Handler+2> movs r0, r0
|
|
||||||
0x80038e8 <Reset_Handler+4> movs r0, r0
|
|
||||||
0x80038ea <Reset_Handler+6> movs r0, r0
|
|
||||||
0x80038ec <Reset_Handler+8> movs r0, r0
|
|
||||||
0x80038ee <Reset_Handler+10> movs r0, r0
|
|
||||||
0x80038f0 <Reset_Handler+12> movs r0, r0
|
|
||||||
0x80038f2 <Reset_Handler+14> movs r0, r0
|
|
||||||
0x80038f4 <Reset_Handler+16> movs r0, r0
|
|
||||||
0x80038f6 <Reset_Handler+18> movs r0, r0
|
|
||||||
0x80038f8 <Reset_Handler+20> movs r0, r0
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/startup_stm32f103xb.s:64
|
|
||||||
59 .weak Reset_Handler
|
|
||||||
60 .type Reset_Handler, %function
|
|
||||||
61 Reset_Handler:
|
|
||||||
62
|
|
||||||
63 /* Call the clock system initialization function.*/
|
|
||||||
► 64 bl SystemInit
|
|
||||||
65
|
|
||||||
66 /* Copy the data segment initializers from flash to SRAM */
|
|
||||||
67 ldr r0, =_sdata
|
|
||||||
68 ldr r1, =_edata
|
|
||||||
69 ldr r2, =_sidata
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20005000
|
|
||||||
... ↓ 7 skipped
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x80038e4 Reset_Handler
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
Detaching from program: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/build/stm32f1_buisnesscard_v1.elf, Remote target
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
benchmark.gdb:49: Error in sourced command file:
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
------- tip of the day (disable with set show-tips off) -------
|
|
||||||
Use the pipe <cmd> | <prog> command to pass output of a GDB/Pwndbg command to a shell program, e.g. pipe elfsections | grep bss. This can also be shortened to: | <cmd> | <prog>
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
R0 0x40
|
|
||||||
R1 0x80
|
|
||||||
R2 1
|
|
||||||
R3 0x20003548
|
|
||||||
R4 0x97
|
|
||||||
R5 6
|
|
||||||
R6 0x8003a20
|
|
||||||
R7 0
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0
|
|
||||||
SP 0x20005000
|
|
||||||
LR 0xffffffff
|
|
||||||
PC 0x80038e4
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x80038e4 <Reset_Handler> bl #SystemInit <SystemInit>
|
|
||||||
|
|
||||||
0x80038e8 <Reset_Handler+4> ldr r0, [pc, #0x2c] R0, [LoopFillZerobss+14]
|
|
||||||
0x80038ea <Reset_Handler+6> ldr r1, [pc, #0x30] R1, [LoopFillZerobss+18]
|
|
||||||
0x80038ec <Reset_Handler+8> ldr r2, [pc, #0x30] R2, [LoopFillZerobss+22]
|
|
||||||
0x80038ee <Reset_Handler+10> movs r3, #0 R3 => 0
|
|
||||||
0x80038f0 <Reset_Handler+12> b #Reset_Handler+20 <Reset_Handler+20>
|
|
||||||
↓
|
|
||||||
0x80038f8 <Reset_Handler+20> adds r4, r0, r3
|
|
||||||
0x80038fa <Reset_Handler+22> cmp r4, r1
|
|
||||||
0x80038fc <Reset_Handler+24> blo #Reset_Handler+14 <Reset_Handler+14>
|
|
||||||
|
|
||||||
0x80038fe <Reset_Handler+26> ldr r2, [pc, #0x24] R2, [LoopFillZerobss+26]
|
|
||||||
0x8003900 <Reset_Handler+28> ldr r4, [pc, #0x24] R4, [LoopFillZerobss+30]
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/startup_stm32f103xb.s:64
|
|
||||||
59 .weak Reset_Handler
|
|
||||||
60 .type Reset_Handler, %function
|
|
||||||
61 Reset_Handler:
|
|
||||||
62
|
|
||||||
63 /* Call the clock system initialization function.*/
|
|
||||||
► 64 bl SystemInit
|
|
||||||
65
|
|
||||||
66 /* Copy the data segment initializers from flash to SRAM */
|
|
||||||
67 ldr r0, =_sdata
|
|
||||||
68 ldr r1, =_edata
|
|
||||||
69 ldr r2, =_sidata
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20005000
|
|
||||||
... ↓ 7 skipped
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x80038e4 Reset_Handler
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Continuing.
|
|
||||||
target not halted
|
|
||||||
target stm32f1x.cpu was not halted when resume was requested
|
|
||||||
|
|
||||||
Program received signal SIGINT, Interrupt.
|
|
||||||
0x08003428 in HAL_PWR_EnterSLEEPMode (Regulator=Regulator@entry=1, SLEEPEntry=SLEEPEntry@entry=1 '\001') at Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c:432
|
|
||||||
432 __WFI();
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
*R0 1
|
|
||||||
*R1 1
|
|
||||||
*R2 0xe000ed00
|
|
||||||
*R3 0
|
|
||||||
*R4 0x2000009c
|
|
||||||
*R5 1
|
|
||||||
*R6 0
|
|
||||||
*R7 0x2000004c
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0
|
|
||||||
*SP 0x20004fc0
|
|
||||||
LR 0x8000ea7
|
|
||||||
*PC 0x8003428
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x8003428 <HAL_PWR_EnterSLEEPMode+24> bx lr <main+478>
|
|
||||||
↓
|
|
||||||
0x8000ea6 <main+478> ldr r5, [pc, #0x7c] R5, [main+604]
|
|
||||||
0x8000ea8 <main+480> ldrb r3, [r5] R3, [button_event]
|
|
||||||
0x8000eaa <main+482> ✔ cbz r3, #main+534 <main+534>
|
|
||||||
↓
|
|
||||||
0x8000ede <main+534> bl #HAL_SuspendTick <HAL_SuspendTick>
|
|
||||||
|
|
||||||
0x8000ee2 <main+538> movs r1, #1 R1 => 1
|
|
||||||
0x8000ee4 <main+540> mov r0, r1
|
|
||||||
0x8000ee6 <main+542> bl #HAL_PWR_EnterSTOPMode <HAL_PWR_EnterSTOPMode>
|
|
||||||
|
|
||||||
0x8000eea <main+546> bl #SystemClock_Config <SystemClock_Config>
|
|
||||||
|
|
||||||
0x8000eee <main+550> bl #HAL_ResumeTick <HAL_ResumeTick>
|
|
||||||
|
|
||||||
0x8000ef2 <main+554> bl #ST7735_wake <ST7735_wake>
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c:432
|
|
||||||
427
|
|
||||||
428 /* Select SLEEP mode entry -------------------------------------------------*/
|
|
||||||
429 if(SLEEPEntry == PWR_SLEEPENTRY_WFI)
|
|
||||||
430 {
|
|
||||||
431 /* Request Wait For Interrupt */
|
|
||||||
► 432 __WFI();
|
|
||||||
433 }
|
|
||||||
434 else
|
|
||||||
435 {
|
|
||||||
436 /* Request Wait For Event */
|
|
||||||
437 __SEV();
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20004fc0
|
|
||||||
01:0004│ 0x20004fc4
|
|
||||||
02:0008│ 0x20004fc8
|
|
||||||
... ↓ 3 skipped
|
|
||||||
06:0018│ 0x20004fd8
|
|
||||||
07:001c│ 0x20004fdc
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x8003428 HAL_PWR_EnterSLEEPMode+24
|
|
||||||
1 0x8000ea6 main+478
|
|
||||||
2 0x8003916 Reset_Handler+50
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
Detaching from program: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/build/stm32f1_buisnesscard_v1.elf, Remote target
|
|
||||||
[Inferior 1 (Remote target) detached]
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
benchmark.gdb:49: Error in sourced command file:
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
------- tip of the day (disable with set show-tips off) -------
|
|
||||||
Use contextprev and contextnext to display a previous context output again without scrolling
|
|
||||||
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
|
|
||||||
───────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────
|
|
||||||
R0 1
|
|
||||||
R1 1
|
|
||||||
R2 0x40007000
|
|
||||||
R3 4
|
|
||||||
R4 0xe000ed00
|
|
||||||
R5 0x20000050
|
|
||||||
R6 0
|
|
||||||
R7 0x2000004c
|
|
||||||
R8 0xffff
|
|
||||||
R9 0x1000
|
|
||||||
R10 0x20000054
|
|
||||||
R11 0x77bdd31d
|
|
||||||
R12 0
|
|
||||||
SP 0x20005000
|
|
||||||
LR 0xffffffff
|
|
||||||
PC 0x80038e4
|
|
||||||
──────────────────[ DISASM / armcm / thumb mode / set emulate on ]──────────────────
|
|
||||||
► 0x80038e4 <Reset_Handler> movs r0, r0
|
|
||||||
0x80038e6 <Reset_Handler+2> movs r0, r0
|
|
||||||
0x80038e8 <Reset_Handler+4> movs r0, r0
|
|
||||||
0x80038ea <Reset_Handler+6> movs r0, r0
|
|
||||||
0x80038ec <Reset_Handler+8> movs r0, r0
|
|
||||||
0x80038ee <Reset_Handler+10> movs r0, r0
|
|
||||||
0x80038f0 <Reset_Handler+12> movs r0, r0
|
|
||||||
0x80038f2 <Reset_Handler+14> movs r0, r0
|
|
||||||
0x80038f4 <Reset_Handler+16> movs r0, r0
|
|
||||||
0x80038f6 <Reset_Handler+18> movs r0, r0
|
|
||||||
0x80038f8 <Reset_Handler+20> movs r0, r0
|
|
||||||
─────────────────────────────────[ SOURCE (CODE) ]──────────────────────────────────
|
|
||||||
In file: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/startup_stm32f103xb.s:64
|
|
||||||
59 .weak Reset_Handler
|
|
||||||
60 .type Reset_Handler, %function
|
|
||||||
61 Reset_Handler:
|
|
||||||
62
|
|
||||||
63 /* Call the clock system initialization function.*/
|
|
||||||
► 64 bl SystemInit
|
|
||||||
65
|
|
||||||
66 /* Copy the data segment initializers from flash to SRAM */
|
|
||||||
67 ldr r0, =_sdata
|
|
||||||
68 ldr r1, =_edata
|
|
||||||
69 ldr r2, =_sidata
|
|
||||||
─────────────────────────────────────[ STACK ]──────────────────────────────────────
|
|
||||||
00:0000│ sp 0x20005000
|
|
||||||
... ↓ 7 skipped
|
|
||||||
───────────────────────────────────[ BACKTRACE ]────────────────────────────────────
|
|
||||||
► 0 0x80038e4 Reset_Handler
|
|
||||||
────────────────────────────────────────────────────────────────────────────────────
|
|
||||||
Error erasing flash with vFlashErase packet
|
|
||||||
Continuing.
|
|
||||||
target not halted
|
|
||||||
target stm32f1x.cpu was not halted when resume was requested
|
|
||||||
shutdown command invoked
|
|
||||||
Remote connection closed
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 14 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
Breakpoint 1 at 0x8000e9a: file Core/Src/main.c, line 129.
|
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
|
||||||
Loading section .isr_vector, size 0x10c lma 0x8000000
|
|
||||||
Loading section .text, size 0x38c0 lma 0x8000110
|
|
||||||
Loading section .rodata, size 0x9c lma 0x80039d0
|
|
||||||
Loading section .init_array, size 0x4 lma 0x8003a6c
|
|
||||||
Loading section .fini_array, size 0x4 lma 0x8003a70
|
|
||||||
Loading section .data, size 0x30 lma 0x8003a74
|
|
||||||
Start address 0x080038e4, load size 15008
|
|
||||||
Transfer rate: 15 KB/sec, 2501 bytes/write.
|
|
||||||
|
|
||||||
Breakpoint 1, main () at Core/Src/main.c:130
|
|
||||||
130 HAL_SuspendTick();
|
|
||||||
$1 = {min_r = -1, min_i = -0.5, max_r = 1, max_i = 0.5}
|
|
||||||
$2 = 1.31749451
|
|
||||||
$3 = {min_r = 3.1577176569116192, min_i = 0.22066305108751161, max_r = 3.1577882779434727, max_i = 0.22069836160343248}
|
|
||||||
$4 = 0.183570281
|
|
||||||
$5 = {min_r = 3.1576023402469482, min_i = 0.22069267606110915, max_r = 3.1576029655564359, max_i = 0.22069298871585336}
|
|
||||||
$6 = 0.217522398
|
|
||||||
$7 = {min_r = 1.5143340717923357, min_i = -1.4054856689592869e-05, max_r = 1.5143697529846534, max_i = 3.7857394692316253e-06}
|
|
||||||
$8 = 0.761290252
|
|
||||||
Quit
|
|
||||||
Detaching from program: /home/indigo/projects/stm32_buisnesscard/program/stm32f1_buisnesscard_v1/build/stm32f1_buisnesscard_v1.elf, Remote target
|
|
||||||
Remote connection closed
|
|
@ -1,201 +0,0 @@
|
|||||||
##########################################################################################################################
|
|
||||||
# File automatically-generated by tool: [projectgenerator] version: [4.5.0-RC5] date: [Sun Apr 27 01:38:15 CDT 2025]
|
|
||||||
##########################################################################################################################
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
|
||||||
# Generic Makefile (based on gcc)
|
|
||||||
#
|
|
||||||
# ChangeLog :
|
|
||||||
# 2017-02-10 - Several enhancements + project update mode
|
|
||||||
# 2015-07-22 - first version
|
|
||||||
# ------------------------------------------------
|
|
||||||
|
|
||||||
######################################
|
|
||||||
# target
|
|
||||||
######################################
|
|
||||||
TARGET = stm32f1_buisnesscard_v1
|
|
||||||
|
|
||||||
|
|
||||||
######################################
|
|
||||||
# building variables
|
|
||||||
######################################
|
|
||||||
# debug build?
|
|
||||||
DEBUG = 1
|
|
||||||
# optimization
|
|
||||||
OPT = -Og -Wall
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# paths
|
|
||||||
#######################################
|
|
||||||
# Build path
|
|
||||||
BUILD_DIR = build
|
|
||||||
|
|
||||||
######################################
|
|
||||||
# source
|
|
||||||
######################################
|
|
||||||
# C sources
|
|
||||||
C_SOURCES = \
|
|
||||||
Core/Src/main.c \
|
|
||||||
Core/Src/stm32f1xx_it.c \
|
|
||||||
Core/Src/stm32f1xx_hal_msp.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
|
|
||||||
Core/Src/system_stm32f1xx.c \
|
|
||||||
Core/Src/sysmem.c \
|
|
||||||
Core/Src/syscalls.c \
|
|
||||||
Core/Src/st7735.c \
|
|
||||||
Core/Src/fonts.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
|
|
||||||
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
|
|
||||||
#Core/Src/mandelbrot.c
|
|
||||||
# ASM sources
|
|
||||||
# ASM sources# ASM sources# ASM sources# ASM sourcesASM_SOURCES = \
|
|
||||||
startup_stm32f103xb.s
|
|
||||||
|
|
||||||
# ASM sources
|
|
||||||
ASMM_SOURCES =
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# binaries
|
|
||||||
#######################################
|
|
||||||
PREFIX = arm-none-eabi-
|
|
||||||
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
|
|
||||||
# either it can be added to the PATH environment variable.
|
|
||||||
ifdef GCC_PATH
|
|
||||||
CC = $(GCC_PATH)/$(PREFIX)gcc
|
|
||||||
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
|
|
||||||
CP = $(GCC_PATH)/$(PREFIX)objcopy
|
|
||||||
SZ = $(GCC_PATH)/$(PREFIX)size
|
|
||||||
else
|
|
||||||
CC = $(PREFIX)gcc
|
|
||||||
AS = $(PREFIX)gcc -x assembler-with-cpp
|
|
||||||
CP = $(PREFIX)objcopy
|
|
||||||
SZ = $(PREFIX)size
|
|
||||||
endif
|
|
||||||
HEX = $(CP) -O ihex
|
|
||||||
BIN = $(CP) -O binary -S
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# CFLAGS
|
|
||||||
#######################################
|
|
||||||
# cpu
|
|
||||||
CPU = -mcpu=cortex-m3
|
|
||||||
|
|
||||||
# fpu
|
|
||||||
# NONE for Cortex-M0/M0+/M3
|
|
||||||
|
|
||||||
# float-abi
|
|
||||||
|
|
||||||
|
|
||||||
# mcu
|
|
||||||
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
|
|
||||||
|
|
||||||
# macros for gcc
|
|
||||||
# AS defines
|
|
||||||
AS_DEFS =
|
|
||||||
|
|
||||||
# C defines
|
|
||||||
C_DEFS = \
|
|
||||||
-DUSE_HAL_DRIVER \
|
|
||||||
-DSTM32F103xB
|
|
||||||
|
|
||||||
|
|
||||||
# AS includes
|
|
||||||
AS_INCLUDES =
|
|
||||||
|
|
||||||
# C includes
|
|
||||||
C_INCLUDES = \
|
|
||||||
-ICore/Inc \
|
|
||||||
-IDrivers/STM32F1xx_HAL_Driver/Inc \
|
|
||||||
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
|
|
||||||
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
|
|
||||||
-IDrivers/CMSIS/Include
|
|
||||||
|
|
||||||
|
|
||||||
# compile gcc flags
|
|
||||||
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
|
||||||
|
|
||||||
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
|
|
||||||
|
|
||||||
ifeq ($(DEBUG), 1)
|
|
||||||
CFLAGS += -ggdb
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
# Generate dependency information
|
|
||||||
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# LDFLAGS
|
|
||||||
#######################################
|
|
||||||
# link script
|
|
||||||
LDSCRIPT = stm32f103c8tx_flash.ld
|
|
||||||
|
|
||||||
# libraries
|
|
||||||
LIBS = -lc -lm -lnosys
|
|
||||||
LIBDIR =
|
|
||||||
#LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
|
|
||||||
LDFLAGS = $(MCU) -ggdb -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
|
|
||||||
|
|
||||||
# default action: build all
|
|
||||||
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# build the application
|
|
||||||
#######################################
|
|
||||||
# list of objects
|
|
||||||
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
|
|
||||||
vpath %.c $(sort $(dir $(C_SOURCES)))
|
|
||||||
# list of ASM program objects
|
|
||||||
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
|
|
||||||
vpath %.s $(sort $(dir $(ASM_SOURCES)))
|
|
||||||
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMM_SOURCES:.S=.o)))
|
|
||||||
vpath %.S $(sort $(dir $(ASMM_SOURCES)))
|
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
|
|
||||||
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
|
|
||||||
$(AS) -c $(CFLAGS) $< -o $@
|
|
||||||
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
|
|
||||||
$(AS) -c $(CFLAGS) $< -o $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
|
|
||||||
$(CC) $(CFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
|
|
||||||
$(SZ) $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
|
|
||||||
$(HEX) $< $@
|
|
||||||
|
|
||||||
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
|
|
||||||
$(BIN) $< $@
|
|
||||||
|
|
||||||
$(BUILD_DIR):
|
|
||||||
mkdir $@
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# clean up
|
|
||||||
#######################################
|
|
||||||
clean:
|
|
||||||
-rm -fR $(BUILD_DIR)
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# dependencies
|
|
||||||
#######################################
|
|
||||||
-include $(wildcard $(BUILD_DIR)/*.d)
|
|
||||||
|
|
||||||
# *** EOF ***
|
|
7
program/stm32f1_buisnesscard_v1/optimization_results
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
before mod change
|
||||||
|
$3 = {0.441072255, 0.427796572, 0.214012727, 1.09791195, 1.38234675, 0.860323548, 0.396820068}
|
||||||
|
$4 = {0.786849678, 1.75887191, 0.250482649, 2.17491865, 2.08977127, 1.37807417, 2.25014758}
|
||||||
|
|
||||||
|
{0.439698875, 0.42016688, 0.212486804, 1.10897517, 1.41301811, 0.844758987, 0.392089635}
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
border tracing - 255 iter only!
|
|
||||||
frame shift
|
|
||||||
change: side that has most iterations is the saved fb
|
|
||||||
benchamrking: make shift benchmark
|
|
6
program/stm32f1_buisnesscard_v1/todo
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
up + down + 2 secs: enable debug mode
|
||||||
|
right: go to next slide
|
||||||
|
up: show border tracing
|
||||||
|
|
||||||
|
enable zoom/pan limits
|
||||||
|
|
@ -1,793 +0,0 @@
|
|||||||
/** READ BEFORE JUDING!
|
|
||||||
* Yes, I know this code is a mess. Debug code is added
|
|
||||||
* happhazardly, two cameras are used, etc.
|
|
||||||
* That's because it's a temporary program
|
|
||||||
* to create optimizations and debug rendering issues without hardware.
|
|
||||||
* None of this is going to be included in the project, and the code is thus
|
|
||||||
* not extensible or organized; it really doesn't save any effort to do so.
|
|
||||||
*
|
|
||||||
* This code is meant for my eyes only. You've been warned!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <complex.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#define WINDOW_SIZE_X 1600
|
|
||||||
#define WINDOW_SIZE_Y 800
|
|
||||||
#define RES_X 160
|
|
||||||
#define RES_Y 80
|
|
||||||
#define DEFAULT_CENTER_X 0
|
|
||||||
#define DEFAULT_CENTER_Y 0
|
|
||||||
#define MOUSE_BUTTON 0
|
|
||||||
#define STEP_SIZE .1
|
|
||||||
#define ZOOM_SIZE .1
|
|
||||||
|
|
||||||
|
|
||||||
#define DECIMAL_LOC 28
|
|
||||||
#define DOUBLE_SCALER (1 << DECIMAL_LOC)
|
|
||||||
#define DOUBLE_TO_FIXED(val) (int32_t)((val) * DOUBLE_SCALER)
|
|
||||||
#define FIXED_MULTIPLY(x,y) ((((uint64_t)(x))*(y)) >> DECIMAL_LOC)
|
|
||||||
#define FIXED_TO_DOUBLE(val) ((val) / (double)DOUBLE_SCALER)
|
|
||||||
|
|
||||||
#define INFTY 2
|
|
||||||
#define INFTY_SQR INFTY * INFTY
|
|
||||||
#define ITERS 255
|
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
|
||||||
|
|
||||||
//#define SHIP
|
|
||||||
//#undef SHIP
|
|
||||||
//#define COLOR_DEBUG
|
|
||||||
|
|
||||||
Color get_color_dbg(int i) {
|
|
||||||
if(i == ITERS) return (Color){0,0,255,255};
|
|
||||||
// if(i == 0) return (Color){255,255,255,255};
|
|
||||||
return (Color){255,0,255,255};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef COLOR_DEBUG
|
|
||||||
#elif SHIP
|
|
||||||
Color get_color(int i) {
|
|
||||||
if(i == ITERS) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
return (Color) {
|
|
||||||
2*(i - 128)+255,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Color get_color(int i) {
|
|
||||||
// if((i == ITERS) || (i == 0)) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == ITERS) return (Color){0,0,0,255};
|
|
||||||
if(i == 0) return (Color){0,0,1,255};
|
|
||||||
if(i < 128) {
|
|
||||||
return (Color) {
|
|
||||||
(8*(i - 128)+255) & 0xff,
|
|
||||||
0,
|
|
||||||
(16*(i - 64)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (Color) {
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
((unsigned int)-2*(i - 128)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//C does remainder, not modulo.
|
|
||||||
//TODO optimize for mod 8
|
|
||||||
inline int mod(int n, int d) {
|
|
||||||
int r = n % d;
|
|
||||||
return (r < 0) ? r + d : r;
|
|
||||||
}
|
|
||||||
int mod(int n, int d);
|
|
||||||
|
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t r; int32_t i;
|
|
||||||
} FixedCord;
|
|
||||||
|
|
||||||
static inline int iterate(FixedCord c) {
|
|
||||||
int32_t z_i = 0;
|
|
||||||
int32_t z_r = 0;
|
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
|
||||||
for(int it = 0; it < ITERS; it++) {
|
|
||||||
z_r_2 = FIXED_MULTIPLY(z_r, z_r);
|
|
||||||
z_i_2 = FIXED_MULTIPLY(z_i, z_i);
|
|
||||||
|
|
||||||
zn_r = z_r_2 - z_i_2 + c.r;
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
zn_i = abs(FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#else
|
|
||||||
zn_i = (FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
z_i = zn_i;
|
|
||||||
z_r = zn_r;
|
|
||||||
|
|
||||||
if(z_i_2 + z_r_2 > INFTY_SQR_FIXED) return it;
|
|
||||||
}
|
|
||||||
return ITERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//blllluuuuurg, matracies and vectors in raylib are floats and we need doubles
|
|
||||||
void shift_cam(struct camera *cam, double step_r, double step_i) {
|
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
|
||||||
cam->min_i += i_offset;
|
|
||||||
cam->max_i += i_offset;
|
|
||||||
cam->min_r += r_offset;
|
|
||||||
cam->max_r += r_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom_cam(struct camera *cam, double zoom) {
|
|
||||||
double i_scale = (cam->max_i - cam->min_i) * zoom;
|
|
||||||
double r_scale = (cam->max_r - cam->min_r) * zoom;
|
|
||||||
cam->min_i += i_scale;
|
|
||||||
cam->max_i -= i_scale;
|
|
||||||
cam->min_r += r_scale;
|
|
||||||
cam->max_r -= r_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DIRECTIONS {
|
|
||||||
N, NE, E, SE, S, SW, W, NW
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//we can inline these if needed
|
|
||||||
|
|
||||||
inline bool bitarray_check(uint8_t *array, size_t i) {
|
|
||||||
return array[i/8] & (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void bitarray_set(uint8_t *array, size_t i) {
|
|
||||||
array[i/8] |= (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
|
||||||
if((direction == NW) || (direction < E)) from_coord.i += step.i;
|
|
||||||
if((direction > N) && (direction < S)) from_coord.r += step.r;
|
|
||||||
if((direction > E) && (direction < W)) from_coord.i -= step.i;
|
|
||||||
if(direction > S) from_coord.r -= step.r;
|
|
||||||
return from_coord;
|
|
||||||
}
|
|
||||||
FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step);
|
|
||||||
|
|
||||||
|
|
||||||
size_t get_neighbor_index(size_t from_pixel, int direction) {
|
|
||||||
const int neighbor_index_accl[8] =
|
|
||||||
{-RES_X, -RES_X + 1, 1, RES_X + 1, RES_X, RES_X - 1, -1, -RES_X - 1};
|
|
||||||
from_pixel += neighbor_index_accl[direction];
|
|
||||||
//canidate for optimization; lots of branches. maybe inline
|
|
||||||
return from_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
//we'll be storing info in the green channel to utalize available memory
|
|
||||||
//per pixel.
|
|
||||||
|
|
||||||
#define BACKSTACK_SIZE 32
|
|
||||||
#define GCHAN_UNRENDERED 0 //don't change; green channel zero'd on cam move
|
|
||||||
#define GCHAN_BLOCKED (1 << 7) //interior element or visiteed
|
|
||||||
#define GCHAN_INTERNAL (1 << 5) //part of set, 0x20
|
|
||||||
#define GCHAN_EXTERNAL (1 << 0) //not part of set, 0x10
|
|
||||||
#define GCHAN_INNER_VISITED (1 << 3)
|
|
||||||
#define GCHAN_INNER_CLOSED (1 << 2)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
void switch_pixel(coord &this_coord, const coord step, size_t this_index, int dir) {
|
|
||||||
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
|
|
||||||
void debug_step(Color *pix, Texture *tex, size_t index, bool pause) {
|
|
||||||
return;
|
|
||||||
// SetTargetFPS(0);
|
|
||||||
static bool fuckin_manual_pause_iguess = false;
|
|
||||||
static Camera2D cam = {0};
|
|
||||||
if(!cam.zoom) cam.zoom = (float)GetRenderWidth()/RES_X;
|
|
||||||
static int debug_color = 0;
|
|
||||||
const float dbg_cam_step = 100;
|
|
||||||
const float dbg_cam_zoom = 1.5;
|
|
||||||
|
|
||||||
(pause || fuckin_manual_pause_iguess) ? SetTargetFPS(60) : SetTargetFPS(0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
cam.offset.y += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
cam.offset.y -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
cam.offset.x += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
cam.offset.x -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
cam.zoom *= dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
cam.zoom /= dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_SPACE:
|
|
||||||
Vector2 mouse_pos = Vector2Multiply(GetMousePosition(), (Vector2){(double)RES_X / WINDOW_SIZE_X, (double)RES_Y / WINDOW_SIZE_Y});
|
|
||||||
//mouse_pos = Vector2Divide(mouse_pos, (Vector2){cam.zoom, cam.zoom});
|
|
||||||
printf("%f, %f (%lu)\n", mouse_pos.x, mouse_pos.y, ((size_t)mouse_pos.y * RES_X) + (size_t)mouse_pos.x);
|
|
||||||
break;
|
|
||||||
case KEY_ENTER:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
pix[index] =
|
|
||||||
(Color) {debug_color, pix[index].g, 0, 255};
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(*tex, pix);
|
|
||||||
DrawTextureEx(*tex, (Vector2)
|
|
||||||
{0 - cam.offset.x, cam.offset.y}, 0,
|
|
||||||
cam.zoom, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
if(!pause && !fuckin_manual_pause_iguess) return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//only need four indecies, however we use 8 because it's more convinient.
|
|
||||||
void detect_borders(bool borders[8], size_t i) {
|
|
||||||
//if this is too slow, it's easy to do it without the modulos.
|
|
||||||
int index_mod = i % RES_X;
|
|
||||||
bzero(borders, sizeof(*borders) * 8);
|
|
||||||
if((i + RES_X) > (RES_X * RES_Y)) {
|
|
||||||
for(int nei_dir = SE; nei_dir <= SW; nei_dir++)
|
|
||||||
borders[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if(((int)i - RES_X) < 0) {
|
|
||||||
borders[NE] = GCHAN_EXTERNAL;
|
|
||||||
borders[N] = GCHAN_EXTERNAL;
|
|
||||||
borders[NW] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
if(index_mod == 0) {
|
|
||||||
for(int nei_dir = SW; nei_dir < NW; nei_dir++)
|
|
||||||
borders[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if(index_mod == (RES_X - 1)) {
|
|
||||||
for(int nei_dir = NE; nei_dir < SE; nei_dir++)
|
|
||||||
borders[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
//runs into occational percision issues
|
|
||||||
if((this_coord.i - scale.i) <= cam_bord_fixed_s) {
|
|
||||||
for(int nei_dir = SE; nei_dir <= SW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.i + scale.i) >= cam_bord_fixed_n) {
|
|
||||||
printf("bruh\n");
|
|
||||||
nei_presort[NE] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[N] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[NW] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
if((this_coord.r - scale.r) <= cam_bord_fixed_w) {
|
|
||||||
for(int nei_dir = SW; nei_dir < NW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.r + scale.r) >= cam_bord_fixed_e) {
|
|
||||||
for(int nei_dir = NE; nei_dir < SE; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_nei_arrays(int *priority, int *presort, size_t index) {
|
|
||||||
int debug_x = index % RES_X;
|
|
||||||
int debug_y = index / RES_X;
|
|
||||||
printf("(%i, %i) %lu: pre [", debug_x, debug_y, index);
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", presort[nd]);
|
|
||||||
printf("], pri [");
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", priority[nd]);
|
|
||||||
printf("]\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SCAN_MODE_NONE,
|
|
||||||
SCAN_MODE_SAFE,
|
|
||||||
SCAN_MODE_INTERIOR
|
|
||||||
} scan_mode;
|
|
||||||
|
|
||||||
unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|
||||||
//these lookup tables r cheap cuz on the stm32f1, 1 memory read is 1 instruction
|
|
||||||
FixedCord scale = {
|
|
||||||
.r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X),
|
|
||||||
.i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y)};
|
|
||||||
FixedCord c = {.r = 0, .i = DOUBLE_TO_FIXED(cam->max_i)};
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
size_t on_pixel = 0;
|
|
||||||
int border_scanning = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture debug_tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
// bzero(pixels, RES_X * RES_Y * sizeof(Color));
|
|
||||||
// for(size_t c = 0; c < (RES_X * RES_Y); c++) pixels[c] = (Color){0,0,0,255};
|
|
||||||
|
|
||||||
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
border_scanning = 0;
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
|
|
||||||
c.r = DOUBLE_TO_FIXED((((on_pixel % RES_X) / (double)RES_X) * (cam->max_r - cam->min_r)) + cam->min_r);
|
|
||||||
c.i = DOUBLE_TO_FIXED((((on_pixel / (double)RES_X) / (double)RES_Y) * (cam->min_i - cam->max_i)) + cam->max_i);
|
|
||||||
|
|
||||||
/**
|
|
||||||
SetTargetFPS(0);
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(debug_tex, pixels);
|
|
||||||
DrawTextureEx(debug_tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
**/
|
|
||||||
|
|
||||||
switch(pixels[on_pixel].g) {
|
|
||||||
case GCHAN_INTERNAL:
|
|
||||||
// printf("starting interior trace...\n");
|
|
||||||
size_t inner_pix_i = on_pixel;
|
|
||||||
int next_pix;
|
|
||||||
bool pass = false;
|
|
||||||
bool start_detached = false;
|
|
||||||
bool touching_start;
|
|
||||||
bool borders[8];
|
|
||||||
int nei_dir;
|
|
||||||
size_t nei_i;
|
|
||||||
|
|
||||||
bool trusted_nei[8];
|
|
||||||
|
|
||||||
{
|
|
||||||
//TODO
|
|
||||||
detect_borders(borders, on_pixel);
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir += 2) if(borders[nei_dir]) break;
|
|
||||||
|
|
||||||
|
|
||||||
int edge_state = 0;
|
|
||||||
bool first_unrendered = false;
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
nei_i = get_neighbor_index(inner_pix_i, nei_dir);
|
|
||||||
if((nei_dir == 0) && (pixels[nei_i].g == GCHAN_UNRENDERED)) first_unrendered = true;
|
|
||||||
if((edge_state & 1) && (pixels[nei_i].g != GCHAN_UNRENDERED)) edge_state++;
|
|
||||||
else if(!(edge_state & 1) && (pixels[nei_i].g == GCHAN_UNRENDERED)) edge_state++;
|
|
||||||
}
|
|
||||||
//tired, easier to think of success states
|
|
||||||
if(!((edge_state == 1)
|
|
||||||
|| ((edge_state == 2) && (!first_unrendered && pixels[nei_i].g != GCHAN_UNRENDERED))
|
|
||||||
|| ((edge_state == 3) && (first_unrendered && pixels[nei_i].g == GCHAN_UNRENDERED)))) break;
|
|
||||||
}
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
nei_i = get_neighbor_index(inner_pix_i, nei_dir);
|
|
||||||
if(pixels[nei_i].g == GCHAN_UNRENDERED) trusted_nei[nei_dir] = true;
|
|
||||||
else trusted_nei[nei_dir] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
detect_borders(borders, inner_pix_i);
|
|
||||||
|
|
||||||
next_pix = -1;
|
|
||||||
touching_start = false;
|
|
||||||
//debug_step(pixels, &debug_tex, inner_pix_i, true);
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
size_t nei_i;
|
|
||||||
size_t localized_dirs[8];
|
|
||||||
|
|
||||||
if(borders[nei_dir]) continue;
|
|
||||||
nei_i = get_neighbor_index(inner_pix_i, nei_dir);
|
|
||||||
if(nei_i == on_pixel) {
|
|
||||||
touching_start = true;
|
|
||||||
if(start_detached) {
|
|
||||||
next_pix = on_pixel;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(pixels[nei_i].g != ((pass) ? GCHAN_INNER_VISITED : GCHAN_INTERNAL)) continue;
|
|
||||||
//if((pixels[nei_i].g == GCHAN_UNRENDERED) || (pixels[nei_i].g == ((pass) ? GCHAN_INNER_CLOSED : GCHAN_INNER_VISITED))) continue;
|
|
||||||
|
|
||||||
for(int i = 0; i < 8; i++) localized_dirs[i] = mod(nei_dir + i, 8);
|
|
||||||
if(!(trusted_nei[localized_dirs[2]] || trusted_nei[localized_dirs[1]] ||
|
|
||||||
trusted_nei[localized_dirs[6]] || trusted_nei[localized_dirs[7]])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/** TODO if we have time, we can only keep track of safe borders when we get in trouble by looking at
|
|
||||||
the past pixel. This has a lot of overhead, but I did it before thinking & I'm out of resources.
|
|
||||||
**/
|
|
||||||
trusted_nei[localized_dirs[4]] = false;
|
|
||||||
trusted_nei[localized_dirs[3]] = trusted_nei[localized_dirs[2]];
|
|
||||||
trusted_nei[localized_dirs[2]] = trusted_nei[localized_dirs[1]];
|
|
||||||
trusted_nei[localized_dirs[5]] = trusted_nei[localized_dirs[6]];
|
|
||||||
trusted_nei[localized_dirs[6]] = trusted_nei[localized_dirs[7]];
|
|
||||||
{
|
|
||||||
bool front_neighbors[5];
|
|
||||||
bool local_borders[8];
|
|
||||||
detect_borders(local_borders, nei_i);
|
|
||||||
for(int nei_edge_dir = -1; nei_edge_dir <= 1; nei_edge_dir++) {
|
|
||||||
size_t nei_edge_local = mod(nei_dir + nei_edge_dir, 8);
|
|
||||||
front_neighbors[nei_edge_dir + 1] =
|
|
||||||
!(local_borders[nei_edge_local] || (pixels[get_neighbor_index(nei_i, nei_edge_local)].g != GCHAN_UNRENDERED));
|
|
||||||
}
|
|
||||||
front_neighbors[3] = trusted_nei[localized_dirs[6]];
|
|
||||||
front_neighbors[4] = trusted_nei[localized_dirs[2]];
|
|
||||||
trusted_nei[localized_dirs[7]] = (front_neighbors[0] && (front_neighbors[3] ||
|
|
||||||
(front_neighbors[1] && front_neighbors[2] && front_neighbors[4])));
|
|
||||||
trusted_nei[localized_dirs[1]] = (front_neighbors[2] && (front_neighbors[4] ||
|
|
||||||
(front_neighbors[0] && front_neighbors[1] && front_neighbors[3])));
|
|
||||||
trusted_nei[localized_dirs[0]] = (front_neighbors[1] && (trusted_nei[localized_dirs[1]] ||
|
|
||||||
trusted_nei[localized_dirs[7]]));
|
|
||||||
}
|
|
||||||
next_pix = nei_i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!start_detached && !touching_start && !(inner_pix_i == on_pixel)) start_detached = true;
|
|
||||||
else if(start_detached && touching_start) {
|
|
||||||
start_detached = false;
|
|
||||||
if(pass) {
|
|
||||||
pixels[inner_pix_i].g = GCHAN_INNER_CLOSED;
|
|
||||||
pixels[touching_start].g = GCHAN_INNER_CLOSED;
|
|
||||||
border_scanning = true;
|
|
||||||
debug_step(pixels, &debug_tex, inner_pix_i, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pass = true;
|
|
||||||
pixels[inner_pix_i].g = GCHAN_INNER_VISITED;
|
|
||||||
inner_pix_i = on_pixel;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pixels[inner_pix_i].g = ((pass) ? GCHAN_INNER_CLOSED : GCHAN_INNER_VISITED);
|
|
||||||
//TODO remove
|
|
||||||
if(pass) pixels[next_pix].r = 0xff;
|
|
||||||
else { pixels[next_pix].b = 0xaa; }
|
|
||||||
|
|
||||||
if(next_pix < 0) {
|
|
||||||
debug_step(pixels, &debug_tex, inner_pix_i, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
inner_pix_i = next_pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GCHAN_UNRENDERED:
|
|
||||||
if(border_scanning) {
|
|
||||||
//pixels[on_pixel] = get_color(ITERS);
|
|
||||||
//printf("interior\n");
|
|
||||||
pixels[on_pixel] = (Color){0xfe,0,0xfe,0xff};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//printf("rendering %i, %i (%lu)\n", x, y, on_pixel);
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[on_pixel] = get_color(i);
|
|
||||||
if(i == ITERS) {
|
|
||||||
FixedCord this_coord = c;
|
|
||||||
size_t this_index = on_pixel;
|
|
||||||
bool seperated_from_start = false;
|
|
||||||
int nei_priority[8];
|
|
||||||
int last_nei_priority[8];
|
|
||||||
int nei_presort[8];
|
|
||||||
|
|
||||||
size_t backstack[BACKSTACK_SIZE];
|
|
||||||
size_t backstack_i = 0;
|
|
||||||
int backstack_calls = 0;
|
|
||||||
|
|
||||||
int nei_dir;
|
|
||||||
|
|
||||||
debug_step(pixels, &debug_tex, this_index, false);
|
|
||||||
bool debug_mode = false;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool borders[8];
|
|
||||||
detect_borders(borders, inner_pix_i);
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
size_t nei_i;
|
|
||||||
if(borders[nei_dir]) break;
|
|
||||||
nei_i = get_neighbor_index(on_pixel, nei_dir);
|
|
||||||
if(pixels[nei_i].g & GCHAN_EXTERNAL) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nei_dir >= 8) {
|
|
||||||
border_scanning = SCAN_MODE_INTERIOR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
detect_borders(borders, this_index);
|
|
||||||
debug_step(pixels, &debug_tex, this_index, false);
|
|
||||||
if(debug_mode) debug_step(pixels, &debug_tex, on_pixel, debug_mode);
|
|
||||||
|
|
||||||
//step 1: check pixels around us, fill in neighbors.
|
|
||||||
bzero(nei_presort, sizeof(nei_presort));
|
|
||||||
|
|
||||||
this_coord.r = DOUBLE_TO_FIXED((((this_index % RES_X) / (double)RES_X) * (cam->max_r - cam->min_r)) + cam->min_r);
|
|
||||||
this_coord.i = DOUBLE_TO_FIXED((((this_index / (double)RES_X) / (double)RES_Y) * (cam->min_i - cam->max_i)) + cam->max_i);
|
|
||||||
/** now fill in neighbor info based on green channel,
|
|
||||||
* iterate if no info available.
|
|
||||||
* if this is to slow we could flatten this; it's predictable
|
|
||||||
* where there will be info
|
|
||||||
**/
|
|
||||||
// TODO replace modulos with bitwise ops
|
|
||||||
bool start_is_nei = false;
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
size_t nei_i;
|
|
||||||
uint8_t gchan_info;
|
|
||||||
|
|
||||||
//happens if we're pushed against the screen
|
|
||||||
if(borders[nei_dir]) {
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nei_i = get_neighbor_index(this_index, nei_dir);
|
|
||||||
gchan_info = pixels[nei_i].g;
|
|
||||||
if(nei_i == on_pixel) start_is_nei = true;
|
|
||||||
//note that when we move this over, there will be no alpha channel.
|
|
||||||
//gchan_info will be extracted differently!!!
|
|
||||||
if(gchan_info) nei_presort[nei_dir] = gchan_info;
|
|
||||||
else {
|
|
||||||
int i = iterate(get_neighbor_coord(this_coord, nei_dir, scale));
|
|
||||||
pixels[nei_i] = get_color(i);
|
|
||||||
if(i == ITERS) nei_presort[nei_dir] = GCHAN_INTERNAL;
|
|
||||||
else {
|
|
||||||
//exterior
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
pixels[nei_i].g = nei_presort[nei_dir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!start_is_nei && !seperated_from_start && (this_index != on_pixel)) seperated_from_start = true;
|
|
||||||
if(start_is_nei && seperated_from_start) {
|
|
||||||
//printf("success!\n");
|
|
||||||
pixels[this_index].g = GCHAN_BLOCKED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//go back if we're in the interior and not an edge
|
|
||||||
int edge_cnt = 0;
|
|
||||||
//sort into prioraties
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
int nei_edge_i;
|
|
||||||
if(nei_presort[nei_dir] != GCHAN_INTERNAL) {
|
|
||||||
nei_priority[nei_dir] = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO rename nei_edge_i
|
|
||||||
//printf("%i: \n", nei_dir);
|
|
||||||
for(nei_edge_i = -2; nei_edge_i <= 2; nei_edge_i++) {
|
|
||||||
int nei_edge_mod = mod((nei_dir + nei_edge_i), 8);
|
|
||||||
if((nei_presort[nei_edge_mod] == GCHAN_EXTERNAL) || borders[nei_edge_mod]) break;
|
|
||||||
}
|
|
||||||
if(nei_edge_i > 2) {
|
|
||||||
//no edge found
|
|
||||||
nei_priority[nei_dir] = -2; //TODO test; remove interior check if nessesary
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//narrow bridge scenario
|
|
||||||
if(nei_presort[mod((nei_dir + 1), 8)] & nei_presort[mod((nei_dir - 1), 8)] & GCHAN_EXTERNAL) {
|
|
||||||
nei_i = get_neighbor_index(this_index, nei_dir);
|
|
||||||
//pixels[nei_i] = (Color) {0xff, pixels[nei_i].g, 0x00, 0xff};
|
|
||||||
nei_priority[nei_dir] = -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
edge_cnt++;
|
|
||||||
nei_priority[nei_dir] = 0;
|
|
||||||
}
|
|
||||||
if(edge_cnt >= 2) {
|
|
||||||
backstack[backstack_i++ % BACKSTACK_SIZE] = this_index;
|
|
||||||
//printf("backstack increased\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//now go to canidate with lowest prioraty
|
|
||||||
pixels[this_index].g = GCHAN_BLOCKED;
|
|
||||||
for(int priority = 0; priority <= 5; priority++) { //TODO we might not need the priority system anymore
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
if(nei_priority[nei_dir] != priority) continue;
|
|
||||||
backstack_calls = 0;
|
|
||||||
this_index = get_neighbor_index(this_index, nei_dir);
|
|
||||||
this_coord = get_neighbor_coord(this_coord, nei_dir, scale);
|
|
||||||
//printf("--> (%zu, %zu)\n", this_index % RES_X, this_index / RES_X);
|
|
||||||
goto NEXT_PIXEL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if((backstack_calls++ > BACKSTACK_SIZE) || (backstack_i < 1)) { //please don't cause issues...
|
|
||||||
//printf("cycled through backstack, questionable success...\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this_index = backstack[--backstack_i % BACKSTACK_SIZE];
|
|
||||||
NEXT_PIXEL:
|
|
||||||
memcpy(last_nei_priority, nei_priority, sizeof(nei_priority));
|
|
||||||
}
|
|
||||||
debug_step(pixels, &debug_tex, this_index, true);
|
|
||||||
}
|
|
||||||
else pixels[on_pixel].g = GCHAN_EXTERNAL;
|
|
||||||
break;
|
|
||||||
case GCHAN_INNER_CLOSED:
|
|
||||||
//printf("bruh\n");
|
|
||||||
if(((x + 2) < RES_X) && (pixels[on_pixel + 1].g == GCHAN_UNRENDERED)) border_scanning = SCAN_MODE_NONE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
border_scanning = SCAN_MODE_NONE;
|
|
||||||
}
|
|
||||||
on_pixel++;
|
|
||||||
c.r += scale.r;
|
|
||||||
//printf("%u\n", on_pixel);
|
|
||||||
}
|
|
||||||
border_scanning = false;
|
|
||||||
}
|
|
||||||
debug_step(pixels, &debug_tex, 0, true);
|
|
||||||
for(size_t i = 0; i < (RES_X * RES_Y); i++) pixels[i].g = 0;
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mandelbrot_unoptimized(struct camera *cam, Color *pixels) {
|
|
||||||
FixedCord scale = {
|
|
||||||
.r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X),
|
|
||||||
.i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y)};
|
|
||||||
FixedCord c = { .r = DOUBLE_TO_FIXED(cam->min_r), .i = DOUBLE_TO_FIXED(cam->max_i) };
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
size_t on_pixel = 0;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
c.r = DOUBLE_TO_FIXED((((on_pixel % RES_X) / (double)RES_X) * (cam->max_r - cam->min_r)) + cam->min_r);
|
|
||||||
c.i = DOUBLE_TO_FIXED((((on_pixel / (double)RES_X) / (double)RES_Y) * (cam->min_i - cam->max_i)) + cam->max_i);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[((y * RES_X) + x)] = get_color(i);
|
|
||||||
on_pixel++;
|
|
||||||
// c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
//test();
|
|
||||||
//return 0;
|
|
||||||
Color *pixels_unoptimized = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
Color *pixels_optimized = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
bool optimized = true;
|
|
||||||
//(1.514379082621093886019, 0.000033222739567139065) - (1.514381385800912305228, 0.000034374329476534746)
|
|
||||||
|
|
||||||
struct camera cam_default = {
|
|
||||||
.min_r = -1,
|
|
||||||
.max_r = 1
|
|
||||||
};
|
|
||||||
cam_default.min_i = ((double)RES_Y / RES_X) * cam_default.min_r;
|
|
||||||
cam_default.max_i = ((double)RES_Y / RES_X) * cam_default.max_r;
|
|
||||||
|
|
||||||
|
|
||||||
//done
|
|
||||||
//.min_r = 0.340060821337554164412, .min_i = -0.076399869494282027227, .max_r = 0.340671385211165078655, .max_i = -0.076094587557451340287
|
|
||||||
|
|
||||||
//done
|
|
||||||
//.min_r = 0.348347456407892719366, .min_i = -0.092130353675640097588, .max_r = 0.349033773135021985201, .max_i = -0.091787195312047098472
|
|
||||||
|
|
||||||
|
|
||||||
//has internal noise
|
|
||||||
//.min_r = 0.348416088080605645949, .min_i = -0.092130353675640097588, .max_r = 0.349102404807734911785, .max_i = -0.091787195312047098472
|
|
||||||
|
|
||||||
//needs diagnol transfer
|
|
||||||
//.min_r = 0.352126044212195454808, .min_i = -0.101818891004586714599, .max_r = 0.354169737175103083171, .max_i = -0.100797044523048578979
|
|
||||||
|
|
||||||
//works
|
|
||||||
//.min_r = 1.514379082621093886019, .min_i = 0.000033222739567139065, .max_r = 1.514381385800912305228, .max_i = 0.000034374329476534746
|
|
||||||
|
|
||||||
// unusual issue; complete rendered border
|
|
||||||
// .min_r = 0.426539347230382670517, .min_i = 0.218210183100018217939, .max_r = 0.427445609943903681582, .max_i = 0.218663314456816582076
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct camera cam = {
|
|
||||||
//.min_r = 0.348416088080605645949, .min_i = -0.092130353675640097588, .max_r = 0.349102404807734911785, .max_i = -0.091787195312047098472
|
|
||||||
.min_r = 0.348347456407892719366, .min_i = -0.092130353675640097588, .max_r = 0.349033773135021985201, .max_i = -0.091787195312047098472
|
|
||||||
};
|
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
|
||||||
SetTraceLogLevel(LOG_ERROR);
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
|
|
||||||
SetTargetFPS(60);
|
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
shift_cam(&cam, 0, STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
shift_cam(&cam, 0, -STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
shift_cam(&cam, STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
shift_cam(&cam, -STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
zoom_cam(&cam, ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
zoom_cam(&cam, -ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_SPACE:
|
|
||||||
optimized = !optimized;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
EndDrawing();
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf(".min_r = %.21f, .min_i = %.21f, .max_r = %.21f, .max_i = %.21f\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
|
||||||
|
|
||||||
|
|
||||||
clock_t begin, end;
|
|
||||||
double time_unoptimized;
|
|
||||||
double time_optimized;
|
|
||||||
|
|
||||||
for(int i = 0; i < (RES_X * RES_Y); i++) { pixels_unoptimized[i] = (Color){0, 0, 0, 0xff}; }
|
|
||||||
for(int i = 0; i < (RES_X * RES_Y); i++) { pixels_optimized[i] = (Color){0, 0, 0, 0xff}; }
|
|
||||||
|
|
||||||
begin = clock();
|
|
||||||
unsigned int unoptimized_iters = mandelbrot_unoptimized(&cam, pixels_unoptimized);
|
|
||||||
end = clock();
|
|
||||||
|
|
||||||
time_unoptimized = (double)(end - begin) / CLOCKS_PER_SEC;
|
|
||||||
printf("Unoptimized: %u iterations, %f seconds\n", unoptimized_iters, time_unoptimized);
|
|
||||||
|
|
||||||
begin = clock();
|
|
||||||
unsigned int optimized_iters = mandelbrot_bordertrace(&cam, pixels_optimized);
|
|
||||||
end = clock();
|
|
||||||
|
|
||||||
time_optimized = (double)(end - begin) / CLOCKS_PER_SEC;
|
|
||||||
printf("Border tracing: %u iterations, %f seconds\n", optimized_iters, time_optimized);
|
|
||||||
|
|
||||||
printf("border tracing does %f%% of nieve approach\n", ((float)optimized_iters / unoptimized_iters) * 100);
|
|
||||||
|
|
||||||
BeginDrawing();
|
|
||||||
printf("%s\n", optimized ? "optimized mode" : "unoptimized mode");
|
|
||||||
UpdateTexture(tex, optimized ? pixels_optimized : pixels_unoptimized);
|
|
||||||
DrawTextureEx(tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,204 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#define WINDOW_SIZE_X 1600
|
|
||||||
#define WINDOW_SIZE_Y 800
|
|
||||||
#define RES_X 160
|
|
||||||
#define RES_Y 80
|
|
||||||
#define DEFAULT_CENTER_X 0
|
|
||||||
#define DEFAULT_CENTER_Y 0
|
|
||||||
#define MOUSE_BUTTON 0
|
|
||||||
#define STEP_SIZE .1
|
|
||||||
#define ZOOM_SIZE .1
|
|
||||||
|
|
||||||
|
|
||||||
#define DECIMAL_LOC 28
|
|
||||||
#define DOUBLE_SCALER (1 << DECIMAL_LOC)
|
|
||||||
#define DOUBLE_TO_FIXED(val) (int32_t)((val) * DOUBLE_SCALER)
|
|
||||||
#define FIXED_MULTIPLY(x,y) ((((uint64_t)(x))*(y)) >> DECIMAL_LOC)
|
|
||||||
#define FIXED_TO_DOUBLE(val) ((val) / (double)DOUBLE_SCALER)
|
|
||||||
|
|
||||||
#define INFTY 2
|
|
||||||
#define INFTY_SQR INFTY * INFTY
|
|
||||||
#define ITERS 255
|
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
|
||||||
|
|
||||||
//#define SHIP
|
|
||||||
#undef SHIP
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
Color get_color(int i) {
|
|
||||||
if(i == ITERS) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
return (Color) {
|
|
||||||
2*(i - 128)+255,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Color get_color(int i) {
|
|
||||||
// if((i == ITERS) || (i == 0)) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == ITERS) return (Color){0,255,0,255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
if(i < 128) {
|
|
||||||
return (Color) {
|
|
||||||
(8*(i - 128)+255) & 0xff,
|
|
||||||
0,
|
|
||||||
(16*(i - 64)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (Color) {
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
((unsigned int)-2*(i - 128)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vec2_double {
|
|
||||||
double x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vec2_float {
|
|
||||||
int32_t x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int iterate(int32_t r, int32_t i) {
|
|
||||||
int32_t z_i = 0;
|
|
||||||
int32_t z_r = 0;
|
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
|
||||||
for(int it = 0; it < ITERS; it++) {
|
|
||||||
z_r_2 = FIXED_MULTIPLY(z_r, z_r);
|
|
||||||
z_i_2 = FIXED_MULTIPLY(z_i, z_i);
|
|
||||||
|
|
||||||
zn_r = z_r_2 - z_i_2 + r;
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
zn_i = abs(FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + i;
|
|
||||||
#else
|
|
||||||
zn_i = (FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
z_i = zn_i;
|
|
||||||
z_r = zn_r;
|
|
||||||
|
|
||||||
if(z_i_2 + z_r_2 > INFTY_SQR_FIXED) return it;
|
|
||||||
}
|
|
||||||
return ITERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//blllluuuuurg, matracies and vectors in raylib are floats and we need doubles
|
|
||||||
void shift_cam(struct camera *cam, double step_r, double step_i) {
|
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
|
||||||
cam->min_i += i_offset;
|
|
||||||
cam->max_i += i_offset;
|
|
||||||
cam->min_r += r_offset;
|
|
||||||
cam->max_r += r_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom_cam(struct camera *cam, double zoom) {
|
|
||||||
double i_scale = (cam->max_i - cam->min_i) * zoom;
|
|
||||||
double r_scale = (cam->max_r - cam->min_r) * zoom;
|
|
||||||
cam->min_i += i_scale;
|
|
||||||
cam->max_i -= i_scale;
|
|
||||||
cam->min_r += r_scale;
|
|
||||||
cam->max_r -= r_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DIRECTIONS {
|
|
||||||
N, NE, E, SE, S, SW, W, NW
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
Color *pixels = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
struct camera cam = {
|
|
||||||
.min_r = -1,
|
|
||||||
.max_r = 1,
|
|
||||||
// .min_i = -1,
|
|
||||||
// .max_i = 1
|
|
||||||
};
|
|
||||||
cam.min_i = ((double)RES_Y / RES_X) * cam.min_r;
|
|
||||||
cam.max_i = ((double)RES_Y / RES_X) * cam.max_r;
|
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
|
|
||||||
SetTargetFPS(10);
|
|
||||||
|
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
shift_cam(&cam, 0, STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
shift_cam(&cam, 0, -STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
shift_cam(&cam, STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
shift_cam(&cam, -STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
zoom_cam(&cam, ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
zoom_cam(&cam, -ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
EndDrawing();
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("(%.21f, %.21f) - (%.21f, %.21f)\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
|
||||||
{
|
|
||||||
int32_t scale_i = DOUBLE_TO_FIXED((cam.max_i - cam.min_i) / (double)RES_Y);
|
|
||||||
int32_t scale_r = DOUBLE_TO_FIXED((cam.max_r - cam.min_r) / (double)RES_X);
|
|
||||||
int32_t c_i = DOUBLE_TO_FIXED(cam.max_i);
|
|
||||||
int32_t c_r;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c_r = DOUBLE_TO_FIXED(cam.min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c_r, c_i);
|
|
||||||
if(i >= ITERS) {
|
|
||||||
int start_x = x;
|
|
||||||
int start_y = y;
|
|
||||||
do {
|
|
||||||
for(int canidate_d = 0; canidate_d < NW; canidate_d++) {
|
|
||||||
|
|
||||||
}
|
|
||||||
} while((x != start_x) && (y != start_y));
|
|
||||||
}
|
|
||||||
pixels[((y * RES_X) + x)] = get_color(iterate(c_r, c_i));
|
|
||||||
c_r += scale_r;
|
|
||||||
}
|
|
||||||
c_i -= scale_i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(tex, pixels);
|
|
||||||
DrawTextureEx(tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,427 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <complex.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define WINDOW_SIZE_X 1600
|
|
||||||
#define WINDOW_SIZE_Y 800
|
|
||||||
#define RES_X 1600
|
|
||||||
#define RES_Y 800
|
|
||||||
#define DEFAULT_CENTER_X 0
|
|
||||||
#define DEFAULT_CENTER_Y 0
|
|
||||||
#define MOUSE_BUTTON 0
|
|
||||||
#define STEP_SIZE .1
|
|
||||||
#define ZOOM_SIZE .1
|
|
||||||
|
|
||||||
|
|
||||||
#define DECIMAL_LOC 28
|
|
||||||
#define DOUBLE_SCALER (1 << DECIMAL_LOC)
|
|
||||||
#define DOUBLE_TO_FIXED(val) (int32_t)((val) * DOUBLE_SCALER)
|
|
||||||
#define FIXED_MULTIPLY(x,y) ((((uint64_t)(x))*(y)) >> DECIMAL_LOC)
|
|
||||||
#define FIXED_TO_DOUBLE(val) ((val) / (double)DOUBLE_SCALER)
|
|
||||||
|
|
||||||
#define INFTY 2
|
|
||||||
#define INFTY_SQR INFTY * INFTY
|
|
||||||
#define ITERS 255
|
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
|
||||||
|
|
||||||
//#define SHIP
|
|
||||||
//#undef SHIP
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
Color get_color(int i) {
|
|
||||||
if(i == ITERS) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
return (Color) {
|
|
||||||
2*(i - 128)+255,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Color get_color(int i) {
|
|
||||||
// if((i == ITERS) || (i == 0)) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == ITERS) return (Color){0,0,0,255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
if(i < 128) {
|
|
||||||
return (Color) {
|
|
||||||
(8*(i - 128)+255) & 0xff,
|
|
||||||
0,
|
|
||||||
(16*(i - 64)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (Color) {
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
((unsigned int)-2*(i - 128)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t r; int32_t i;
|
|
||||||
} FixedCord;
|
|
||||||
|
|
||||||
static inline int iterate(FixedCord c) {
|
|
||||||
int32_t z_i = 0;
|
|
||||||
int32_t z_r = 0;
|
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
|
||||||
for(int it = 0; it < ITERS; it++) {
|
|
||||||
z_r_2 = FIXED_MULTIPLY(z_r, z_r);
|
|
||||||
z_i_2 = FIXED_MULTIPLY(z_i, z_i);
|
|
||||||
|
|
||||||
zn_r = z_r_2 - z_i_2 + c.r;
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
zn_i = abs(FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#else
|
|
||||||
zn_i = (FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
z_i = zn_i;
|
|
||||||
z_r = zn_r;
|
|
||||||
|
|
||||||
if(z_i_2 + z_r_2 > INFTY_SQR_FIXED) return it;
|
|
||||||
}
|
|
||||||
return ITERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//blllluuuuurg, matracies and vectors in raylib are floats and we need doubles
|
|
||||||
void shift_cam(struct camera *cam, double step_r, double step_i) {
|
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
|
||||||
cam->min_i += i_offset;
|
|
||||||
cam->max_i += i_offset;
|
|
||||||
cam->min_r += r_offset;
|
|
||||||
cam->max_r += r_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom_cam(struct camera *cam, double zoom) {
|
|
||||||
double i_scale = (cam->max_i - cam->min_i) * zoom;
|
|
||||||
double r_scale = (cam->max_r - cam->min_r) * zoom;
|
|
||||||
cam->min_i += i_scale;
|
|
||||||
cam->max_i -= i_scale;
|
|
||||||
cam->min_r += r_scale;
|
|
||||||
cam->max_r -= r_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DIRECTIONS {
|
|
||||||
N, NE, E, SE, S, SW, W, NW
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//we can inline these if needed
|
|
||||||
|
|
||||||
inline bool bitarray_check(uint8_t *array, size_t i) {
|
|
||||||
return array[i/8] & (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void bitarray_set(uint8_t *array, size_t i) {
|
|
||||||
array[i/8] |= (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
|
||||||
if((direction == NW) || (direction < E)) from_coord.i += step.i;
|
|
||||||
if((direction > N) && (direction < S)) from_coord.r += step.r;
|
|
||||||
if((direction > E) && (direction < W)) from_coord.i -= step.i;
|
|
||||||
if(direction > S) from_coord.r -= step.r;
|
|
||||||
return from_coord;
|
|
||||||
}
|
|
||||||
FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step);
|
|
||||||
|
|
||||||
|
|
||||||
size_t get_neighbor_index(size_t from_pixel, int direction) {
|
|
||||||
const size_t neighbor_index_accl[8] =
|
|
||||||
{-RES_X, -RES_X + 1, 1, RES_X + 1, RES_X, RES_X - 1, -1, -RES_X - 1};
|
|
||||||
from_pixel += neighbor_index_accl[direction];
|
|
||||||
//canidate for optimization; lots of branches. maybe inline
|
|
||||||
return from_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool bitarray_check(uint8_t *array, size_t i);
|
|
||||||
void bitarray_set(uint8_t *array, size_t i);
|
|
||||||
#define BITARRAY_SET(array, i) ((array)[(i)/8] |= (1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CLEAR(array, i) ((array)[(i)/8] &= ~(1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CHECK(array, i) ((array)[(i)/8] & (1 << ((i) % 8)))
|
|
||||||
|
|
||||||
//a lot of these are just so I can keep track of my cases while I program this, simplification will happen later
|
|
||||||
enum CANIDATE_STATUS {
|
|
||||||
UNSOLVED = 0,
|
|
||||||
M_ELEMENT,
|
|
||||||
M_EXTERIOR,
|
|
||||||
M_INTERIOR,
|
|
||||||
M_VISITED, //part of the curve we've been drawing
|
|
||||||
M_SKETCHY_SUSPENSION_ROPE_BRIDGE_TYPE_SHIT
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|
||||||
//these lookup tables r cheap cuz on the stm32f1, 1 memory read is 1 instruction
|
|
||||||
FixedCord scale = {
|
|
||||||
.r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X),
|
|
||||||
.i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y)};
|
|
||||||
FixedCord c = {.r = 0, .i = DOUBLE_TO_FIXED(cam->max_i)};
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
size_t on_pixel = 0;
|
|
||||||
uint8_t border[(RES_X*RES_Y)/8] = {0};
|
|
||||||
|
|
||||||
//having these r kinda gross, will restructure later
|
|
||||||
int32_t cam_bord_fixed_n = DOUBLE_TO_FIXED(cam->min_i);
|
|
||||||
int32_t cam_bord_fixed_s = DOUBLE_TO_FIXED(cam->max_i);
|
|
||||||
int32_t cam_bord_fixed_e = DOUBLE_TO_FIXED(cam->max_r);
|
|
||||||
int32_t cam_bord_fixed_w = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
//for keeping track of border only. will organize later
|
|
||||||
uint8_t set[(160*80)/8] = {0};
|
|
||||||
uint8_t unset[(160*80)/8] = {0};
|
|
||||||
**/
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
uint8_t border_bit = BITARRAY_CHECK(border, on_pixel);
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[on_pixel] = get_color(i);
|
|
||||||
|
|
||||||
const Color debug_colors[] =
|
|
||||||
{ (Color) {0xff, 0x00, 0x00, 0xff},
|
|
||||||
(Color) {0xff, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x00, 0xff, 0x00, 0xff},
|
|
||||||
(Color) {0x00, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x6a, 0x00, 0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int on_dbg_color = 0;
|
|
||||||
|
|
||||||
//this is where it all begins
|
|
||||||
uint8_t rendered[(RES_X*RES_Y)/8] = {0};
|
|
||||||
uint8_t deadend[(RES_X*RES_Y)/8] = {0};
|
|
||||||
if(i == ITERS) {
|
|
||||||
BORDER_START:
|
|
||||||
__attribute__((unused));
|
|
||||||
|
|
||||||
//just makes getting index of neigbor easier; doesn't cost extra cycles
|
|
||||||
FixedCord starting_bord_cord = c;
|
|
||||||
FixedCord current_bord_cord = c;
|
|
||||||
FixedCord last_bord_cord;
|
|
||||||
int previous_neighbors[8] = {UNSOLVED};
|
|
||||||
int current_neighbors[8] = {UNSOLVED};
|
|
||||||
current_neighbors[W] = UNSOLVED;
|
|
||||||
size_t current_bord_i = on_pixel;
|
|
||||||
uint8_t visited_border[(RES_X*RES_Y)/8] = {0};
|
|
||||||
int source_dir = 0;
|
|
||||||
size_t prev_bord_i = 0;
|
|
||||||
while(true) {
|
|
||||||
int filled_neighbors = 0;
|
|
||||||
|
|
||||||
//find if we're pushed against screen border.
|
|
||||||
//find a less gross way to do this
|
|
||||||
if((current_bord_cord.i - scale.i) < cam_bord_fixed_n) {
|
|
||||||
for(int nei_dir = SE; nei_dir <= SW; nei_dir++)
|
|
||||||
current_neighbors[nei_dir] = M_EXTERIOR;
|
|
||||||
}
|
|
||||||
if((current_bord_cord.i + scale.i) > cam_bord_fixed_s) {
|
|
||||||
current_neighbors[NE] = M_EXTERIOR;
|
|
||||||
current_neighbors[N] = M_EXTERIOR;
|
|
||||||
current_neighbors[NW] = M_EXTERIOR;
|
|
||||||
}
|
|
||||||
if((current_bord_cord.r - scale.r) < cam_bord_fixed_w) {
|
|
||||||
for(int nei_dir = SW; nei_dir < NW; nei_dir++)
|
|
||||||
current_neighbors[nei_dir] = M_EXTERIOR;
|
|
||||||
}
|
|
||||||
if((current_bord_cord.r + scale.r) > cam_bord_fixed_e) {
|
|
||||||
for(int nei_dir = NE; nei_dir < SE; nei_dir++)
|
|
||||||
current_neighbors[nei_dir] = M_EXTERIOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
//get info on neighbors, fill in missing current_neighbors info
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
size_t nei_i = get_neighbor_index(current_bord_i, nei_dir);
|
|
||||||
if(current_neighbors[nei_dir] == M_EXTERIOR) continue;
|
|
||||||
if(current_neighbors[nei_dir] != UNSOLVED) {
|
|
||||||
filled_neighbors++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(current_neighbors[nei_dir] == M_VISITED) continue;
|
|
||||||
if(BITARRAY_CHECK(visited_border, nei_i)) {
|
|
||||||
current_neighbors[nei_dir] = M_VISITED;
|
|
||||||
filled_neighbors++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int i = iterate(get_neighbor_coord(current_bord_cord, nei_dir, scale));
|
|
||||||
total_iters += i;
|
|
||||||
if(i == ITERS) {
|
|
||||||
current_neighbors[nei_dir] = M_ELEMENT;
|
|
||||||
filled_neighbors++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
current_neighbors[nei_dir] = M_EXTERIOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(filled_neighbors >= 8) {
|
|
||||||
memcpy(current_neighbors, previous_neighbors, sizeof(current_neighbors));
|
|
||||||
current_bord_cord = last_bord_cord;
|
|
||||||
current_bord_i = prev_bord_i;
|
|
||||||
current_neighbors[source_dir] = M_INTERIOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginDrawing();
|
|
||||||
DrawPixel(current_bord_i % RES_X, current_bord_i / RES_X, debug_colors[on_dbg_color]);
|
|
||||||
EndDrawing();
|
|
||||||
|
|
||||||
int nei_dir;
|
|
||||||
memcpy(previous_neighbors, current_neighbors, sizeof(current_neighbors));
|
|
||||||
memset(current_neighbors, 0, sizeof(current_neighbors));
|
|
||||||
for(nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
//found a valid neighbor to switch to
|
|
||||||
if(previous_neighbors[nei_dir] == M_ELEMENT) {
|
|
||||||
BITARRAY_SET(visited_border, current_bord_i);
|
|
||||||
current_neighbors[(nei_dir + 4) % 8] = M_VISITED;
|
|
||||||
if(nei_dir % 2) { //diagnals
|
|
||||||
current_neighbors[(nei_dir + 3) % 8] = previous_neighbors[(nei_dir + 1) % 8];
|
|
||||||
current_neighbors[(nei_dir + 5) % 8] = previous_neighbors[(nei_dir - 1) % 8];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
current_neighbors[(nei_dir + 2) % 8] = previous_neighbors[(nei_dir + 1) % 8];
|
|
||||||
current_neighbors[(nei_dir + 3) % 8] = previous_neighbors[(nei_dir + 2) % 8];
|
|
||||||
current_neighbors[(nei_dir + 5) % 8] = previous_neighbors[(nei_dir - 2) % 8];
|
|
||||||
current_neighbors[(nei_dir + 6) % 8] = previous_neighbors[(nei_dir - 1) % 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
last_bord_cord = current_bord_cord;
|
|
||||||
current_bord_cord = get_neighbor_coord(current_bord_cord, nei_dir, scale);
|
|
||||||
|
|
||||||
prev_bord_i = current_bord_i;
|
|
||||||
current_bord_i = get_neighbor_index(current_bord_i, nei_dir);
|
|
||||||
|
|
||||||
|
|
||||||
source_dir = nei_dir;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!memcmp(¤t_bord_cord, &starting_bord_cord, sizeof(current_bord_cord))) {
|
|
||||||
for(size_t bord_i = 0; bord_i < sizeof(border); bord_i++){
|
|
||||||
border[bord_i] |= visited_border[bord_i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("%zu: ", prev_bord_i);
|
|
||||||
printf("(%zu, %zu) -> (%zu, %zu) | {", prev_bord_i % RES_X, prev_bord_i / RES_X, current_bord_i % RES_X, current_bord_i / RES_X);
|
|
||||||
for(int i = 0; i < 8; i++) printf("%i, ", previous_neighbors[i]);
|
|
||||||
printf("} -> {");
|
|
||||||
for(int i = 0; i < 8; i++) printf("%i, ", current_neighbors[i]);
|
|
||||||
printf("}\n");
|
|
||||||
|
|
||||||
if(nei_dir > 7) break;
|
|
||||||
//printf("loop\n");
|
|
||||||
}
|
|
||||||
on_dbg_color = (on_dbg_color + 1) % (sizeof(debug_colors) / sizeof(*debug_colors));
|
|
||||||
}
|
|
||||||
on_pixel++;
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mandelbrot_unoptimized(struct camera *cam, Color *pixels) {
|
|
||||||
FixedCord scale = { .r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X), .i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y) };
|
|
||||||
FixedCord c = { .r = 0, .i = DOUBLE_TO_FIXED(cam->max_i) };
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[((y * RES_X) + x)] = get_color(i);
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test() {
|
|
||||||
uint8_t bitarray[(160*80)/8] = {0};
|
|
||||||
int test_i = 9;
|
|
||||||
BITARRAY_SET(bitarray, test_i);
|
|
||||||
printf("%s\n", BITARRAY_CHECK(bitarray, 9) ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
//test();
|
|
||||||
//return 0;
|
|
||||||
Color *pixels = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
struct camera cam = {
|
|
||||||
.min_r = -1,
|
|
||||||
.max_r = 1,
|
|
||||||
// .min_i = -1,
|
|
||||||
// .max_i = 1
|
|
||||||
};
|
|
||||||
cam.min_i = ((double)RES_Y / RES_X) * cam.min_r;
|
|
||||||
cam.max_i = ((double)RES_Y / RES_X) * cam.max_r;
|
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
|
|
||||||
SetTargetFPS(0);
|
|
||||||
|
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
shift_cam(&cam, 0, STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
shift_cam(&cam, 0, -STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
shift_cam(&cam, STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
shift_cam(&cam, -STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
zoom_cam(&cam, ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
zoom_cam(&cam, -ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
EndDrawing();
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("(%.21f, %.21f) - (%.21f, %.21f)\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
|
||||||
|
|
||||||
printf("Unoptimized: %u iterations\n", mandelbrot_unoptimized(&cam, pixels));
|
|
||||||
printf("Border tracing: %u iterations\n", mandelbrot_bordertrace(&cam, pixels));
|
|
||||||
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(tex, pixels);
|
|
||||||
DrawTextureEx(tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,585 +0,0 @@
|
|||||||
/** READ BEFORE JUDING!
|
|
||||||
* Yes, I know this code is a mess. Debug code is added
|
|
||||||
* happhazardly, two cameras are used, etc.
|
|
||||||
* That's because it's a temporary program
|
|
||||||
* to create optimizations and debug rendering issues without hardware.
|
|
||||||
* None of this is going to be included in the project, and the code is thus
|
|
||||||
* not extensible or organized; it really doesn't save any effort to do so.
|
|
||||||
*
|
|
||||||
* This code is meant for my eyes only. You've been warned!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <complex.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define WINDOW_SIZE_X 1600
|
|
||||||
#define WINDOW_SIZE_Y 800
|
|
||||||
#define RES_X 1600
|
|
||||||
#define RES_Y 800
|
|
||||||
#define DEFAULT_CENTER_X 0
|
|
||||||
#define DEFAULT_CENTER_Y 0
|
|
||||||
#define MOUSE_BUTTON 0
|
|
||||||
#define STEP_SIZE .1
|
|
||||||
#define ZOOM_SIZE .1
|
|
||||||
|
|
||||||
|
|
||||||
#define DECIMAL_LOC 28
|
|
||||||
#define DOUBLE_SCALER (1 << DECIMAL_LOC)
|
|
||||||
#define DOUBLE_TO_FIXED(val) (int32_t)((val) * DOUBLE_SCALER)
|
|
||||||
#define FIXED_MULTIPLY(x,y) ((((uint64_t)(x))*(y)) >> DECIMAL_LOC)
|
|
||||||
#define FIXED_TO_DOUBLE(val) ((val) / (double)DOUBLE_SCALER)
|
|
||||||
|
|
||||||
#define INFTY 2
|
|
||||||
#define INFTY_SQR INFTY * INFTY
|
|
||||||
#define ITERS 255
|
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
|
||||||
|
|
||||||
//#define SHIP
|
|
||||||
//#undef SHIP
|
|
||||||
|
|
||||||
int debug_x, debug_y;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
Color get_color(int i) {
|
|
||||||
if(i == ITERS) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
return (Color) {
|
|
||||||
2*(i - 128)+255,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Color get_color(int i) {
|
|
||||||
// if((i == ITERS) || (i == 0)) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == ITERS) return (Color){0,0,0,255};
|
|
||||||
if(i == 0) return (Color){0,0,1,255};
|
|
||||||
if(i < 128) {
|
|
||||||
return (Color) {
|
|
||||||
(8*(i - 128)+255) & 0xff,
|
|
||||||
0,
|
|
||||||
(16*(i - 64)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (Color) {
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
((unsigned int)-2*(i - 128)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//TODO remove
|
|
||||||
struct debug_info {
|
|
||||||
int32_t r, i;
|
|
||||||
int x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((used)) struct debug_info debug_get_coord(size_t i) {
|
|
||||||
struct debug_info ret;
|
|
||||||
ret.x = i % RES_X;
|
|
||||||
ret.y = i / RES_Y;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t r; int32_t i;
|
|
||||||
} FixedCord;
|
|
||||||
|
|
||||||
static inline int iterate(FixedCord c) {
|
|
||||||
int32_t z_i = 0;
|
|
||||||
int32_t z_r = 0;
|
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
|
||||||
for(int it = 0; it < ITERS; it++) {
|
|
||||||
z_r_2 = FIXED_MULTIPLY(z_r, z_r);
|
|
||||||
z_i_2 = FIXED_MULTIPLY(z_i, z_i);
|
|
||||||
|
|
||||||
zn_r = z_r_2 - z_i_2 + c.r;
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
zn_i = abs(FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#else
|
|
||||||
zn_i = (FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
z_i = zn_i;
|
|
||||||
z_r = zn_r;
|
|
||||||
|
|
||||||
if(z_i_2 + z_r_2 > INFTY_SQR_FIXED) return it;
|
|
||||||
}
|
|
||||||
return ITERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//blllluuuuurg, matracies and vectors in raylib are floats and we need doubles
|
|
||||||
void shift_cam(struct camera *cam, double step_r, double step_i) {
|
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
|
||||||
cam->min_i += i_offset;
|
|
||||||
cam->max_i += i_offset;
|
|
||||||
cam->min_r += r_offset;
|
|
||||||
cam->max_r += r_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom_cam(struct camera *cam, double zoom) {
|
|
||||||
double i_scale = (cam->max_i - cam->min_i) * zoom;
|
|
||||||
double r_scale = (cam->max_r - cam->min_r) * zoom;
|
|
||||||
cam->min_i += i_scale;
|
|
||||||
cam->max_i -= i_scale;
|
|
||||||
cam->min_r += r_scale;
|
|
||||||
cam->max_r -= r_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DIRECTIONS {
|
|
||||||
N, NE, E, SE, S, SW, W, NW
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//we can inline these if needed
|
|
||||||
|
|
||||||
inline bool bitarray_check(uint8_t *array, size_t i) {
|
|
||||||
return array[i/8] & (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void bitarray_set(uint8_t *array, size_t i) {
|
|
||||||
array[i/8] |= (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
|
||||||
if((direction == NW) || (direction < E)) from_coord.i += step.i;
|
|
||||||
if((direction > N) && (direction < S)) from_coord.r += step.r;
|
|
||||||
if((direction > E) && (direction < W)) from_coord.i -= step.i;
|
|
||||||
if(direction > S) from_coord.r -= step.r;
|
|
||||||
return from_coord;
|
|
||||||
}
|
|
||||||
FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step);
|
|
||||||
|
|
||||||
|
|
||||||
size_t get_neighbor_index(size_t from_pixel, int direction) {
|
|
||||||
const int neighbor_index_accl[8] =
|
|
||||||
{-RES_X, -RES_X + 1, 1, RES_X + 1, RES_X, RES_X - 1, -1, -RES_X - 1};
|
|
||||||
from_pixel += neighbor_index_accl[direction];
|
|
||||||
//canidate for optimization; lots of branches. maybe inline
|
|
||||||
return from_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool bitarray_check(uint8_t *array, size_t i);
|
|
||||||
void bitarray_set(uint8_t *array, size_t i);
|
|
||||||
#define BITARRAY_SET(array, i) ((array)[(i)/8] |= (1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CLEAR(array, i) ((array)[(i)/8] &= ~(1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CHECK(array, i) ((array)[(i)/8] & (1 << ((i) % 8)))
|
|
||||||
|
|
||||||
|
|
||||||
#define PRESORT_UNSOLVED (1 << 0)
|
|
||||||
#define PRESORT_VISITED (1 << VISITED)
|
|
||||||
//#define PRESORT_INTERIOR (1 << INTERIOR) //in set, NOT an edge
|
|
||||||
//#define PRESORT_BACKTRACKED (1 << BACKTRACED)
|
|
||||||
//#define PRESORT_EXTERIOR (1 <<
|
|
||||||
|
|
||||||
//we'll be storing info in the green channel to utalize all available memory.
|
|
||||||
//the following is bitmasks to do so
|
|
||||||
#define GCHAN_RENDERED (1 << 0)
|
|
||||||
#define GCHAN_VISITED (1 << 1)
|
|
||||||
#define GCHAN_BLOCKED (1 << 2) //interior element or backtrack
|
|
||||||
#define GCHAN_EXTERNAL (1 << 3)
|
|
||||||
#define GCHAN_DEBUG (1 << 4) //extra, not nessesary
|
|
||||||
|
|
||||||
/**
|
|
||||||
void switch_pixel(coord &this_coord, const coord step, size_t this_index, int dir) {
|
|
||||||
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
|
|
||||||
unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|
||||||
//these lookup tables r cheap cuz on the stm32f1, 1 memory read is 1 instruction
|
|
||||||
FixedCord scale = {
|
|
||||||
.r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X),
|
|
||||||
.i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y)};
|
|
||||||
FixedCord c = {.r = 0, .i = DOUBLE_TO_FIXED(cam->max_i)};
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
size_t on_pixel = 0;
|
|
||||||
|
|
||||||
//for camera border calculations
|
|
||||||
int32_t cam_bord_fixed_n = DOUBLE_TO_FIXED(cam->min_i);
|
|
||||||
int32_t cam_bord_fixed_s = DOUBLE_TO_FIXED(cam->max_i);
|
|
||||||
int32_t cam_bord_fixed_e = DOUBLE_TO_FIXED(cam->max_r);
|
|
||||||
int32_t cam_bord_fixed_w = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
|
|
||||||
|
|
||||||
//I know this is gross, just for debugigng!
|
|
||||||
//will clean up once I get things ironed out
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture debug_tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
Color *debug_pix = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
memcpy(debug_pix, pixels, RES_X * RES_Y * sizeof(Color));
|
|
||||||
static Camera2D debug_cam = {0};
|
|
||||||
debug_cam.zoom = (float)GetRenderWidth()/RES_X;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
//for keeping track of border only. will organize later
|
|
||||||
uint8_t set[(160*80)/8] = {0};
|
|
||||||
uint8_t unset[(160*80)/8] = {0};
|
|
||||||
**/
|
|
||||||
|
|
||||||
const Color debug_colors[] =
|
|
||||||
{ (Color) {0xff, 0x00, 0x00, 0xff},
|
|
||||||
(Color) {0xff, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x00, 0xff, 0x00, 0xff},
|
|
||||||
(Color) {0x00, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x6a, 0x00, 0xff, 0xff}
|
|
||||||
};
|
|
||||||
static int debug_color = 0;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[on_pixel] = get_color(i);
|
|
||||||
|
|
||||||
|
|
||||||
if(i == ITERS) {
|
|
||||||
FixedCord this_coord = c;
|
|
||||||
size_t this_index = on_pixel;
|
|
||||||
int nei_priority[8];
|
|
||||||
int last_nei_priority[8];
|
|
||||||
int last_direction = E;
|
|
||||||
int nei_presort[8];
|
|
||||||
|
|
||||||
//only really need to zero green channel
|
|
||||||
bzero(pixels, RES_X * RES_Y * sizeof(*pixels));
|
|
||||||
|
|
||||||
//this is so fucking knarly
|
|
||||||
printf("NEW BORDER\n");
|
|
||||||
while(true) {
|
|
||||||
//step 1: check pixels around us, fill in neighbors.
|
|
||||||
bzero(nei_presort, sizeof(nei_presort));
|
|
||||||
|
|
||||||
//find if we're pushed against screen border.
|
|
||||||
//feels gross but I don't think there's a better way
|
|
||||||
if((this_coord.i - scale.i) < cam_bord_fixed_n) {
|
|
||||||
for(int nei_dir = SE; nei_dir <= SW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.i + scale.i) > cam_bord_fixed_s) {
|
|
||||||
nei_presort[NE] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[N] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[NW] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
if((this_coord.r - scale.r) < cam_bord_fixed_w) {
|
|
||||||
for(int nei_dir = SW; nei_dir < NW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.r + scale.r) > cam_bord_fixed_e) {
|
|
||||||
for(int nei_dir = NE; nei_dir < SE; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** now fill in neighbor info based on green channel,
|
|
||||||
* iterate if no info available.
|
|
||||||
* if this is to slow we could flatten this; it's predictable
|
|
||||||
* where there will be info
|
|
||||||
**/
|
|
||||||
// TODO replace modulos with something faster
|
|
||||||
bool interior = true;
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
size_t nei_i;
|
|
||||||
uint8_t gchan_info;
|
|
||||||
|
|
||||||
//happens if we're pushed against the screen
|
|
||||||
if(nei_presort[nei_dir] == GCHAN_EXTERNAL) {
|
|
||||||
interior = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nei_i = get_neighbor_index(this_index, nei_dir);
|
|
||||||
gchan_info = pixels[nei_i].g;
|
|
||||||
//note that when we move this over, there will be no alpha channel.
|
|
||||||
//gchan_info will be extracted differently!!!
|
|
||||||
if(gchan_info & GCHAN_RENDERED) {
|
|
||||||
gchan_info &= ~(GCHAN_RENDERED);
|
|
||||||
|
|
||||||
if(gchan_info & GCHAN_EXTERNAL) {
|
|
||||||
interior = false;
|
|
||||||
gchan_info = GCHAN_BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gchan_info & GCHAN_BLOCKED) gchan_info = GCHAN_BLOCKED;
|
|
||||||
|
|
||||||
nei_presort[nei_dir] = gchan_info;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int i = iterate(get_neighbor_coord(this_coord, nei_dir, scale));
|
|
||||||
pixels[nei_i] = get_color(i);
|
|
||||||
pixels[nei_i].g = GCHAN_RENDERED;
|
|
||||||
if(i == ITERS) nei_presort[nei_dir] = 0;
|
|
||||||
else {
|
|
||||||
//exterior
|
|
||||||
interior = false;
|
|
||||||
nei_presort[nei_dir] = GCHAN_BLOCKED;
|
|
||||||
pixels[nei_i].g |= GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(interior) {
|
|
||||||
printf("interior\n");
|
|
||||||
asm volatile("interior_check:");
|
|
||||||
pixels[this_index].g = GCHAN_RENDERED | GCHAN_BLOCKED;
|
|
||||||
//printf("bruh\n");
|
|
||||||
memcpy(nei_priority, last_nei_priority, sizeof(nei_priority));
|
|
||||||
nei_priority[last_direction] = -1;
|
|
||||||
this_index = get_neighbor_index(this_index, (last_direction + 4) % 8);
|
|
||||||
this_coord = get_neighbor_coord(
|
|
||||||
this_coord, (last_direction + 4) % 8, scale);
|
|
||||||
pixels[this_index].g ^= GCHAN_VISITED; //so we don't think we need to backtrack
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int blocked_cnt = 0;
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
int offset_cw = (last_direction - nei_dir) % 8;
|
|
||||||
int offset_ccw = (nei_dir - last_direction) % 8;
|
|
||||||
int forward_offset;
|
|
||||||
switch(nei_presort[nei_dir]) {
|
|
||||||
case GCHAN_VISITED:
|
|
||||||
nei_priority[nei_dir] = 15;
|
|
||||||
break;
|
|
||||||
case GCHAN_BLOCKED:
|
|
||||||
case GCHAN_EXTERNAL:
|
|
||||||
nei_priority[nei_dir] = -1;
|
|
||||||
blocked_cnt++;
|
|
||||||
break;
|
|
||||||
default: //unvisited element
|
|
||||||
if((nei_presort[(nei_dir - 1) % 8] == 0) ||
|
|
||||||
(nei_presort[(nei_dir + 1) % 8] == 0)) {
|
|
||||||
nei_priority[nei_dir] = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((nei_presort[(nei_dir - 1) % 8] == GCHAN_VISITED) ||
|
|
||||||
(nei_presort[(nei_dir + 1) % 8] == GCHAN_VISITED)) {
|
|
||||||
nei_priority[nei_dir] = 7;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nei_priority[nei_dir] = 11;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(nei_priority[nei_dir] < 0) continue;
|
|
||||||
forward_offset = abs((offset_cw < offset_ccw) ?
|
|
||||||
offset_cw : offset_ccw);
|
|
||||||
if(forward_offset < 3) nei_priority[nei_dir] -= (3-forward_offset);
|
|
||||||
}
|
|
||||||
if(blocked_cnt == 8) {
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", nei_priority[nd]);
|
|
||||||
printf("we blocked ourselves in!\n");
|
|
||||||
for(;;) sleep(10);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int priority = 0; priority < 17; priority++) {
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
if(nei_priority[nei_dir] != priority) continue;
|
|
||||||
if(nei_dir % 2) continue;
|
|
||||||
printf("(%zu, %zu): dir %i. [", this_index % RES_X, this_index / RES_X, nei_dir);
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", nei_priority[nd]);
|
|
||||||
printf("] -> ");
|
|
||||||
|
|
||||||
// if(pixels[this_index].g & GCHAN_VISITED) {
|
|
||||||
if(priority >= 12) {
|
|
||||||
pixels[this_index].g |= GCHAN_BLOCKED;
|
|
||||||
printf("backtracking!!!\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pixels[this_index].g |= GCHAN_VISITED;
|
|
||||||
|
|
||||||
memcpy(last_nei_priority, nei_priority, sizeof(nei_priority));
|
|
||||||
last_direction = nei_dir;
|
|
||||||
this_index = get_neighbor_index(this_index, nei_dir);
|
|
||||||
this_coord = get_neighbor_coord(this_coord, nei_dir, scale);
|
|
||||||
printf("(%zu, %zu)\n", this_index % RES_X, this_index / RES_X);
|
|
||||||
|
|
||||||
debug_x = this_index % RES_X;
|
|
||||||
debug_y = this_index / RES_X;
|
|
||||||
|
|
||||||
/**
|
|
||||||
BeginDrawing();
|
|
||||||
DrawPixel(debug_x, debug_y,
|
|
||||||
debug_colors[debug_color % (sizeof(debug_colors) / sizeof(*debug_colors))]);
|
|
||||||
EndDrawing();
|
|
||||||
*/
|
|
||||||
|
|
||||||
//FOR VISUAL DEBUGGING- read warning on line 0!
|
|
||||||
{
|
|
||||||
static bool hit_debug_pix = false;
|
|
||||||
const float dbg_cam_step = 100;
|
|
||||||
const float dbg_cam_zoom = .25;
|
|
||||||
if((debug_x == 1046) && (debug_y == 126)) hit_debug_pix = true;
|
|
||||||
if(hit_debug_pix) {
|
|
||||||
for(;;) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
debug_cam.offset.y += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
debug_cam.offset.y -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
debug_cam.offset.x += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
debug_cam.offset.x -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
debug_cam.zoom += dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
debug_cam.zoom -= dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_ENTER:
|
|
||||||
goto switch_pixel;
|
|
||||||
default:
|
|
||||||
// BeginDrawing();
|
|
||||||
BeginDrawing();
|
|
||||||
const int dbg_clrs = 32;
|
|
||||||
uint8_t this_dbg_clr =
|
|
||||||
((debug_color++) % dbg_clrs) * (255 / dbg_clrs);
|
|
||||||
debug_pix[this_index] =
|
|
||||||
(Color) {this_dbg_clr, this_dbg_clr, this_dbg_clr, 255};
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(debug_tex, debug_pix);
|
|
||||||
DrawTextureEx(debug_tex, (Vector2)
|
|
||||||
{0 - debug_cam.offset.x, debug_cam.offset.y}, 0,
|
|
||||||
debug_cam.zoom, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
// EndDrawing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto switch_pixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch_pixel:
|
|
||||||
}
|
|
||||||
debug_color++;
|
|
||||||
}
|
|
||||||
on_pixel++;
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mandelbrot_unoptimized(struct camera *cam, Color *pixels) {
|
|
||||||
FixedCord scale = { .r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X), .i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y) };
|
|
||||||
FixedCord c = { .r = 0, .i = DOUBLE_TO_FIXED(cam->max_i) };
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[((y * RES_X) + x)] = get_color(i);
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test() {
|
|
||||||
uint8_t bitarray[(160*80)/8] = {0};
|
|
||||||
int test_i = 9;
|
|
||||||
BITARRAY_SET(bitarray, test_i);
|
|
||||||
printf("%s\n", BITARRAY_CHECK(bitarray, 9) ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
//test();
|
|
||||||
//return 0;
|
|
||||||
Color *pixels = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
struct camera cam = {
|
|
||||||
.min_r = -1,
|
|
||||||
.max_r = 1,
|
|
||||||
// .min_i = -1,
|
|
||||||
// .max_i = 1
|
|
||||||
};
|
|
||||||
cam.min_i = ((double)RES_Y / RES_X) * cam.min_r;
|
|
||||||
cam.max_i = ((double)RES_Y / RES_X) * cam.max_r;
|
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture tex = LoadTextureFromImage(img);
|
|
||||||
Texture backdrop = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
|
|
||||||
SetTargetFPS(60);
|
|
||||||
|
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
shift_cam(&cam, 0, STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
shift_cam(&cam, 0, -STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
shift_cam(&cam, STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
shift_cam(&cam, -STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
zoom_cam(&cam, ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
zoom_cam(&cam, -ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
EndDrawing();
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("(%.21f, %.21f) - (%.21f, %.21f)\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
|
||||||
|
|
||||||
printf("Unoptimized: %u iterations\n", mandelbrot_unoptimized(&cam, pixels));
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(backdrop, pixels);
|
|
||||||
DrawTextureEx(backdrop, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
|
|
||||||
/**
|
|
||||||
printf("Border tracing: %u iterations\n", mandelbrot_bordertrace(&cam, pixels));
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(tex, pixels);
|
|
||||||
DrawTextureEx(tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
**/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,561 +0,0 @@
|
|||||||
/** READ BEFORE JUDING!
|
|
||||||
* Yes, I know this code is a mess. Debug code is added
|
|
||||||
* happhazardly, two cameras are used, etc.
|
|
||||||
* That's because it's a temporary program
|
|
||||||
* to create optimizations and debug rendering issues without hardware.
|
|
||||||
* None of this is going to be included in the project, and the code is thus
|
|
||||||
* not extensible or organized; it really doesn't save any effort to do so.
|
|
||||||
*
|
|
||||||
* This code is meant for my eyes only. You've been warned!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <complex.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define WINDOW_SIZE_X 1600
|
|
||||||
#define WINDOW_SIZE_Y 800
|
|
||||||
#define RES_X 1600
|
|
||||||
#define RES_Y 800
|
|
||||||
#define DEFAULT_CENTER_X 0
|
|
||||||
#define DEFAULT_CENTER_Y 0
|
|
||||||
#define MOUSE_BUTTON 0
|
|
||||||
#define STEP_SIZE .1
|
|
||||||
#define ZOOM_SIZE .1
|
|
||||||
|
|
||||||
|
|
||||||
#define DECIMAL_LOC 28
|
|
||||||
#define DOUBLE_SCALER (1 << DECIMAL_LOC)
|
|
||||||
#define DOUBLE_TO_FIXED(val) (int32_t)((val) * DOUBLE_SCALER)
|
|
||||||
#define FIXED_MULTIPLY(x,y) ((((uint64_t)(x))*(y)) >> DECIMAL_LOC)
|
|
||||||
#define FIXED_TO_DOUBLE(val) ((val) / (double)DOUBLE_SCALER)
|
|
||||||
|
|
||||||
#define INFTY 2
|
|
||||||
#define INFTY_SQR INFTY * INFTY
|
|
||||||
#define ITERS 255
|
|
||||||
#define INFTY_SQR_FIXED DOUBLE_TO_FIXED(INFTY_SQR)
|
|
||||||
|
|
||||||
//#define SHIP
|
|
||||||
//#undef SHIP
|
|
||||||
|
|
||||||
int debug_x, debug_y;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
Color get_color(int i) {
|
|
||||||
if(i == ITERS) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == 0) return (Color){0, 0, 0, 255};
|
|
||||||
return (Color) {
|
|
||||||
2*(i - 128)+255,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Color get_color(int i) {
|
|
||||||
// if((i == ITERS) || (i == 0)) return (Color){0, 0, 0, 255};
|
|
||||||
if(i == ITERS) return (Color){0,0,0,255};
|
|
||||||
if(i == 0) return (Color){0,0,1,255};
|
|
||||||
if(i < 128) {
|
|
||||||
return (Color) {
|
|
||||||
(8*(i - 128)+255) & 0xff,
|
|
||||||
0,
|
|
||||||
(16*(i - 64)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (Color) {
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
((unsigned int)-2*(i - 128)+255) & 0xff,
|
|
||||||
255
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//TODO remove
|
|
||||||
struct debug_info {
|
|
||||||
int32_t r, i;
|
|
||||||
int x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((used)) struct debug_info debug_get_coord(size_t i) {
|
|
||||||
struct debug_info ret;
|
|
||||||
ret.x = i % RES_X;
|
|
||||||
ret.y = i / RES_Y;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct camera {
|
|
||||||
double min_r, min_i, max_r, max_i;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t r; int32_t i;
|
|
||||||
} FixedCord;
|
|
||||||
|
|
||||||
static inline int iterate(FixedCord c) {
|
|
||||||
int32_t z_i = 0;
|
|
||||||
int32_t z_r = 0;
|
|
||||||
int32_t z_r_2, z_i_2, zn_r, zn_i;
|
|
||||||
for(int it = 0; it < ITERS; it++) {
|
|
||||||
z_r_2 = FIXED_MULTIPLY(z_r, z_r);
|
|
||||||
z_i_2 = FIXED_MULTIPLY(z_i, z_i);
|
|
||||||
|
|
||||||
zn_r = z_r_2 - z_i_2 + c.r;
|
|
||||||
|
|
||||||
#ifdef SHIP
|
|
||||||
zn_i = abs(FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#else
|
|
||||||
zn_i = (FIXED_MULTIPLY((DOUBLE_TO_FIXED(2)), (FIXED_MULTIPLY(z_r, z_i)))) + c.i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
z_i = zn_i;
|
|
||||||
z_r = zn_r;
|
|
||||||
|
|
||||||
if(z_i_2 + z_r_2 > INFTY_SQR_FIXED) return it;
|
|
||||||
}
|
|
||||||
return ITERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
//blllluuuuurg, matracies and vectors in raylib are floats and we need doubles
|
|
||||||
void shift_cam(struct camera *cam, double step_r, double step_i) {
|
|
||||||
double i_offset = (cam->max_i - cam->min_i) * step_i;
|
|
||||||
double r_offset = (cam->max_r - cam->min_r) * step_r;
|
|
||||||
cam->min_i += i_offset;
|
|
||||||
cam->max_i += i_offset;
|
|
||||||
cam->min_r += r_offset;
|
|
||||||
cam->max_r += r_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void zoom_cam(struct camera *cam, double zoom) {
|
|
||||||
double i_scale = (cam->max_i - cam->min_i) * zoom;
|
|
||||||
double r_scale = (cam->max_r - cam->min_r) * zoom;
|
|
||||||
cam->min_i += i_scale;
|
|
||||||
cam->max_i -= i_scale;
|
|
||||||
cam->min_r += r_scale;
|
|
||||||
cam->max_r -= r_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DIRECTIONS {
|
|
||||||
N, NE, E, SE, S, SW, W, NW
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//we can inline these if needed
|
|
||||||
|
|
||||||
inline bool bitarray_check(uint8_t *array, size_t i) {
|
|
||||||
return array[i/8] & (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void bitarray_set(uint8_t *array, size_t i) {
|
|
||||||
array[i/8] |= (1 << (i%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step) {
|
|
||||||
if((direction == NW) || (direction < E)) from_coord.i += step.i;
|
|
||||||
if((direction > N) && (direction < S)) from_coord.r += step.r;
|
|
||||||
if((direction > E) && (direction < W)) from_coord.i -= step.i;
|
|
||||||
if(direction > S) from_coord.r -= step.r;
|
|
||||||
return from_coord;
|
|
||||||
}
|
|
||||||
FixedCord get_neighbor_coord(FixedCord from_coord, int direction, FixedCord step);
|
|
||||||
|
|
||||||
|
|
||||||
size_t get_neighbor_index(size_t from_pixel, int direction) {
|
|
||||||
const int neighbor_index_accl[8] =
|
|
||||||
{-RES_X, -RES_X + 1, 1, RES_X + 1, RES_X, RES_X - 1, -1, -RES_X - 1};
|
|
||||||
from_pixel += neighbor_index_accl[direction];
|
|
||||||
//canidate for optimization; lots of branches. maybe inline
|
|
||||||
return from_pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool bitarray_check(uint8_t *array, size_t i);
|
|
||||||
void bitarray_set(uint8_t *array, size_t i);
|
|
||||||
#define BITARRAY_SET(array, i) ((array)[(i)/8] |= (1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CLEAR(array, i) ((array)[(i)/8] &= ~(1 << ((i) % 8)))
|
|
||||||
#define BITARRAY_CHECK(array, i) ((array)[(i)/8] & (1 << ((i) % 8)))
|
|
||||||
|
|
||||||
//we'll be storing info in the green channel to utalize available memory
|
|
||||||
//per pixel.
|
|
||||||
|
|
||||||
#define GCHAN_BLOCKED (1 << 0) //interior element or visiteed
|
|
||||||
#define GCHAN_INTERNAL (1 << 1) //part of set
|
|
||||||
#define GCHAN_EXTERNAL (1 << 2) //not part of set
|
|
||||||
#define GCHAN_DEBUG (1 << 3) //extra, not nessesary
|
|
||||||
|
|
||||||
#define BACKSTACK_SIZE 32
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
void switch_pixel(coord &this_coord, const coord step, size_t this_index, int dir) {
|
|
||||||
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
|
|
||||||
void debug_step(Color *pix, Texture *tex, size_t index) {
|
|
||||||
static Camera2D cam = {0};
|
|
||||||
if(!cam.zoom) cam.zoom = (float)GetRenderWidth()/RES_X;
|
|
||||||
static int debug_color = 0;
|
|
||||||
const Color debug_colors[] =
|
|
||||||
{ (Color) {0xff, 0x00, 0x00, 0xff},
|
|
||||||
(Color) {0xff, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x00, 0xff, 0x00, 0xff},
|
|
||||||
(Color) {0x00, 0x00, 0xff, 0xff},
|
|
||||||
(Color) {0x6a, 0x00, 0xff, 0xff}
|
|
||||||
};
|
|
||||||
const float dbg_cam_step = 100;
|
|
||||||
const float dbg_cam_zoom = .25;
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
cam.offset.y += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
cam.offset.y -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
cam.offset.x += dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
cam.offset.x -= dbg_cam_step;
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
cam.zoom += dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
cam.zoom -= dbg_cam_zoom;
|
|
||||||
break;
|
|
||||||
case KEY_ENTER:
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
const int dbg_clrs = 32;
|
|
||||||
uint8_t this_dbg_clr =
|
|
||||||
((debug_color++) % dbg_clrs) * (255 / dbg_clrs);
|
|
||||||
pix[index] =
|
|
||||||
(Color) {this_dbg_clr, this_dbg_clr, this_dbg_clr, 255};
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(*tex, pix);
|
|
||||||
DrawTextureEx(*tex, (Vector2)
|
|
||||||
{0 - cam.offset.x, cam.offset.y}, 0,
|
|
||||||
cam.zoom, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|
||||||
//these lookup tables r cheap cuz on the stm32f1, 1 memory read is 1 instruction
|
|
||||||
FixedCord scale = {
|
|
||||||
.r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X),
|
|
||||||
.i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y)};
|
|
||||||
FixedCord c = {.r = 0, .i = DOUBLE_TO_FIXED(cam->max_i)};
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
size_t on_pixel = 0;
|
|
||||||
|
|
||||||
//for camera border calculations
|
|
||||||
int32_t cam_bord_fixed_n = DOUBLE_TO_FIXED(cam->min_i);
|
|
||||||
int32_t cam_bord_fixed_s = DOUBLE_TO_FIXED(cam->max_i);
|
|
||||||
int32_t cam_bord_fixed_e = DOUBLE_TO_FIXED(cam->max_r);
|
|
||||||
int32_t cam_bord_fixed_w = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
|
|
||||||
|
|
||||||
//I know this is gross, just for debugigng!
|
|
||||||
//will clean up once I get things ironed out
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture debug_tex = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
Color *debug_pix = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
memcpy(debug_pix, pixels, RES_X * RES_Y * sizeof(Color));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
//for keeping track of border only. will organize later
|
|
||||||
uint8_t set[(160*80)/8] = {0};
|
|
||||||
uint8_t unset[(160*80)/8] = {0};
|
|
||||||
**/
|
|
||||||
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[on_pixel] = get_color(i);
|
|
||||||
|
|
||||||
|
|
||||||
if(i == ITERS) {
|
|
||||||
FixedCord this_coord = c;
|
|
||||||
size_t this_index = on_pixel;
|
|
||||||
int nei_priority[8];
|
|
||||||
int last_nei_priority[8];
|
|
||||||
int last_direction = E;
|
|
||||||
int nei_presort[8];
|
|
||||||
|
|
||||||
size_t backstack[BACKSTACK_SIZE];
|
|
||||||
size_t backstack_i = 0;
|
|
||||||
|
|
||||||
//only really need to zero green channel
|
|
||||||
bzero(pixels, RES_X * RES_Y * sizeof(*pixels));
|
|
||||||
|
|
||||||
//this is so fucking knarly
|
|
||||||
printf("NEW BORDER\n");
|
|
||||||
while(true) {
|
|
||||||
//step 1: check pixels around us, fill in neighbors.
|
|
||||||
bzero(nei_presort, sizeof(nei_presort));
|
|
||||||
|
|
||||||
//find if we're pushed against screen border.
|
|
||||||
//feels gross but I don't think there's a better way
|
|
||||||
if((this_coord.i - scale.i) < cam_bord_fixed_n) {
|
|
||||||
for(int nei_dir = SE; nei_dir <= SW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.i + scale.i) > cam_bord_fixed_s) {
|
|
||||||
nei_presort[NE] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[N] = GCHAN_EXTERNAL;
|
|
||||||
nei_presort[NW] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
if((this_coord.r - scale.r) < cam_bord_fixed_w) {
|
|
||||||
for(int nei_dir = SW; nei_dir < NW; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
else if((this_coord.r + scale.r) > cam_bord_fixed_e) {
|
|
||||||
for(int nei_dir = NE; nei_dir < SE; nei_dir++)
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** now fill in neighbor info based on green channel,
|
|
||||||
* iterate if no info available.
|
|
||||||
* if this is to slow we could flatten this; it's predictable
|
|
||||||
* where there will be info
|
|
||||||
**/
|
|
||||||
// TODO replace modulos with something faster
|
|
||||||
bool interior = true;
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir++) {
|
|
||||||
size_t nei_i;
|
|
||||||
uint8_t gchan_info;
|
|
||||||
|
|
||||||
//happens if we're pushed against the screen
|
|
||||||
if(nei_presort[nei_dir] == GCHAN_EXTERNAL) {
|
|
||||||
interior = false;
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nei_i = get_neighbor_index(this_index, nei_dir);
|
|
||||||
gchan_info = pixels[nei_i].g;
|
|
||||||
//note that when we move this over, there will be no alpha channel.
|
|
||||||
//gchan_info will be extracted differently!!!
|
|
||||||
if(gchan_info) {
|
|
||||||
if(gchan_info & GCHAN_EXTERNAL) interior = false;
|
|
||||||
nei_presort[nei_dir] = gchan_info;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int i = iterate(get_neighbor_coord(this_coord, nei_dir, scale));
|
|
||||||
pixels[nei_i] = get_color(i);
|
|
||||||
if(i == ITERS) nei_presort[nei_dir] = GCHAN_INTERNAL;
|
|
||||||
else {
|
|
||||||
//exterior
|
|
||||||
interior = false;
|
|
||||||
nei_presort[nei_dir] = GCHAN_EXTERNAL;
|
|
||||||
}
|
|
||||||
pixels[nei_i].g = nei_presort[nei_dir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//go back if we're in the interior and not an edge
|
|
||||||
if(interior) {
|
|
||||||
printf("interior\n");
|
|
||||||
asm volatile("interior_check:");
|
|
||||||
pixels[this_index].g = GCHAN_BLOCKED;
|
|
||||||
//printf("bruh\n");
|
|
||||||
memcpy(nei_priority, last_nei_priority, sizeof(nei_priority));
|
|
||||||
nei_priority[last_direction] = -1;
|
|
||||||
this_index = get_neighbor_index(this_index, (last_direction + 4) % 8);
|
|
||||||
this_coord = get_neighbor_coord(
|
|
||||||
this_coord, (last_direction + 4) % 8, scale);
|
|
||||||
pixels[this_index].g = GCHAN_BLOCKED; //so we don't think we need to backtrack
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int edge_cnt = 0;
|
|
||||||
//sort into prioraties
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
int nei_1 = nei_presort[(nei_dir + 1) % 8];
|
|
||||||
int nei_2 = nei_presort[(nei_dir - 1) % 8];
|
|
||||||
if((nei_presort[nei_dir] != GCHAN_INTERNAL) || ((nei_1 & nei_2) & (GCHAN_EXTERNAL | GCHAN_BLOCKED))) {
|
|
||||||
nei_priority[nei_dir] = -1;
|
|
||||||
}
|
|
||||||
else if(((nei_1 ^ nei_2) & (GCHAN_INTERNAL | GCHAN_EXTERNAL)) == (GCHAN_INTERNAL | GCHAN_EXTERNAL)) {
|
|
||||||
edge_cnt++;
|
|
||||||
nei_priority[nei_dir] = 0;
|
|
||||||
}
|
|
||||||
else if(nei_1 & nei_2 & GCHAN_INTERNAL) {
|
|
||||||
nei_priority[nei_dir] = 1;
|
|
||||||
}
|
|
||||||
else if(((nei_1 ^ nei_2) & (GCHAN_BLOCKED | GCHAN_EXTERNAL)) == (GCHAN_BLOCKED | GCHAN_EXTERNAL)) {
|
|
||||||
nei_priority[nei_dir] = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(edge_cnt >= 2) {
|
|
||||||
backstack[backstack_i] = this_index;
|
|
||||||
if(backstack_i++ > BACKSTACK_SIZE) {
|
|
||||||
printf("max backstack\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
printf("backstack increased\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//now go to canidate with lowest prioraty
|
|
||||||
for(int priority = 0; priority <= 1; priority++) {
|
|
||||||
for(int nei_dir = 0; nei_dir < 8; nei_dir += 2) {
|
|
||||||
if(nei_priority[nei_dir] != priority) continue;
|
|
||||||
printf("(%zu, %zu): dir %i. [", this_index % RES_X, this_index / RES_X, nei_dir);
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", nei_priority[nd]);
|
|
||||||
printf("] -> ");
|
|
||||||
|
|
||||||
pixels[this_index].g = GCHAN_BLOCKED;
|
|
||||||
|
|
||||||
memcpy(last_nei_priority, nei_priority, sizeof(nei_priority));
|
|
||||||
this_index = get_neighbor_index(this_index, nei_dir);
|
|
||||||
this_coord = get_neighbor_coord(this_coord, nei_dir, scale);
|
|
||||||
printf("(%zu, %zu)\n", this_index % RES_X, this_index / RES_X);
|
|
||||||
|
|
||||||
debug_x = this_index % RES_X;
|
|
||||||
debug_y = this_index / RES_X;
|
|
||||||
|
|
||||||
//FOR VISUAL DEBUGGING- read warning on line 0!
|
|
||||||
{
|
|
||||||
static bool hit_debug_pix = true;
|
|
||||||
if((debug_x == 1046) && (debug_y == 126)) hit_debug_pix = true;
|
|
||||||
if(hit_debug_pix) debug_step(debug_pix, &debug_tex, this_index);
|
|
||||||
}
|
|
||||||
goto next_pixel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("checking backtrack stack\nThis pri:");
|
|
||||||
for(int nd = 0; nd < 8; nd++) printf("%i, ", nei_priority[nd]);
|
|
||||||
printf("\n");
|
|
||||||
if(--backstack_i > BACKSTACK_SIZE) {
|
|
||||||
printf("backstack depleated, no recovery\n");
|
|
||||||
for(;;);
|
|
||||||
}
|
|
||||||
printf("%lu\n", backstack_i);
|
|
||||||
this_index = backstack[backstack_i];
|
|
||||||
this_coord.r = (((this_index % RES_X) / (float)RES_X) * (cam->max_r - cam->min_r)) + cam->min_r;
|
|
||||||
this_coord.i = (((this_index / RES_X) / (float)RES_Y) * (cam->max_i - cam->min_i)) + cam->min_i;
|
|
||||||
debug_step(debug_pix, &debug_tex, this_index);
|
|
||||||
next_pixel:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
on_pixel++;
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int mandelbrot_unoptimized(struct camera *cam, Color *pixels) {
|
|
||||||
FixedCord scale = { .r = DOUBLE_TO_FIXED((cam->max_r - cam->min_r) / (double)RES_X), .i = DOUBLE_TO_FIXED((cam->max_i - cam->min_i) / (double)RES_Y) };
|
|
||||||
FixedCord c = { .r = 0, .i = DOUBLE_TO_FIXED(cam->max_i) };
|
|
||||||
unsigned int total_iters = 0;
|
|
||||||
for(int y = 0; y < RES_Y; y++) {
|
|
||||||
c.r = DOUBLE_TO_FIXED(cam->min_r);
|
|
||||||
for(int x = 0; x < RES_X; x++) {
|
|
||||||
int i = iterate(c);
|
|
||||||
total_iters += i;
|
|
||||||
pixels[((y * RES_X) + x)] = get_color(i);
|
|
||||||
c.r += scale.r;
|
|
||||||
}
|
|
||||||
c.i -= scale.i;
|
|
||||||
}
|
|
||||||
return total_iters;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test() {
|
|
||||||
uint8_t bitarray[(160*80)/8] = {0};
|
|
||||||
int test_i = 9;
|
|
||||||
BITARRAY_SET(bitarray, test_i);
|
|
||||||
printf("%s\n", BITARRAY_CHECK(bitarray, 9) ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
//test();
|
|
||||||
//return 0;
|
|
||||||
Color *pixels = malloc(RES_X * RES_Y * sizeof(Color));
|
|
||||||
struct camera cam = {
|
|
||||||
.min_r = -1,
|
|
||||||
.max_r = 1,
|
|
||||||
// .min_i = -1,
|
|
||||||
// .max_i = 1
|
|
||||||
};
|
|
||||||
cam.min_i = ((double)RES_Y / RES_X) * cam.min_r;
|
|
||||||
cam.max_i = ((double)RES_Y / RES_X) * cam.max_r;
|
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
|
||||||
|
|
||||||
Image img = GenImageColor(RES_X, RES_Y, BLUE);
|
|
||||||
Texture tex = LoadTextureFromImage(img);
|
|
||||||
Texture backdrop = LoadTextureFromImage(img);
|
|
||||||
UnloadImage(img);
|
|
||||||
|
|
||||||
SetTargetFPS(60);
|
|
||||||
|
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
|
||||||
switch(GetKeyPressed()) {
|
|
||||||
case KEY_UP:
|
|
||||||
shift_cam(&cam, 0, STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
shift_cam(&cam, 0, -STEP_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
shift_cam(&cam, STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_LEFT:
|
|
||||||
shift_cam(&cam, -STEP_SIZE, 0);
|
|
||||||
break;
|
|
||||||
case KEY_W:
|
|
||||||
zoom_cam(&cam, ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
case KEY_S:
|
|
||||||
zoom_cam(&cam, -ZOOM_SIZE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BeginDrawing();
|
|
||||||
EndDrawing();
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("(%.21f, %.21f) - (%.21f, %.21f)\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
|
||||||
|
|
||||||
printf("Unoptimized: %u iterations\n", mandelbrot_unoptimized(&cam, pixels));
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(backdrop, pixels);
|
|
||||||
DrawTextureEx(backdrop, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
|
|
||||||
printf("Border tracing: %u iterations\n", mandelbrot_bordertrace(&cam, pixels));
|
|
||||||
BeginDrawing();
|
|
||||||
UpdateTexture(tex, pixels);
|
|
||||||
DrawTextureEx(tex, (Vector2){0,0}, 0, (float)GetRenderWidth()/RES_X, WHITE);
|
|
||||||
EndDrawing();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -189,6 +189,7 @@ void switch_pixel(coord &this_coord, const coord step, size_t this_index, int di
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
void debug_step(Color *pix, Texture *tex, size_t index, bool pause) {
|
void debug_step(Color *pix, Texture *tex, size_t index, bool pause) {
|
||||||
|
// return;
|
||||||
// SetTargetFPS(0);
|
// SetTargetFPS(0);
|
||||||
static bool fuckin_manual_pause_iguess = false;
|
static bool fuckin_manual_pause_iguess = false;
|
||||||
static Camera2D cam = {0};
|
static Camera2D cam = {0};
|
||||||
@ -197,7 +198,7 @@ void debug_step(Color *pix, Texture *tex, size_t index, bool pause) {
|
|||||||
const float dbg_cam_step = 100;
|
const float dbg_cam_step = 100;
|
||||||
const float dbg_cam_zoom = 1.5;
|
const float dbg_cam_zoom = 1.5;
|
||||||
|
|
||||||
(pause || fuckin_manual_pause_iguess) ? SetTargetFPS(60) : SetTargetFPS(0);
|
// (pause || fuckin_manual_pause_iguess) ? SetTargetFPS(60) : SetTargetFPS(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -232,14 +233,15 @@ void debug_step(Color *pix, Texture *tex, size_t index, bool pause) {
|
|||||||
default:
|
default:
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
pix[index] =
|
pix[index] =
|
||||||
(Color) {0, pix[index].g, 255, 255};
|
(Color) {255, pix[index].g, 255, 255};
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
UpdateTexture(*tex, pix);
|
UpdateTexture(*tex, pix);
|
||||||
DrawTextureEx(*tex, (Vector2)
|
DrawTextureEx(*tex, (Vector2)
|
||||||
{0 - cam.offset.x, cam.offset.y}, 0,
|
{0 - cam.offset.x, cam.offset.y}, 0,
|
||||||
cam.zoom, WHITE);
|
cam.zoom, WHITE);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
if(!pause && !fuckin_manual_pause_iguess) return;
|
return;
|
||||||
|
// if(!pause && !fuckin_manual_pause_iguess) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,7 +318,7 @@ unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|||||||
if(border_scanning) {
|
if(border_scanning) {
|
||||||
//pixels[on_pixel] = get_color(ITERS);
|
//pixels[on_pixel] = get_color(ITERS);
|
||||||
//printf("interior\n");
|
//printf("interior\n");
|
||||||
pixels[on_pixel] = (Color){0xfe,0,0xfe,0xff};
|
pixels[on_pixel] = (Color){0x00,0,0x0,0xff};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//printf("rendering %i, %i (%lu)\n", x, y, on_pixel);
|
//printf("rendering %i, %i (%lu)\n", x, y, on_pixel);
|
||||||
@ -446,11 +448,6 @@ unsigned int mandelbrot_bordertrace(struct camera *cam, Color *pixels) {
|
|||||||
}
|
}
|
||||||
else pixels[on_pixel].g = GCHAN_EXTERNAL;
|
else pixels[on_pixel].g = GCHAN_EXTERNAL;
|
||||||
break;
|
break;
|
||||||
/**
|
|
||||||
case GCHAN_INNER_CLOSED:
|
|
||||||
if(((x + 2) < RES_X) && (pixels[on_pixel + 1].g == GCHAN_UNRENDERED)) border_scanning = SCAN_MODE_NONE;
|
|
||||||
break;
|
|
||||||
**/
|
|
||||||
default:
|
default:
|
||||||
border_scanning = SCAN_MODE_NONE;
|
border_scanning = SCAN_MODE_NONE;
|
||||||
}
|
}
|
||||||
@ -525,9 +522,7 @@ int main() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct camera cam = {
|
struct camera cam = (struct camera) {-0.641121775196897503157, 0.410802460984564632440, -0.638087553194557455249, 0.412319571985918953416};
|
||||||
.min_r = -0.640818352996663453958, .min_i = 0.410802460984564632440, .max_r = -0.637784130994323406050, .max_i = 0.412319571985918953416
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
InitWindow(WINDOW_SIZE_X, WINDOW_SIZE_Y, "mandelbrot fixed point test");
|
||||||
@ -537,7 +532,7 @@ int main() {
|
|||||||
Texture tex = LoadTextureFromImage(img);
|
Texture tex = LoadTextureFromImage(img);
|
||||||
UnloadImage(img);
|
UnloadImage(img);
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(0);
|
||||||
|
|
||||||
while(!WindowShouldClose()) {
|
while(!WindowShouldClose()) {
|
||||||
switch(GetKeyPressed()) {
|
switch(GetKeyPressed()) {
|
||||||
@ -568,7 +563,8 @@ int main() {
|
|||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf(".min_r = %.21f, .min_i = %.21f, .max_r = %.21f, .max_i = %.21f\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
//printf(".min_r = %.21f, .min_i = %.21f, .max_r = %.21f, .max_i = %.21f\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
||||||
|
printf("(struct camera) {%.21f, %.21f, %.21f, %.21f}\n", cam.min_r, cam.min_i, cam.max_r, cam.max_i);
|
||||||
|
|
||||||
|
|
||||||
clock_t begin, end;
|
clock_t begin, end;
|
||||||
@ -586,7 +582,7 @@ int main() {
|
|||||||
printf("Unoptimized: %u iterations, %f seconds\n", unoptimized_iters, time_unoptimized);
|
printf("Unoptimized: %u iterations, %f seconds\n", unoptimized_iters, time_unoptimized);
|
||||||
|
|
||||||
begin = clock();
|
begin = clock();
|
||||||
unsigned int optimized_iters = mandelbrot_bordertrace(&cam, pixels_optimized);
|
unsigned int optimized_iters = mandelbrot_bordertrace(&cam, pixels_unoptimized);
|
||||||
end = clock();
|
end = clock();
|
||||||
|
|
||||||
time_optimized = (double)(end - begin) / CLOCKS_PER_SEC;
|
time_optimized = (double)(end - begin) / CLOCKS_PER_SEC;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
.default: make
|
.default: make
|
||||||
make:
|
make:
|
||||||
gcc main.c -O0 -ggdb3 -o mandelbrot -lraylib -lm -Wall -ggdb
|
gcc main.c -Ofast -o mandelbrot -lraylib -lm -Wall -ggdb
|
||||||
#gcc main.c -Ofast -o mandelbrot -lraylib -lm -Wall -ggdb
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f mandelbrot
|
rm -f mandelbrot
|
||||||
|
Before Width: | Height: | Size: 4.0 KiB |
BIN
writeup/bad_curcuit.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
writeup/bordertracing.mkv
Normal file
BIN
writeup/closed_border.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
writeup/pcb_pads.png
Normal file
After Width: | Height: | Size: 141 KiB |