<root>
<document scada='0' projtype='1' schema='103' license='1,79829088,Q2XNNM' title='New Embedded Project' description='New &lt;ESP32-S3_WROOM&gt; Embedded Project' fcversion='720898' target='ESP.ESP32.ESP32-S3_WROOM' >
	<config data='' clkspd='360000000' simspd='0' usewdt='0' constif='0' SSH_IP='DD6171BB7AD97877' SSH_User='DD6171BB7AD97877' SSH_Pass='DD6171BB7AD97877' Use3V3='0' />
	<plugins >
		<dll_models enabled='1' />
	</plugins>
	<supplement use='1' head='#include &lt;code.h&gt;' body='#include &lt;code.c&gt;' />
	<debug />
	<traces />
	<ghost >
		<FK2 >
			<data name='FK2D0' port='4294967295' pin='4294967295' />
			<data name='FK2D1' port='4294967295' pin='4294967295' />
			<data name='FK2D2' port='4294967295' pin='4294967295' />
			<data name='FK2D3' port='4294967295' pin='4294967295' />
			<data name='FK2D4' port='4294967295' pin='4294967295' />
			<data name='FK2D5' port='4294967295' pin='4294967295' />
			<data name='FK2D6' port='4294967295' pin='4294967295' />
			<data name='FK2D7' port='4294967295' pin='4294967295' />
			<data name='FK2D8' port='4294967295' pin='4294967295' />
			<data name='FK2D9' port='4294967295' pin='4294967295' />
			<data name='FK2D10' port='4294967295' pin='4294967295' />
			<data name='FK2D11' port='4294967295' pin='4294967295' />
			<data name='FK2D12' port='4294967295' pin='4294967295' />
			<data name='FK2D13' port='4294967295' pin='4294967295' />
			<data name='FK2D14' port='4294967295' pin='4294967295' />
			<data name='FK2D15' port='4294967295' pin='4294967295' />
			<data name='FK2A0' port='4294967295' pin='4294967295' />
			<data name='FK2A1' port='4294967295' pin='4294967295' />
			<data name='FK2A2' port='4294967295' pin='4294967295' />
			<data name='FK2A3' port='4294967295' pin='4294967295' />
			<data name='FK2A4' port='4294967295' pin='4294967295' />
			<data name='FK2A5' port='4294967295' pin='4294967295' />
		</FK2>
		<ICD >
			<data name='AnalogPrescaleValue' value='19' />
			<data name='DigitalSampleRate' value='100000' />
			<data name='BreakpointCount' value='8' />
			<data name='CallStackDepthCount' value='8' />
			<data name='ClockPort' value='1' />
			<data name='ClockPin' value='6' />
			<data name='DataPort' value='1' />
			<data name='DataPin' value='7' />
			<data name='UseDefaultPins' value='1' />
			<data name='WrapEnabled' value='1' />
			<data name='CommsDelayOverridden' value='0' />
			<data name='CommsDelay' value='1' />
			<data name='CalculatedCommsDelay' value='1' />
			<data name='AnalogEB2PrescaleValue' value='2' />
			<data name='DigitalEB2SampleRate' value='100000' />
		</ICD>
		<pins >
			<digital A='0' B='0' C='0' D='0' E='0' F='0' G='0' H='0' I='0' J='0' K='0' L='0' M='0' N='0' O='0' P='0' Q='0' R='0' S='0' T='0' U='0' V='0' W='0' X='0' Y='0' Z='0' />
			<analog A='0' B='0' C='0' D='0' E='0' F='0' G='0' H='0' I='0' J='0' K='0' L='0' M='0' N='0' O='0' P='0' Q='0' R='0' S='0' T='0' U='0' V='0' W='0' X='0' Y='0' Z='0' />
		</pins>
	</ghost>
	<components >
		<settings autoimg='0' center='1' unitscale='0' fixedscale='0' fixedx='25' fixedy='25' fixedz='25' headcode='0' />
		<definition guid='5af25872-aa2a-41ad-b66b-0943a76cd17d' vstate='40' vmin='0' vmaj='1' srcleaf='' visiblename='' description='' category='' category2='' category3='' bIs2dOnly='0' bIs3dOnly='0' bIsWysiwyg='0' catenable='1' author='' manuname='' manucode='' sysinfo='0' keywords='' dynamic='1' scadaCompatible='0' embeddedCompatible='1' showmacros='1' iconpath='' />
		<component class_type='root' codename='ComponentRoot' panelId='-1' x='0' y='0' z='0' xsz='1' ysz='1' zsz='1' xang='0' yang='0' zang='0' xquat='0' yquat='0' zquat='0' wquat='1' visible='1' scadavisible='1' interactive='1' solid='1' layer='0' poslock='0' ancTop='0' ancBottom='0' ancLeft='0' ancRight='0' ancMinX='0' ancMinY='0' comp2dType='0' >
			<resources />
			<properties />
			<values />
			<events />
			<apis />
			<variables >
				<variable public='0' >
					<def class_type='variable' name='b_next' type='u32' description='Pointer to float grid array' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='julia' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='1' setinit='1' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='render_complete' type='b1' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='dt' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='1.0' setinit='1.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='weight_diagonal' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.0500000007450580596923828125' setinit='0.05' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='false' type='b1' description='' isconst='1' isHidden='0' isinit='1' usrinit='0' setinit='0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='kill' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.061999998986721038818359375' setinit='0.062' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='zoom' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='1.0' setinit='1.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='centre_re' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='-0.5' setinit='-0.5' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='palette' type='u16' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' >
						<array size='500' />
					</def>
				</variable>
				<variable public='0' >
					<def class_type='variable' name='feed' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.05449999868869781494140625' setinit='0.0545' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='julia_c_im' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.0' setinit='0.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='a_next' type='u32' description='Pointer to float grid array' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='HEIGHT' type='u32' description='' isconst='1' isHidden='0' isinit='1' usrinit='800' setinit='800' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='b_current' type='u32' description='Pointer to float grid array' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='WIDTH' type='u32' description='' isconst='1' isHidden='0' isinit='1' usrinit='800' setinit='800' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='colours' type='u16' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' >
						<array size='256' />
					</def>
				</variable>
				<variable public='0' >
					<def class_type='variable' name='weight_diagpnal' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.0500000007450580596923828125' setinit='0.05' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='weight_adjacent' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.20000000298023223876953125' setinit='0.2' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='Db' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.5' setinit='0.5' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='Da' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='1.0' setinit='1.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='weight_centre' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='-1.0' setinit='-1.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='redraw' type='b1' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='a_current' type='u32' description='Pointer to float grid array' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='centre_im' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.0' setinit='0.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='mandelbrot' type='u32' description='' isconst='1' isHidden='0' isinit='1' usrinit='0' setinit='0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='julia_c_re' type='f32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0.0' setinit='0.0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='image' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='true' type='b1' description='' isconst='1' isHidden='0' isinit='1' usrinit='1' setinit='1' />
				</variable>
				<variable public='0' >
					<def class_type='variable' name='max_iter' type='u16' description='' isconst='0' isHidden='0' isinit='1' usrinit='100' setinit='100' />
				</variable>
			</variables>
			<macros >
				<macro >
					<flowline name='SelectFractal' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<param name='event' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='opt' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<command class_type='native' title='Code' ccode='lv_obj_t *e = (lv_obj_t *)FCL_EVENT;

lv_obj_t * dropdown = (lv_obj_t *)lv_event_get_target(e);
FCL_OPT = lv_dropdown_get_selected(dropdown);' language='C' />
						<command class_type='decision' title='Decision' exp='.opt == 0' swap='0' >
							<flowline >
								<command class_type='calculation' title='Calculation' >
									<exp exp='image = mandelbrot' />
									<exp exp='centre_re = -0.5' />
									<exp exp='centre_im = 0.0' />
								</command>
							</flowline>
							<flowline >
								<command class_type='decision' title='Decision' exp='.opt == 1' swap='0' >
									<flowline >
										<command class_type='calculation' title='Calculation' >
											<exp exp='image = julia' />
											<exp exp='julia_c_re = -0.8' />
											<exp exp='julia_c_im = 0.156' />
											<exp exp='centre_re = 0.0' />
											<exp exp='centre_im = 0.0' />
										</command>
									</flowline>
									<flowline />
								</command>
							</flowline>
						</command>
						<command class_type='calculation' title='Calculation' >
							<exp exp='zoom = 1.0' />
							<exp exp='redraw = true' />
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='ScreenLVGL' description='Setup widgets for display' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<command class_type='native' title='Code' ccode='    // 1. Create a Column Flexbox container
    lv_obj_t * main_col = lv_obj_create(lv_screen_active());
    //lv_obj_remove_flag(lv_screen_active(), LV_OBJ_FLAG_SCROLLABLE);
    //lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x000000), 0);
    lv_obj_set_size(main_col, 800, 1280); // Native hardware resolution
    lv_obj_set_style_pad_all(main_col, 0, 0);
    lv_obj_set_style_border_width(main_col, 0, 0);
    lv_obj_set_layout(main_col, LV_LAYOUT_FLEX);
    lv_obj_set_flex_flow(main_col, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_bg_color(main_col, lv_color_hex(0x000000), 0);

    // --- TOP: THE FRACTAL CANVAS (800x800) ---
    size_t canvas_size = 800 * 800 * 2;
    canvas_buf = (uint16_t *)heap_caps_malloc(canvas_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
    canvas = lv_canvas_create(main_col);
    lv_canvas_set_buffer(canvas, canvas_buf, 800, 800, LV_COLOR_FORMAT_RGB565);
    lv_obj_add_flag(canvas, LV_OBJ_FLAG_CLICKABLE);
    lv_obj_remove_flag(canvas, LV_OBJ_FLAG_SCROLL_CHAIN); // Don&apos;t pass drags to the layout
    lv_obj_remove_flag(canvas, LV_OBJ_FLAG_SCROLLABLE);   // Don&apos;t scroll internally
    lv_obj_add_event_cb(canvas, FCM_CanvasClick, LV_EVENT_ALL, NULL);
    
    zoom_box = lv_obj_create(canvas);
    lv_obj_set_style_bg_opa(zoom_box, LV_OPA_TRANSP, 0); // Transparent center
    lv_obj_set_style_border_color(zoom_box, lv_color_hex(0x00FF00), 0); // Neon green border
    lv_obj_set_style_border_width(zoom_box, 3, 0);
    lv_obj_remove_flag(zoom_box, LV_OBJ_FLAG_CLICKABLE); // Let touches pass through
    lv_obj_add_flag(zoom_box, LV_OBJ_FLAG_HIDDEN); // Hide it until touched

    // --- BOTTOM: THE CONTROL PANEL (800x480) ---
    lv_obj_t * panel = lv_obj_create(main_col);
    lv_obj_set_size(panel, 800, 479);
    lv_obj_set_style_bg_color(panel, lv_color_hex(0x1a1a1a), 0);
    lv_obj_set_style_border_width(panel, 0, 0);
    
    // Use a ROW Wrap flex layout inside the panel so elements sit side-by-side
    lv_obj_set_layout(panel, LV_LAYOUT_FLEX);
    lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW_WRAP);
    lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_all(panel, 20, 0); 
    lv_obj_set_style_pad_row(panel, 30, 0);
    lv_obj_set_style_pad_column(panel, 40, 0); // Space between side-by-side elements

    // Title (Forces a line break if we make it 100% width)
    lv_obj_t * title = lv_label_create(panel);
    lv_label_set_text(title, &quot;Mandelbrot Explorer&quot;);
    lv_obj_set_style_text_color(title, lv_color_hex(0x00AAFF), 0);
    lv_obj_set_width(title, lv_pct(100)); // Take full width to push next items down
    lv_obj_set_style_text_align(title, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_style_text_font(title, &amp;lv_font_montserrat_30, 0);

    // Parameter Labels Container
    lv_obj_t * labels_cont = lv_obj_create(panel);
    lv_obj_set_size(labels_cont, 300, 200);
    lv_obj_set_style_bg_opa(labels_cont, LV_OPA_TRANSP, 0);
    lv_obj_set_style_border_width(labels_cont, 0, 0);
    lv_obj_set_layout(labels_cont, LV_LAYOUT_FLEX);
    lv_obj_set_flex_flow(labels_cont, LV_FLEX_FLOW_COLUMN);
    
    lbl_re = lv_label_create(labels_cont);
    lbl_im = lv_label_create(labels_cont);
    lbl_zoom = lv_label_create(labels_cont);
    lbl_iter = lv_label_create(labels_cont);
    lv_obj_set_style_text_color(lbl_re, lv_color_hex(0xCCCCCC), 0);
    lv_obj_set_style_text_color(lbl_im, lv_color_hex(0xCCCCCC), 0);
    lv_obj_set_style_text_color(lbl_zoom, lv_color_hex(0xFFFFFF), 0);
    lv_obj_set_style_text_color(lbl_iter, lv_color_hex(0xFFFFFF), 0);

    // Controls Container
    lv_obj_t * controls_cont = lv_obj_create(panel);
    lv_obj_set_size(controls_cont, 350, 200);
    lv_obj_set_style_bg_opa(controls_cont, LV_OPA_TRANSP, 0);
    lv_obj_set_style_border_width(controls_cont, 0, 0);
    lv_obj_set_layout(controls_cont, LV_LAYOUT_FLEX);
    lv_obj_set_flex_flow(controls_cont, LV_FLEX_FLOW_COLUMN);

    lv_obj_t * reset_btn = lv_button_create(controls_cont);
    lv_obj_set_size(reset_btn, 300, 60);
    lv_obj_set_style_bg_color(reset_btn, lv_color_hex(0xAA0000), 0);
    lv_obj_add_event_cb(reset_btn, FCM_ResetBtn, LV_EVENT_CLICKED, NULL);
    
    lv_obj_t * reset_lbl = lv_label_create(reset_btn);
    lv_label_set_text(reset_lbl, &quot;Reset View&quot;);
    lv_obj_center(reset_lbl);

// Fractal Selection Dropdown
    dropdown = lv_dropdown_create(panel);
    lv_obj_set_style_align(dropdown, LV_ALIGN_CENTER, 0);
    lv_obj_set_width(dropdown, lv_pct(100));
//    lv_obj_set_width(dropdown, 300);
//    lv_obj_set_style_margin_bottom(dropdown, 300, 0); // Spacing
    lv_dropdown_set_options(dropdown, &quot;Mandelbrot Set\nJulia Set&quot;);
    lv_obj_add_event_cb(dropdown, FCM_SelectFractal, LV_EVENT_VALUE_CHANGED, NULL);

    
    status_box = lv_obj_create(panel);
    lv_obj_set_size(status_box, 200, 50);
    lv_obj_set_style_bg_color(status_box, lv_color_hex(0x00FF00), 0); // Start Green
    lv_obj_set_style_border_width(status_box, 0, 0);
    lv_obj_set_style_margin_top(status_box, 20, 0);
    
    status_label = lv_label_create(status_box);
    lv_label_set_text(status_label, &quot;Ready&quot;);
    lv_obj_set_style_text_color(status_label, lv_color_hex(0x000000), 0); // Black text
    lv_obj_center(status_label);
' language='C' />
						<command class_type='calculation' title='Calculation' >
							<exp exp='redraw = true' />
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='ResetBtn' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<command class_type='calculation' title='Calculation' >
							<exp exp='centre_im = 0.0' />
							<exp exp='zoom = 1.0' />
							<exp exp='max_iter = 100' />
							<exp exp='redraw = true' />
						</command>
						<command class_type='decision' title='Decision' exp='image == julia' swap='0' >
							<flowline >
								<command class_type='calculation' title='Calculation' >
									<exp exp='centre_re = 0.0' />
								</command>
							</flowline>
							<flowline >
								<command class_type='calculation' title='Calculation' >
									<exp exp='centre_re = -0.5' />
								</command>
							</flowline>
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='CanvasClick' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<param name='lv_event' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<command class_type='native' title='Code' ccode='const int CANVAS_W = 800;
const int CANVAS_H = 800;

    lv_event_t *e = (lv_event_t *) FCL_LV_EVENT;
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * canvas = (lv_obj_t *)lv_event_get_target(e);
    uint8_t * buf = (uint8_t *)lv_event_get_user_data(e);
    
    // Get raw touch coordinates
    lv_indev_t * indev = lv_indev_active();
    if(indev == NULL) return;
    lv_point_t p;
    lv_indev_get_point(indev, &amp;p);

    // Translate to canvas-relative coordinates
    lv_area_t coords;
    lv_obj_get_coords(canvas, &amp;coords);
    int local_x = p.x - coords.x1;
    int local_y = p.y - coords.y1;

    // Clamp coordinates to ensure we don&apos;t drag out of bounds
    if(local_x &lt; 0) local_x = 0;
    if(local_x &gt;= CANVAS_W) local_x = CANVAS_W - 1;
    if(local_y &lt; 0) local_y = 0;
    if(local_y &gt;= CANVAS_H) local_y = CANVAS_H - 1;

    if (code == LV_EVENT_PRESSED) {
        // Finger touched down: Anchor the start point and unhide the box
        drag_start_x = local_x;
        drag_start_y = local_y;
        lv_obj_set_pos(zoom_box, drag_start_x, drag_start_y);
        lv_obj_set_size(zoom_box, 0, 0);
        lv_obj_remove_flag(zoom_box, LV_OBJ_FLAG_HIDDEN);
    } else if (code == LV_EVENT_PRESSING) {
        // Finger is moving: Calculate the top-left corner and the width/height
        int x1 = (local_x &lt; drag_start_x) ? local_x : drag_start_x;
        int y1 = (local_y &lt; drag_start_y) ? local_y : drag_start_y;
        int w = abs(local_x - drag_start_x);
        int h = abs(local_y - drag_start_y);
        
        // Update the visual box dynamically
        lv_obj_set_pos(zoom_box, x1, y1);
        lv_obj_set_size(zoom_box, w, h);
        
    } else if (code == LV_EVENT_RELEASED) {
        // Finger lifted: Hide the box and calculate the math
        lv_obj_add_flag(zoom_box, LV_OBJ_FLAG_HIDDEN);
        
        int w = abs(local_x - drag_start_x);
        int h = abs(local_y - drag_start_y);
        int max_dim = (w &gt; h) ? w : h; // Use largest side to prevent distortion
        
        // Only zoom if the drag box is larger than 20 pixels (ignore accidental twitches)
        if (max_dim &gt; 20) {
            // Find the center of the dragged box
            int box_center_x = drag_start_x + (local_x - drag_start_x) / 2;
            int box_center_y = drag_start_y + (local_y - drag_start_y) / 2;
            
            // Calculate how much we are zooming in
            float zoom_factor = (float)CANVAS_W / (float)max_dim;
            
            // Reverse math: Map pixel center back to Complex Plane
            float clicked_re = FCV_CENTRE_RE + (box_center_x - CANVAS_W / 2.0f) * (4.0f / (CANVAS_W * FCV_ZOOM));
            float clicked_im = FCV_CENTRE_IM + (box_center_y - CANVAS_H / 2.0f) * (4.0f / (CANVAS_W * FCV_ZOOM));
            
            // Apply new state
            FCV_CENTRE_RE = clicked_re;
            FCV_CENTRE_IM = clicked_im;
            FCV_ZOOM *= zoom_factor;
            FCV_MAX_ITER += (int)(zoom_factor * 2); // Add more detail for deeper zooms
            FCV_REDRAW = true;
        } else {
            // If it was a small tap AND we are looking at the Mandelbrot set...
            if (FCV_IMAGE == FCV_MANDELBROT) {
                
                // 1. Calculate the exact complex coordinate you tapped
                float tapped_re = center_re + (local_x - CANVAS_W / 2.0f) * (4.0f / (CANVAS_W * FCV_ZOOM));
                float tapped_im = center_im + (local_y - CANVAS_H / 2.0f) * (4.0f / (CANVAS_W * FCV_ZOOM));
                
                // 2. Set those coordinates as the new Julia C shape constant
                FCV_JULIA_C_RE = tapped_re;
                FCV_JULIA_C_IM = tapped_im;
                
                // 3. Switch the math engine to Julia and reset the camera
                FCV_IMAGE = FCV_JULIA;
                FCV_CENTRE_RE = 0.0f; 
                FCV_CENTRE_IM = 0.0f;
                FCV_ZOOM = 1.0f;
                
                // 4. Synchronize the UI dashboard to match the new state
                if (dropdown) lv_dropdown_set_selected(dropdown, 1);
                
                FCV_REDRAW = 1;
            }
        }
    }
' language='C' />
					</flowline>
				</macro>
				<macro >
					<flowline name='DrawMandelbrot' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<local name='y' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='x' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='c_re' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='c_im' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='x_new' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_re' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_im' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='iter' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='q' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='c_im_sq' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_re_sq' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_im_sq' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<command class_type='loop' title='Loop' type='2' forvar='.y' exp='HEIGHT' for1='' for3='' >
							<flowline >
								<command class_type='loop' title='Loop' type='2' forvar='.x' exp='WIDTH' for1='' for3='' >
									<flowline >
										<command class_type='calculation' title='Calculation' >
											<exp exp='.c_re = centre_re + (.x - WIDTH / 2.0) * (4.0 / (WIDTH * zoom))' />
											<exp exp='.c_im = centre_im + (.y - HEIGHT / 2.0) * (4.0 / (HEIGHT * zoom))' />
											<exp exp='.z_re = 0.0' />
											<exp exp='.z_im = 0.0' />
											<exp exp='.iter = 0' />
										</command>
										<command class_type='calculation' title='Calculation' >
											<exp exp='.c_im_sq = .c_im * .c_im' />
											<exp exp='.q = sqrt((.c_re - 0.25) * (.c_re - 0.25) + .c_im_sq)' />
										</command>
										<command class_type='decision' title='Decision' exp='(.c_re &lt;= (.q - 2.0 * .q * .q + 0.025)) || ((.c_re + 1.0) * (.c_re + 1.0) + .c_im_sq &lt; 0.0625)' swap='0' >
											<flowline >
												<command class_type='calculation' title='Calculation' >
													<exp exp='.iter = max_iter' />
												</command>
											</flowline>
											<flowline >
												<command class_type='calculation' title='Calculation' >
													<exp exp='.z_im_sq = .z_im * .z_im' />
													<exp exp='.z_re_sq = .z_re * .z_re' />
												</command>
												<command class_type='loop' title='Loop' type='0' exp='(.z_re_sq + .z_im_sq &lt;= 4) &amp;&amp; (.iter &lt; max_iter)' for1='' for3='' >
													<flowline >
														<command class_type='calculation' title='Calculation' >
															<exp exp='.x_new = .z_re_sq - .z_im_sq + .c_re' />
															<exp exp='.z_im = 2 * .z_re * .z_im + .c_im' />
															<exp exp='.z_re = .x_new' />
															<exp exp='.iter += 1' />
														</command>
														<command class_type='calculation' title='Calculation' >
															<exp exp='.z_im_sq = .z_im * .z_im' />
															<exp exp='.z_re_sq = .z_re * .z_re' />
														</command>
													</flowline>
												</command>
											</flowline>
										</command>
										<command class_type='native' title='Code' ccode='canvas_buf[FCL_Y * FCV_WIDTH + FCL_X] = FCV_PALETTE[FCL_ITER];' language='C' />
									</flowline>
								</command>
							</flowline>
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='DrawJulia' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<local name='i' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='x' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='y' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='iter' type='u32' description='' isconst='0' isHidden='0' isinit='1' usrinit='0' setinit='0' />
						<local name='px_im' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_im' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='z_re' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='x_new' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<local name='px_re' type='f32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0.0' setinit='' />
						<command class_type='loop' title='Loop' type='2' forvar='.y' exp='HEIGHT' for1='' for3='' >
							<flowline >
								<command class_type='loop' title='Loop' type='2' forvar='.x' exp='WIDTH' for1='' for3='' >
									<flowline >
										<command class_type='calculation' title='Calculation' >
											<exp exp='.px_re = centre_re + (.x - 800 / 2.0) * (4.0 / (800 * zoom))' />
											<exp exp='.px_im = centre_im + (.y - 800 / 2.0) * (4.0 / (800 * zoom))' />
											<exp exp='.iter = 0' />
											<exp exp='' />
											<exp exp='.z_re = .px_re' />
											<exp exp='.z_im = .px_im' />
										</command>
										<command class_type='loop' title='Loop' type='0' exp='(.z_re * .z_re + .z_im * .z_im &lt;= 4.0) &amp;&amp; (.iter &lt; max_iter)' for1='' for3='' >
											<flowline >
												<command class_type='calculation' title='Calculation' >
													<exp exp='.x_new = .z_re * .z_re - .z_im * .z_im + julia_c_re' />
													<exp exp='.z_im = 2.0 * .z_re * .z_im + julia_c_im' />
													<exp exp='.z_re = .x_new' />
													<exp exp='.iter += 1' />
												</command>
											</flowline>
										</command>
										<command class_type='native' title='Code' ccode='canvas_buf[FCL_Y * FCV_WIDTH + FCL_X] = FCV_PALETTE[FCL_ITER];
' language='C' />
									</flowline>
								</command>
							</flowline>
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='UpdateLabels' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<command class_type='native' title='Code' ccode='lv_label_set_text_fmt(lbl_re, &quot;Real (X): %f&quot;, FCV_CENTRE_RE);
lv_label_set_text_fmt(lbl_im, &quot;Imag (Y): %f&quot;, FCV_CENTRE_IM);
lv_label_set_text_fmt(lbl_zoom, &quot;Zoom: %.1fx&quot;, FCV_ZOOM);
lv_label_set_text_fmt(lbl_iter, &quot;Max Iterations: %d&quot;, FCV_MAX_ITER);
' language='C' />
					</flowline>
				</macro>
				<macro >
					<flowline name='Refresh' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<command class_type='loop' title='Loop' type='3' exp='1' for1='' for3='' >
							<flowline >
								<command class_type='native' title='Code' ccode='lv_tick_inc(10);
lv_timer_handler();
' language='C' />
								<command class_type='delay' title='Delay' exp='10' type='1' />
							</flowline>
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='GeneratePalette' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<param name='max_iterations' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='r' type='u8' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='b' type='u8' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='g' type='u8' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<local name='i' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<command class_type='loop' title='Loop' type='2' forvar='.i' exp='.max_iterations' for1='' for3='' >
							<flowline >
								<command class_type='calculation' title='Calculation' >
									<exp exp='.r = sin(0.1 * .i) * 127 + 128' />
									<exp exp='.g = sin(0.1 * .i + 2) * 127 + 128' />
									<exp exp='.b = sin(0.1 + .i + 4) * 127 + 128' />
									<exp exp='palette[.i] = ((.r &amp; 0xF8) &lt;&lt; 8) | ((.g &amp; 0xFC) &lt;&lt; 3) | (.b &gt;&gt; 3)' />
								</command>
							</flowline>
						</command>
						<command class_type='calculation' title='Calculation' >
							<exp exp='palette[.max_iterations] = 0 // black when tends to infinity' />
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='RenderTask' description='Wait for a signal from the main task - then render the current fractal / image
Signals &apos;main&apos; when done by setting render_complete to true' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<local name='signal' type='u32' description='' isconst='0' isHidden='0' isinit='0' usrinit='0' setinit='' />
						<command class_type='native' title='Avoid WDT issues - rendering can take some time' ccode='esp_task_wdt_deinit();' language='C' />
						<command class_type='loop' title='Loop' type='3' exp='1' for1='' for3='' >
							<flowline >
								<command class_type='native' title='Wait for a signal from main' ccode='FCL_SIGNAL = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);' language='C' />
								<command class_type='decision' title='Decision' exp='image == mandelbrot' swap='0' >
									<flowline >
										<command class_type='call' title='User Macro' macro='DrawMandelbrot' />
									</flowline>
									<flowline >
										<command class_type='call' title='User Macro' macro='DrawJulia' />
									</flowline>
								</command>
								<command class_type='calculation' title='Calculation' >
									<exp exp='render_complete = true' />
								</command>
							</flowline>
						</command>
					</flowline>
				</macro>
				<macro >
					<flowline name='Main' description='' statediag='0' >
						<return name='Return' type='v0' description='' isconst='0' isHidden='0' isinit='0' usrinit='' setinit='' />
						<command class_type='native' title='Code' ccode='test_main();' language='C' />
						<command class_type='native' title='Code' ccode='xTaskCreate(FCM_Refresh, &quot;Refresh Display&quot;, 10240, NULL, 5, NULL);
xTaskCreatePinnedToCore(FCM_RenderTask, &quot;RenderTask&quot;, 8192, 0, 5, &amp;render_task_handle, 1);
' language='C' />
						<command class_type='call' title='User Macro' macro='ScreenLVGL' />
						<command class_type='loop' title='Loop' type='3' exp='1' for1='' for3='' >
							<flowline >
								<command class_type='decision' title='Decision' exp='redraw' swap='0' >
									<flowline >
										<command class_type='calculation' title='Calculation' >
											<exp exp='render_complete = false' />
										</command>
										<command class_type='call' title='User Macro' macro='GeneratePalette' >
											<argument exp='max_iter' />
										</command>
										<command class_type='native' title='Code' ccode='lv_obj_set_style_bg_color(status_box, lv_color_hex(0xFF0000), 0);
lv_label_set_text(status_label, &quot;Calculating...&quot;);
lv_timer_handler();' language='C' />
										<command class_type='call' title='User Macro' macro='UpdateLabels' />
										<command class_type='native' title='Code' ccode='xTaskNotifyGive(render_task_handle);' language='C' />
										<command class_type='calculation' title='Calculation' >
											<exp exp='redraw = false' />
										</command>
									</flowline>
									<flowline />
								</command>
								<command class_type='decision' title='Decision' exp='render_complete' swap='0' >
									<flowline >
										<command class_type='calculation' title='Calculation' >
											<exp exp='render_complete = false' />
										</command>
										<command class_type='native' title='Code' ccode='lv_obj_set_style_bg_color(status_box, lv_color_hex(0x00FF00), 0);
lv_label_set_text(status_label, &quot;Ready&quot;);
lv_obj_invalidate(canvas);' language='C' />
									</flowline>
									<flowline />
								</command>
								<command class_type='delay' title='Delay' exp='10' type='1' />
							</flowline>
						</command>
					</flowline>
				</macro>
			</macros>
		</component>
	</components>
	<scadaresourcelookup />
	<keymap />
	<panel2d shadows='0' lighting='2' brightness='0' >
		<background rgb='7292207' img='' style='0' />
		<camera xe='0' ye='0' ze='1098.27' xt='0' yt='0' zt='0' xquat='0' yquat='0' zquat='0' wquat='1' />
		<viewport dx='351' dy='1640' zoom='38.6707' fix_topleft='0' />
		<page x='1000' y='1000' show='0' rgb='7360576' />
		<winpos ID='7005' RectRecentFloat='794,0,1444,576' RectRecentDocked='0,0,351,1690' RecentFrameAlignment='16384' RecentRowIndex='0' IsFloating='0' MRUWidth='32767' PinState='0' IsMaximized='0' IsVisible='0' />
	</panel2d>
	<panel3d shadows='0' lighting='2' brightness='0' perspective='1' >
		<background rgb='8409120' img='' style='0' />
		<table rgb='7360576' img='' style='0' size='0' />
		<camera xe='0' ye='0' ze='781.66' xt='0' yt='0' zt='0' xquat='0' yquat='0' zquat='0' wquat='1' />
		<camerakey0 xe='0' ye='0' ze='300' xt='0' yt='0' zt='0' xquat='0' yquat='0' zquat='0' wquat='1' />
		<camerakey1 xe='-3.67394e-14' ye='0' ze='-300' xt='0' yt='0' zt='0' xquat='0' yquat='1' zquat='0' wquat='6.12323e-17' />
		<camerakey2 xe='0' ye='-300' ze='6.66134e-14' xt='0' yt='0' zt='0' xquat='-0.707107' yquat='0' zquat='0' wquat='0.707107' />
		<camerakey3 xe='-3.67394e-14' ye='300' ze='6.66134e-14' xt='0' yt='0' zt='0' xquat='-4.32978e-17' yquat='0.707107' zquat='0.707107' wquat='4.32978e-17' />
		<camerakey4 xe='-300' ye='-6.66134e-14' ze='6.66134e-14' xt='0' yt='0' zt='0' xquat='-0.5' yquat='0.5' zquat='0.5' wquat='0.5' />
		<camerakey5 xe='300' ye='-6.66134e-14' ze='6.66134e-14' xt='0' yt='0' zt='0' xquat='-0.5' yquat='-0.5' zquat='-0.5' wquat='0.5' />
		<camerakey6 xe='-173.205' ye='-173.205' ze='173.205' xt='0' yt='0' zt='0' xquat='-0.424708' yquat='0.17592' zquat='0.339851' wquat='0.820473' />
		<winpos ID='7004' RectRecentFloat='642,390,1292,840' RectRecentDocked='0,0,210,1690' RecentFrameAlignment='16384' RecentRowIndex='0' IsFloating='0' MRUWidth='32767' PinState='0' IsMaximized='0' IsVisible='0' />
	</panel3d>
	<panels2d count='1' >
		<panel2d_0 id='0' name='NewPanel' type='0' >
			<winpos ID='1171' RectRecentFloat='167,107,817,557' RectRecentDocked='3198,328,3840,2018' RecentFrameAlignment='16384' RecentRowIndex='0' IsFloating='1' MRUWidth='32767' PinState='0' IsMaximized='0' IsVisible='0' />
			<background fill='288230376151053813' showgrid='1' gridstyle='1' gridsize='10' gridbrush='71776119075691740' snaptogrid='1' fitcomp='0' disp_x='300' disp_y='400' scale='400' disp_col='16777215' />
		</panel2d_0>
	</panels2d>
	<layout >
		<view type='0' name='Main' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='220' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='Refresh' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='260' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='DrawMandelbrot' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='160' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='ScreenLVGL' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='180' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='ResetBtn' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='240' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='UpdateLabels' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='135' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='CanvasClick' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='180' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='GeneratePalette' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='190' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='DrawJulia' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='240' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='RenderTask' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='200' scrollx='0' scrolly='0' flags='0' />
		<view type='0' name='SelectFractal' mode='0' placement='LAAAAAAAAAABAAAA---------------------wUAAAAzAAAAEA0AAJUGAAA' zoom='170' scrollx='0' scrolly='0' flags='0' />
	</layout>
</document>
</root>
