summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomer Shalev <shalev.tomer@gmail.com>2010-01-15 05:53:15 +0000
committerTomer Shalev <shalev.tomer@gmail.com>2010-01-15 05:53:15 +0000
commit7719d297f2a1da0e45fd39cad21e99e23fd695c8 (patch)
treeae2b97d1b372340627ca3537554cd45310bace92
parent51630cbac1dcb04345fb1384812f1576f0ea29db (diff)
FS#10911 - Plugins: Fractals (formerly Mandelbrot)
- Rename the mandelbrot plugin to fractals - Update manual accordingly - Separate plugin's functionality into separate files - Lay the ground for having fractals sets other than the Mandelbrot set. For that the following will need to be implemented: - Create a new file for the new fracral set - Provide key mapping to switch between sets git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24230 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/CATEGORIES2
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/SUBDIRS1
-rw-r--r--apps/plugins/fractals/SOURCES10
-rw-r--r--apps/plugins/fractals/cpu_arm.c40
-rw-r--r--apps/plugins/fractals/cpu_arm.h27
-rw-r--r--apps/plugins/fractals/cpu_coldfire.c58
-rw-r--r--apps/plugins/fractals/cpu_coldfire.h29
-rw-r--r--apps/plugins/fractals/cpu_sh7043.c94
-rw-r--r--apps/plugins/fractals/cpu_sh7043.h29
-rw-r--r--apps/plugins/fractals/fractal.c260
-rw-r--r--apps/plugins/fractals/fractal.h352
-rw-r--r--apps/plugins/fractals/fractal_rect.c209
-rw-r--r--apps/plugins/fractals/fractal_rect.h38
-rw-r--r--apps/plugins/fractals/fractal_sets.h52
-rw-r--r--apps/plugins/fractals/fractals.make21
-rw-r--r--apps/plugins/fractals/mandelbrot_set.c392
-rw-r--r--apps/plugins/fractals/mandelbrot_set.h60
-rw-r--r--manual/plugins/fractals.tex (renamed from manual/plugins/mandelbrot.tex)2
-rw-r--r--manual/plugins/main.tex4
20 files changed, 1676 insertions, 5 deletions
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index fc9589282e..a41514f93d 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -41,7 +41,7 @@ keybox,apps
lamp,apps
logo,demos
lua,viewers
-mandelbrot,demos
+fractals,demos
matrix,demos
maze,games
mazezam,games
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index a3ce60fbf8..16f7ff6f9a 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -77,7 +77,6 @@ codebuster.c
/* Plugins needing the grayscale lib on low-depth LCDs */
fire.c
-mandelbrot.c
plasma.c
blackjack.c
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index 587050fb94..0993e8221c 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -20,6 +20,7 @@ rockboy
pictureflow
#endif
chessbox
+fractals
jpeg
sudoku
reversi
diff --git a/apps/plugins/fractals/SOURCES b/apps/plugins/fractals/SOURCES
new file mode 100644
index 0000000000..72a22467c2
--- /dev/null
+++ b/apps/plugins/fractals/SOURCES
@@ -0,0 +1,10 @@
+fractal.c
+fractal_rect.c
+mandelbrot_set.c
+#if CONFIG_CPU == SH7034
+cpu_sh7043.c
+#elif defined CPU_COLDFIRE
+cpu_coldfire.c
+#elif defined CPU_ARM
+cpu_arm.c
+#endif
diff --git a/apps/plugins/fractals/cpu_arm.c b/apps/plugins/fractals/cpu_arm.c
new file mode 100644
index 0000000000..1d8b1a76f6
--- /dev/null
+++ b/apps/plugins/fractals/cpu_arm.c
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "cpu_arm.h"
+
+inline long muls32_asr26(long a, long b)
+{
+ long r, t1;
+ asm (
+ "smull %[r], %[t1], %[a], %[b] \n"
+ "mov %[r], %[r], lsr #26 \n"
+ "orr %[r], %[r], %[t1], lsl #6 \n"
+ : /* outputs */
+ [r] "=&r,&r,&r"(r),
+ [t1]"=&r,&r,&r"(t1)
+ : /* inputs */
+ [a] "%r,%r,%r" (a),
+ [b] "r,0,1" (b)
+ );
+ return r;
+}
+
diff --git a/apps/plugins/fractals/cpu_arm.h b/apps/plugins/fractals/cpu_arm.h
new file mode 100644
index 0000000000..51a3718f66
--- /dev/null
+++ b/apps/plugins/fractals/cpu_arm.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _CPU_ARM_H
+#define _CPU_ARM_H
+
+inline long muls32_asr26(long a, long b);
+
+#endif
diff --git a/apps/plugins/fractals/cpu_coldfire.c b/apps/plugins/fractals/cpu_coldfire.c
new file mode 100644
index 0000000000..a005a3141e
--- /dev/null
+++ b/apps/plugins/fractals/cpu_coldfire.c
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "cpu_coldfire.h"
+
+inline short muls16_asr10(short a, short b)
+{
+ asm (
+ "muls.w %[a],%[b] \n"
+ "asr.l #8,%[b] \n"
+ "asr.l #2,%[b] \n"
+ : /* outputs */
+ [b]"+d"(b)
+ : /* inputs */
+ [a]"d" (a)
+ );
+ return b;
+}
+
+inline long muls32_asr26(long a, long b)
+{
+ long r, t1;
+ asm (
+ "mac.l %[a], %[b], %%acc0 \n" /* multiply */
+ "move.l %%accext01, %[t1] \n" /* get low part */
+ "movclr.l %%acc0, %[r] \n" /* get high part */
+ "asl.l #5, %[r] \n" /* hi <<= 5, plus one free */
+ "lsr.l #3, %[t1] \n" /* lo >>= 3 */
+ "and.l #0x1f, %[t1] \n" /* mask out unrelated bits */
+ "or.l %[t1], %[r] \n" /* combine result */
+ : /* outputs */
+ [r] "=d"(r),
+ [t1]"=d"(t1)
+ : /* inputs */
+ [a] "d" (a),
+ [b] "d" (b)
+ );
+ return r;
+}
+
diff --git a/apps/plugins/fractals/cpu_coldfire.h b/apps/plugins/fractals/cpu_coldfire.h
new file mode 100644
index 0000000000..452f18e2c5
--- /dev/null
+++ b/apps/plugins/fractals/cpu_coldfire.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _CPU_COLDFIRE_H
+#define _CPU_COLDFIRE_H
+
+inline short muls16_asr10(short a, short b);
+
+inline long muls32_asr26(long a, long b);
+
+#endif
diff --git a/apps/plugins/fractals/cpu_sh7043.c b/apps/plugins/fractals/cpu_sh7043.c
new file mode 100644
index 0000000000..1bce37d654
--- /dev/null
+++ b/apps/plugins/fractals/cpu_sh7043.c
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "cpu_sh7043.h"
+
+inline short muls16_asr10(short a, short b)
+{
+ short r;
+ asm (
+ "muls %[a],%[b] \n"
+ "sts macl,%[r] \n"
+ "shlr8 %[r] \n"
+ "shlr2 %[r] \n"
+ : /* outputs */
+ [r]"=r"(r)
+ : /* inputs */
+ [a]"r"(a),
+ [b]"r"(b)
+ );
+ return r;
+}
+
+inline long muls32_asr26(long a, long b)
+{
+ long r, t1, t2, t3;
+ asm (
+ /* Signed 32bit * 32bit -> 64bit multiplication.
+ Notation: xxab * xxcd, where each letter represents 16 bits.
+ xx is the 64 bit sign extension. */
+ "swap.w %[a],%[t1] \n" /* t1 = ba */
+ "mulu %[t1],%[b] \n" /* a * d */
+ "swap.w %[b],%[t3] \n" /* t3 = dc */
+ "sts macl,%[t2] \n" /* t2 = a * d */
+ "mulu %[t1],%[t3] \n" /* a * c */
+ "sts macl,%[r] \n" /* hi = a * c */
+ "mulu %[a],%[t3] \n" /* b * c */
+ "clrt \n"
+ "sts macl,%[t3] \n" /* t3 = b * c */
+ "addc %[t2],%[t3] \n" /* t3 += t2, carry -> t2 */
+ "movt %[t2] \n"
+ "mulu %[a],%[b] \n" /* b * d */
+ "mov %[t3],%[t1] \n" /* t1t3 = t2t3 << 16 */
+ "xtrct %[t2],%[t1] \n"
+ "shll16 %[t3] \n"
+ "sts macl,%[t2] \n" /* lo = b * d */
+ "clrt \n" /* hi.lo += t1t3 */
+ "addc %[t3],%[t2] \n"
+ "addc %[t1],%[r] \n"
+ "cmp/pz %[a] \n" /* ab >= 0 ? */
+ "bt 1f \n"
+ "sub %[b],%[r] \n" /* no: hi -= cd (sign extension of ab is -1) */
+ "1: \n"
+ "cmp/pz %[b] \n" /* cd >= 0 ? */
+ "bt 2f \n"
+ "sub %[a],%[r] \n" /* no: hi -= ab (sign extension of cd is -1) */
+ "2: \n"
+ /* Shift right by 26 and return low 32 bits */
+ "shll2 %[r] \n" /* hi <<= 6 */
+ "shll2 %[r] \n"
+ "shll2 %[r] \n"
+ "shlr16 %[t2] \n" /* (unsigned)lo >>= 26 */
+ "shlr8 %[t2] \n"
+ "shlr2 %[t2] \n"
+ "or %[t2],%[r] \n" /* combine result */
+ : /* outputs */
+ [r] "=&r"(r),
+ [t1]"=&r"(t1),
+ [t2]"=&r"(t2),
+ [t3]"=&r"(t3)
+ : /* inputs */
+ [a] "r" (a),
+ [b] "r" (b)
+ );
+ return r;
+}
+
diff --git a/apps/plugins/fractals/cpu_sh7043.h b/apps/plugins/fractals/cpu_sh7043.h
new file mode 100644
index 0000000000..4805092377
--- /dev/null
+++ b/apps/plugins/fractals/cpu_sh7043.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _CPU_SH7043_H
+#define _CPU_SH7043_H
+
+inline short muls16_asr10(short a, short b);
+
+inline long muls32_asr26(long a, long b);
+
+#endif
diff --git a/apps/plugins/fractals/fractal.c b/apps/plugins/fractals/fractal.c
new file mode 100644
index 0000000000..3a0c785bdd
--- /dev/null
+++ b/apps/plugins/fractals/fractal.c
@@ -0,0 +1,260 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2004 Matthias Wientapper
+ * Heavily extended 2005 Jens Arnold
+ * Extended 2009 Tomer Shalev
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+#ifdef HAVE_LCD_BITMAP
+
+#include "fractal.h"
+#include "fractal_rect.h"
+#include "fractal_sets.h"
+#include "mandelbrot_set.h"
+
+#if (LCD_DEPTH < 8)
+#define USEGSLIB
+#define MYLCD(fn) grey_ub_ ## fn
+#define MYLCD_UPDATE()
+#define MYXLCD(fn) grey_ub_ ## fn
+#else
+#define MYLCD(fn) rb->lcd_ ## fn
+#define MYLCD_UPDATE() rb->lcd_update();
+#define MYXLCD(fn) xlcd_ ## fn
+#endif
+
+#ifdef USEGSLIB
+GREY_INFO_STRUCT
+static unsigned char *gbuf;
+static size_t gbuf_size = 0;
+unsigned char imgbuffer[LCD_HEIGHT];
+#else
+fb_data imgbuffer[LCD_HEIGHT];
+#endif
+
+#define REDRAW_NONE 0
+#define REDRAW_PARTIAL 1
+#define REDRAW_FULL 2
+
+PLUGIN_HEADER
+
+/* returns 1 if a button has been pressed, 0 otherwise */
+static int button_yield(void *ctx)
+{
+ long *button = (long *)ctx;
+
+ *button = rb->button_get(false);
+ switch (*button)
+ {
+ case FRACTAL_QUIT:
+ case FRACTAL_UP:
+ case FRACTAL_DOWN:
+ case FRACTAL_LEFT:
+ case FRACTAL_RIGHT:
+ case FRACTAL_ZOOM_IN:
+ case FRACTAL_ZOOM_OUT:
+ case FRACTAL_PRECISION_INC:
+ case FRACTAL_PRECISION_DEC:
+ case FRACTAL_RESET:
+#ifdef FRACTAL_ZOOM_IN2
+ case FRACTAL_ZOOM_IN2:
+#endif
+#ifdef FRACTAL_ZOOM_IN_PRE
+ case FRACTAL_ZOOM_IN_PRE:
+#endif
+ return 1;
+ default:
+ *button = BUTTON_NONE;
+ return 0;
+ }
+}
+
+static void cleanup(void *parameter)
+{
+ (void)parameter;
+#ifdef USEGSLIB
+ grey_release();
+#endif
+}
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ long lastbutton = BUTTON_NONE;
+ int redraw = REDRAW_FULL;
+ struct fractal_ops *ops = &mandelbrot_ops;
+
+ (void)parameter;
+
+#ifdef USEGSLIB
+ /* get the remainder of the plugin buffer */
+ gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
+
+ /* initialize the greyscale buffer.*/
+ if (!grey_init(gbuf, gbuf_size, GREY_ON_COP, LCD_WIDTH, LCD_HEIGHT, NULL))
+ {
+ rb->splash(HZ, "Couldn't init greyscale display");
+ return 0;
+ }
+ grey_show(true); /* switch on greyscale overlay */
+#endif
+
+#if LCD_DEPTH > 1
+ rb->lcd_set_backdrop(NULL);
+#endif
+
+ ops->init();
+
+ /* main loop */
+ while (true)
+ {
+ long button = BUTTON_NONE;
+
+ if (redraw != REDRAW_NONE)
+ {
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+ if (redraw == REDRAW_FULL)
+ {
+ MYLCD(clear_display)();
+ MYLCD_UPDATE();
+ rects_queue_init();
+ }
+
+ /* paint all rects */
+ rects_calc_all(ops->calc, button_yield, (void *)&button);
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+ /* not interrupted by button press - screen is fully drawn */
+ redraw = (button == BUTTON_NONE) ? REDRAW_NONE : REDRAW_PARTIAL;
+ }
+
+ if (button == BUTTON_NONE)
+ button = rb->button_get(true);
+
+ switch (button)
+ {
+#ifdef FRACTAL_RC_QUIT
+ case FRACTAL_RC_QUIT:
+#endif
+ case FRACTAL_QUIT:
+#ifdef USEGSLIB
+ grey_release();
+#endif
+ return PLUGIN_OK;
+
+ case FRACTAL_ZOOM_OUT:
+#ifdef FRACTAL_ZOOM_OUT_PRE
+ if (lastbutton != FRACTAL_ZOOM_OUT_PRE)
+ break;
+#endif
+ ops->zoom(-1);
+ redraw = REDRAW_FULL;
+ break;
+
+
+ case FRACTAL_ZOOM_IN:
+#ifdef FRACTAL_ZOOM_IN_PRE
+ if (lastbutton != FRACTAL_ZOOM_IN_PRE)
+ break;
+#endif
+#ifdef FRACTAL_ZOOM_IN2
+ case FRACTAL_ZOOM_IN2:
+#endif
+ ops->zoom(1);
+ redraw = REDRAW_FULL;
+ break;
+
+ case FRACTAL_UP:
+ ops->move(0, +1);
+ MYXLCD(scroll_down)(LCD_SHIFT_Y);
+ MYLCD_UPDATE();
+ if (redraw != REDRAW_FULL)
+ redraw = rects_move_down() ? REDRAW_FULL : REDRAW_PARTIAL;
+ break;
+
+ case FRACTAL_DOWN:
+ ops->move(0, -1);
+ MYXLCD(scroll_up)(LCD_SHIFT_Y);
+ MYLCD_UPDATE();
+ if (redraw != REDRAW_FULL)
+ redraw = rects_move_up() ? REDRAW_FULL : REDRAW_PARTIAL;
+ break;
+
+ case FRACTAL_LEFT:
+ ops->move(-1, 0);
+ MYXLCD(scroll_right)(LCD_SHIFT_X);
+ MYLCD_UPDATE();
+ if (redraw != REDRAW_FULL)
+ redraw = rects_move_right() ? REDRAW_FULL : REDRAW_PARTIAL;
+ break;
+
+ case FRACTAL_RIGHT:
+ ops->move(+1, 0);
+ MYXLCD(scroll_left)(LCD_SHIFT_X);
+ MYLCD_UPDATE();
+ if (redraw != REDRAW_FULL)
+ redraw = rects_move_left() ? REDRAW_FULL : REDRAW_PARTIAL;
+ break;
+
+ case FRACTAL_PRECISION_DEC:
+#ifdef FRACTAL_PRECISION_DEC_PRE
+ if (lastbutton != FRACTAL_PRECISION_DEC_PRE)
+ break;
+#endif
+ if (ops->precision(-1))
+ redraw = REDRAW_FULL;
+
+ break;
+
+ case FRACTAL_PRECISION_INC:
+#ifdef FRACTAL_PRECISION_INC_PRE
+ if (lastbutton != FRACTAL_PRECISION_INC_PRE)
+ break;
+#endif
+ if (ops->precision(+1))
+ redraw = REDRAW_FULL;
+
+ break;
+
+ case FRACTAL_RESET:
+ ops->init();
+ redraw = REDRAW_FULL;
+ break;
+
+ default:
+ if (rb->default_event_handler_ex(button, cleanup, NULL)
+ == SYS_USB_CONNECTED)
+ return PLUGIN_USB_CONNECTED;
+ break;
+ }
+
+ if (button != BUTTON_NONE)
+ lastbutton = button;
+ }
+#ifdef USEGSLIB
+ grey_release();
+#endif
+ return PLUGIN_OK;
+}
+
+#endif
diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h
new file mode 100644
index 0000000000..e1dfd5b6c9
--- /dev/null
+++ b/apps/plugins/fractals/fractal.h
@@ -0,0 +1,352 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FRACTAL_H
+#define _FRACTAL_H
+
+/* variable button definitions */
+#if CONFIG_KEYPAD == RECORDER_PAD
+#define FRACTAL_QUIT BUTTON_OFF
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_PLAY
+#define FRACTAL_ZOOM_OUT BUTTON_ON
+#define FRACTAL_PRECISION_INC BUTTON_F2
+#define FRACTAL_PRECISION_DEC BUTTON_F1
+#define FRACTAL_RESET BUTTON_F3
+
+#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
+#define FRACTAL_QUIT BUTTON_OFF
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT BUTTON_ON
+#define FRACTAL_PRECISION_INC BUTTON_F2
+#define FRACTAL_PRECISION_DEC BUTTON_F1
+#define FRACTAL_RESET BUTTON_F3
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+#define FRACTAL_QUIT BUTTON_OFF
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_MENU
+#define FRACTAL_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
+#define FRACTAL_ZOOM_IN2 (BUTTON_MENU | BUTTON_UP)
+#define FRACTAL_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
+#define FRACTAL_PRECISION_INC (BUTTON_MENU | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_MENU | BUTTON_LEFT)
+#define FRACTAL_RESET (BUTTON_MENU | BUTTON_OFF)
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H300_PAD)
+#define FRACTAL_QUIT BUTTON_OFF
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT BUTTON_MODE
+#define FRACTAL_PRECISION_INC (BUTTON_ON | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_ON | BUTTON_LEFT)
+#define FRACTAL_RESET BUTTON_REC
+
+#define FRACTAL_RC_QUIT BUTTON_RC_STOP
+
+#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IPOD_3G_PAD) || \
+ (CONFIG_KEYPAD == IPOD_1G2G_PAD)
+#define FRACTAL_QUIT (BUTTON_SELECT | BUTTON_MENU)
+#define FRACTAL_UP BUTTON_MENU
+#define FRACTAL_DOWN BUTTON_PLAY
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_SCROLL_FWD
+#define FRACTAL_ZOOM_OUT BUTTON_SCROLL_BACK
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET (BUTTON_SELECT | BUTTON_PLAY)
+
+#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC_PRE BUTTON_PLAY
+#define FRACTAL_PRECISION_INC (BUTTON_PLAY | BUTTON_REL)
+#define FRACTAL_PRECISION_DEC_PRE BUTTON_PLAY
+#define FRACTAL_PRECISION_DEC (BUTTON_PLAY | BUTTON_REPEAT)
+#define FRACTAL_RESET BUTTON_REC
+
+#elif CONFIG_KEYPAD == GIGABEAT_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC BUTTON_VOL_UP
+#define FRACTAL_PRECISION_DEC BUTTON_VOL_DOWN
+#define FRACTAL_RESET BUTTON_A
+
+#elif CONFIG_KEYPAD == SANSA_E200_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_SCROLL_FWD
+#define FRACTAL_ZOOM_OUT BUTTON_SCROLL_BACK
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET BUTTON_REC
+
+#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
+#define FRACTAL_QUIT (BUTTON_HOME|BUTTON_REPEAT)
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_SCROLL_FWD
+#define FRACTAL_ZOOM_OUT BUTTON_SCROLL_BACK
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET (BUTTON_SELECT | BUTTON_REPEAT)
+
+#elif CONFIG_KEYPAD == SANSA_C200_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_VOL_UP
+#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET BUTTON_REC
+
+#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_VOL_UP
+#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET BUTTON_HOME
+
+#elif CONFIG_KEYPAD == SANSA_M200_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_VOL_UP
+#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN
+#define FRACTAL_PRECISION_INC (BUTTON_SELECT | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_SELECT | BUTTON_LEFT)
+#define FRACTAL_RESET (BUTTON_SELECT | BUTTON_UP)
+
+#elif CONFIG_KEYPAD == IRIVER_H10_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_SCROLL_UP
+#define FRACTAL_DOWN BUTTON_SCROLL_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_PLAY
+#define FRACTAL_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_PLAY
+#define FRACTAL_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC BUTTON_FF
+#define FRACTAL_PRECISION_DEC BUTTON_REW
+#define FRACTAL_RESET (BUTTON_PLAY | BUTTON_REW)
+
+#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
+#define FRACTAL_QUIT BUTTON_EQ
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC (BUTTON_PLAY | BUTTON_RIGHT)
+#define FRACTAL_PRECISION_DEC (BUTTON_PLAY | BUTTON_LEFT)
+#define FRACTAL_RESET BUTTON_MODE
+
+#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
+#define FRACTAL_QUIT BUTTON_BACK
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_VOL_UP
+#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN
+#define FRACTAL_PRECISION_INC BUTTON_PREV
+#define FRACTAL_PRECISION_DEC BUTTON_NEXT
+#define FRACTAL_RESET BUTTON_MENU
+
+#elif CONFIG_KEYPAD == MROBE100_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_SELECT
+#define FRACTAL_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC BUTTON_MENU
+#define FRACTAL_PRECISION_DEC BUTTON_PLAY
+#define FRACTAL_RESET BUTTON_DISPLAY
+
+#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
+#define FRACTAL_QUIT BUTTON_RC_REC
+#define FRACTAL_UP BUTTON_RC_VOL_UP
+#define FRACTAL_DOWN BUTTON_RC_VOL_DOWN
+#define FRACTAL_LEFT BUTTON_RC_REW
+#define FRACTAL_RIGHT BUTTON_RC_FF
+#define FRACTAL_ZOOM_IN_PRE BUTTON_RC_PLAY
+#define FRACTAL_ZOOM_IN (BUTTON_RC_PLAY | BUTTON_REL)
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_RC_PLAY
+#define FRACTAL_ZOOM_OUT (BUTTON_RC_PLAY | BUTTON_REPEAT)
+#define FRACTAL_PRECISION_INC_PRE BUTTON_RC_MODE
+#define FRACTAL_PRECISION_INC (BUTTON_RC_MODE|BUTTON_REL)
+#define FRACTAL_PRECISION_DEC_PRE BUTTON_RC_MODE
+#define FRACTAL_PRECISION_DEC (BUTTON_RC_MODE|BUTTON_REPEAT)
+#define FRACTAL_RESET BUTTON_RC_MENU
+
+#elif CONFIG_KEYPAD == COWON_D2_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+
+#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
+#define FRACTAL_QUIT BUTTON_BACK
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_PLAY
+#define FRACTAL_ZOOM_OUT BUTTON_MENU
+#define FRACTAL_PRECISION_INC (BUTTON_UP | BUTTON_CUSTOM)
+#define FRACTAL_PRECISION_DEC (BUTTON_DOWN | BUTTON_CUSTOM)
+#define FRACTAL_RESET BUTTON_SELECT
+
+#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN BUTTON_VIEW
+#define FRACTAL_ZOOM_OUT BUTTON_PLAYLIST
+#define FRACTAL_PRECISION_INC BUTTON_VOL_UP
+#define FRACTAL_PRECISION_DEC BUTTON_VOL_DOWN
+#define FRACTAL_RESET BUTTON_MENU
+
+#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_PREV
+#define FRACTAL_RIGHT BUTTON_NEXT
+#define FRACTAL_ZOOM_IN BUTTON_RIGHT
+#define FRACTAL_ZOOM_OUT BUTTON_LEFT
+#define FRACTAL_PRECISION_INC BUTTON_VOL_UP
+#define FRACTAL_PRECISION_DEC BUTTON_VOL_DOWN
+#define FRACTAL_RESET BUTTON_MENU
+
+#elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+
+#elif CONFIG_KEYPAD == ONDAVX777_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+
+#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
+#define FRACTAL_QUIT BUTTON_REC
+#define FRACTAL_UP BUTTON_UP
+#define FRACTAL_DOWN BUTTON_DOWN
+#define FRACTAL_LEFT BUTTON_LEFT
+#define FRACTAL_RIGHT BUTTON_RIGHT
+#define FRACTAL_ZOOM_IN_PRE (BUTTON_FFWD | BUTTON_UP)
+#define FRACTAL_ZOOM_IN (BUTTON_REW | BUTTON_UP)
+#define FRACTAL_ZOOM_OUT_PRE (BUTTON_FFWD | BUTTON_DOWN)
+#define FRACTAL_ZOOM_OUT (BUTTON_REW | BUTTON_DOWN)
+#define FRACTAL_PRECISION_INC (BUTTON_PLAY | BUTTON_UP)
+#define FRACTAL_PRECISION_DEC (BUTTON_FFWD | BUTTON_DOWN)
+#define FRACTAL_RESET (BUTTON_PLAY | BUTTON_RIGHT)
+
+#else
+#error No keymap defined!
+#endif
+
+#ifdef HAVE_TOUCHSCREEN
+#ifndef FRACTAL_UP
+#define FRACTAL_UP BUTTON_TOPMIDDLE
+#endif
+#ifndef FRACTAL_DOWN
+#define FRACTAL_DOWN BUTTON_BOTTOMMIDDLE
+#endif
+#ifndef FRACTAL_LEFT
+#define FRACTAL_LEFT BUTTON_MIDLEFT
+#endif
+#ifndef FRACTAL_RIGHT
+#define FRACTAL_RIGHT BUTTON_MIDRIGHT
+#endif
+#ifndef FRACTAL_ZOOM_IN_PRE
+#define FRACTAL_ZOOM_IN_PRE BUTTON_TOPRIGHT
+#endif
+#ifndef FRACTAL_ZOOM_IN
+#define FRACTAL_ZOOM_IN (BUTTON_TOPRIGHT | BUTTON_REL)
+#endif
+#ifndef FRACTAL_ZOOM_OUT_PRE
+#define FRACTAL_ZOOM_OUT_PRE BUTTON_TOPLEFT
+#endif
+#ifndef FRACTAL_ZOOM_OUT
+#define FRACTAL_ZOOM_OUT (BUTTON_TOPLEFT | BUTTON_REL)
+#endif
+#ifndef FRACTAL_PRECISION_INC
+#define FRACTAL_PRECISION_INC BUTTON_BOTTOMRIGHT
+#endif
+#ifndef FRACTAL_PRECISION_DEC
+#define FRACTAL_PRECISION_DEC BUTTON_BOTTOMLEFT
+#endif
+#ifndef FRACTAL_RESET
+#define FRACTAL_RESET BUTTON_CENTER
+#endif
+#endif
+
+#endif
+
diff --git a/apps/plugins/fractals/fractal_rect.c b/apps/plugins/fractals/fractal_rect.c
new file mode 100644
index 0000000000..af846d3f7a
--- /dev/null
+++ b/apps/plugins/fractals/fractal_rect.c
@@ -0,0 +1,209 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "fractal_rect.h"
+
+#define RECT_QUEUE_LEN 32
+
+#define QUEUE_NEXT(i) (((i) + 1) % RECT_QUEUE_LEN)
+#define QUEUE_PREV(i) (((i) - 1) % RECT_QUEUE_LEN)
+#define QUEUE_IS_EMPTY (QUEUE_NEXT(rectq.head) == rectq.tail)
+#define QUEUE_TAIL \
+ (&rectq.rects[rectq.tail]);
+#define QUEUE_ITEM(i) &rectq.rects[(i)]
+
+struct rect_queue
+{
+ struct fractal_rect rects[RECT_QUEUE_LEN];
+ unsigned head;
+ unsigned tail;
+};
+
+static struct rect_queue rectq;
+
+/*#define FRACTAL_RECT_DEBUG*/
+#if defined(FRACTAL_RECT_DEBUG) && defined(SIMULATOR)
+#include <stdio.h>
+
+static void rectq_print(void)
+{
+ unsigned i = rectq.head;
+
+ printf("Rects queue:\n");
+ for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV(i))
+ {
+ printf("\tItem %d/%d; idx %d; (%d,%d),(%d,%d),%svalid%s%s\n",
+ (i - rectq.head + 1) % RECT_QUEUE_LEN,
+ (rectq.head - rectq.tail) % RECT_QUEUE_LEN,
+ i,
+ rectq.rects[(i)].px_min,
+ rectq.rects[(i)].py_min,
+ rectq.rects[(i)].px_max,
+ rectq.rects[(i)].py_max,
+ (rectq.rects[(i)].valid ? "" : "in"),
+ ((i == rectq.head) ? ",head" : ""),
+ ((i == rectq.tail) ? ",tail" : ""));
+ }
+}
+#else
+#define rectq_print(...)
+#endif
+
+static int rects_add(int px_min, int py_min, int px_max, int py_max)
+{
+ struct fractal_rect *rect = &rectq.rects[rectq.tail];
+
+ if (rectq.head == QUEUE_PREV(rectq.tail)) /* queue is full */
+ return 1;
+
+ rect->px_min = px_min;
+ rect->py_min = py_min;
+ rect->px_max = px_max;
+ rect->py_max = py_max;
+ rect->valid = 1;
+ rectq.tail = QUEUE_PREV(rectq.tail);
+
+ return 0;
+}
+
+static void rects_queue_reset(void)
+{
+ rectq.tail = 0;
+ rectq.head = 0;
+}
+
+void rects_queue_init(void)
+{
+ rects_queue_reset();
+ rects_add(0, 0, LCD_WIDTH, LCD_HEIGHT);
+}
+
+void rects_calc_all(int (*calc)(struct fractal_rect *, int (*)(void *), void *),
+ int (*button_yield_cb)(void *), void *ctx)
+{
+ while (rectq.head != rectq.tail) /* queue is not empty */
+ {
+ struct fractal_rect *rect = &rectq.rects[rectq.head];
+
+ rectq_print();
+ if (rect->valid)
+ {
+ if (calc(rect, button_yield_cb, ctx))
+ return; /* interrupted by key-press */
+ }
+
+ rectq.head = QUEUE_PREV(rectq.head); /* dequeue */
+ }
+ rects_queue_reset();
+}
+
+int rects_move_up(void)
+{
+ unsigned i;
+
+ /* move current regions up */
+ for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
+ {
+ struct fractal_rect *rect = QUEUE_ITEM(i);
+
+ rect->py_min -= LCD_SHIFT_Y;
+ rect->py_max -= LCD_SHIFT_Y;
+
+ if (rect->py_min < 0)
+ rect->py_min = 0;
+
+ if (rect->py_max < 0)
+ rect->valid = 0;
+ }
+
+ /* add bottom region */
+ return rects_add(0, LCD_HEIGHT - LCD_SHIFT_Y, LCD_WIDTH, LCD_HEIGHT);
+}
+
+int rects_move_down(void)
+{
+ unsigned i;
+
+ /* move current regions down */
+ for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
+ {
+ struct fractal_rect *rect = QUEUE_ITEM(i);
+
+ rect->py_min += LCD_SHIFT_Y;
+ rect->py_max += LCD_SHIFT_Y;
+
+ if (rect->py_max > LCD_HEIGHT)
+ rect->py_max = LCD_HEIGHT;
+
+ if (LCD_HEIGHT <= rect->py_min)
+ rect->valid = 0;
+ }
+
+ /* add top region */
+ return rects_add(0, 0, LCD_WIDTH, LCD_SHIFT_Y);
+}
+
+int rects_move_left(void)
+{
+ unsigned i;
+
+ /* move current regions left */
+ for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
+ {
+ struct fractal_rect *rect = QUEUE_ITEM(i);
+
+ rect->px_min -= LCD_SHIFT_X;
+ rect->px_max -= LCD_SHIFT_X;
+
+ if (rect->px_min < 0)
+ rect->px_min = 0;
+
+ if (rect->px_max < 0)
+ rect->valid = 0;
+ }
+
+ /* add right region */
+ return rects_add(LCD_WIDTH - LCD_SHIFT_X, 0, LCD_WIDTH, LCD_HEIGHT);
+}
+
+int rects_move_right(void)
+{
+ unsigned i;
+
+ /* move current regions right */
+ for (i = rectq.head; i != rectq.tail; i = QUEUE_PREV((i)))
+ {
+ struct fractal_rect *rect = QUEUE_ITEM(i);
+
+ rect->px_min += LCD_SHIFT_X;
+ rect->px_max += LCD_SHIFT_X;
+
+ if (rect->px_max > LCD_WIDTH)
+ rect->px_max = LCD_WIDTH;
+
+ if (LCD_WIDTH <= rect->px_min)
+ rect->valid = 0;
+ }
+
+ /* add left region */
+ return rects_add(0, 0, LCD_SHIFT_X, LCD_HEIGHT);
+}
+
diff --git a/apps/plugins/fractals/fractal_rect.h b/apps/plugins/fractals/fractal_rect.h
new file mode 100644
index 0000000000..eca66556d3
--- /dev/null
+++ b/apps/plugins/fractals/fractal_rect.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FRACTAL_RECT_H
+#define _FRACTAL_RECT_H
+
+#include "fractal_sets.h"
+
+#define LCD_SHIFT_X (LCD_WIDTH / 8)
+#define LCD_SHIFT_Y (LCD_HEIGHT / 8)
+
+void rects_queue_init(void);
+void rects_calc_all(int (*calc)(struct fractal_rect *, int (*)(void *), void *),
+ int (*button_yield_cb)(void *), void *ctx);
+int rects_move_up(void);
+int rects_move_down(void);
+int rects_move_left(void);
+int rects_move_right(void);
+
+#endif
+
diff --git a/apps/plugins/fractals/fractal_sets.h b/apps/plugins/fractals/fractal_sets.h
new file mode 100644
index 0000000000..c5339d63d7
--- /dev/null
+++ b/apps/plugins/fractals/fractal_sets.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FRACTAL_SETS_H
+#define _FRACTAL_SETS_H
+
+#include "lib/grey.h"
+#include "lib/xlcd.h"
+
+#ifdef USEGSLIB
+extern unsigned char imgbuffer[LCD_HEIGHT];
+#else
+extern fb_data imgbuffer[LCD_HEIGHT];
+#endif
+
+struct fractal_rect
+{
+ int px_min;
+ int py_min;
+ int px_max;
+ int py_max;
+ int valid;
+};
+
+struct fractal_ops
+{
+ void (*init)(void);
+ int (*calc)(struct fractal_rect *rect, int (*button_yield_cb)(void *ctx),
+ void *button_yield_ctx);
+ void (*move)(int dx, int dy);
+ void (*zoom)(int factor);
+ int (*precision)(int d);
+};
+
+#endif
diff --git a/apps/plugins/fractals/fractals.make b/apps/plugins/fractals/fractals.make
new file mode 100644
index 0000000000..48bff5c611
--- /dev/null
+++ b/apps/plugins/fractals/fractals.make
@@ -0,0 +1,21 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+FRACTALSSRCDIR := $(APPSDIR)/plugins/fractals
+FRACTALSBUILDDIR := $(BUILDDIR)/apps/plugins/fractals
+
+ROCKS += $(FRACTALSBUILDDIR)/fractals.rock
+
+FRACTALS_SRC := $(call preprocess, $(FRACTALSSRCDIR)/SOURCES)
+FRACTALS_OBJ := $(call c2obj, $(FRACTALS_SRC))
+
+# add source files to OTHER_SRC to get automatic dependencies
+OTHER_SRC += $(FRACTALS_SRC)
+
+$(FRACTALSBUILDDIR)/fractals.rock: $(FRACTALS_OBJ)
diff --git a/apps/plugins/fractals/mandelbrot_set.c b/apps/plugins/fractals/mandelbrot_set.c
new file mode 100644
index 0000000000..ccc65b8e91
--- /dev/null
+++ b/apps/plugins/fractals/mandelbrot_set.c
@@ -0,0 +1,392 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: mandelbrot.c 24010 2009-12-15 20:51:41Z tomers $
+ *
+ * Copyright (C) 2004 Matthias Wientapper
+ * Heavily extended 2005 Jens Arnold
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "mandelbrot_set.h"
+
+#define BUTTON_YIELD_TIMEOUT (HZ / 4)
+
+/* 8 entries cyclical, last entry is black (convergence) */
+#ifdef HAVE_LCD_COLOR
+static const fb_data color[9] = {
+ LCD_RGBPACK(255, 0, 159), LCD_RGBPACK(159, 0, 255), LCD_RGBPACK(0, 0, 255),
+ LCD_RGBPACK(0, 159, 255), LCD_RGBPACK(0, 255, 128), LCD_RGBPACK(128, 255, 0),
+ LCD_RGBPACK(255, 191, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 0, 0)
+};
+#else /* greyscale */
+static const unsigned char color[9] = {
+ 255, 223, 191, 159, 128, 96, 64, 32, 0
+};
+#endif
+
+#if CONFIG_LCD == LCD_SSD1815
+/* Recorder, Ondio: pixel_height == 1.25 * pixel_width */
+#define MB_HEIGHT (LCD_HEIGHT*5/4)
+#else
+/* square pixels */
+#define MB_HEIGHT LCD_HEIGHT
+#endif
+
+#define MB_XOFS (-0x03000000L) /* -0.75 (s5.26) */
+#if 3000*MB_HEIGHT/LCD_WIDTH >= 2400 /* width is limiting factor */
+#define MB_XFAC (0x06000000LL) /* 1.5 (s5.26) */
+#define MB_YFAC (MB_XFAC*MB_HEIGHT/LCD_WIDTH)
+#else /* height is limiting factor */
+#define MB_YFAC (0x04cccccdLL) /* 1.2 (s5.26) */
+#define MB_XFAC (MB_YFAC*LCD_WIDTH/MB_HEIGHT)
+#endif
+
+#if (LCD_DEPTH < 8)
+#else
+#define UPDATE_FREQ (HZ/50)
+#endif
+
+/* Fixed point format s5.26: sign, 5 bits integer part, 26 bits fractional part */
+struct mandelbrot_ctx
+{
+ struct fractal_ops *ops;
+ long x_min;
+ long x_max;
+ long x_step;
+ long x_delta;
+ long y_min;
+ long y_max;
+ long y_step;
+ long y_delta;
+ int step_log2;
+ unsigned max_iter;
+} ctx;
+
+static void mandelbrot_init(void);
+
+static int mandelbrot_calc_low_prec(struct fractal_rect *rect,
+ int (*button_yield_cb)(void *), void *button_yield_ctx);
+
+static int mandelbrot_calc_high_prec(struct fractal_rect *rect,
+ int (*button_yield_cb)(void *), void *button_yield_ctx);
+
+static void mandelbrot_move(int dx, int dy);
+
+static void mandelbrot_zoom(int factor);
+
+static int mandelbrot_precision(int d);
+
+struct fractal_ops mandelbrot_ops =
+{
+ .init = mandelbrot_init,
+ .calc = NULL,
+ .move = mandelbrot_move,
+ .zoom = mandelbrot_zoom,
+ .precision = mandelbrot_precision,
+};
+
+static int ilog2_fp(long value) /* calculate integer log2(value_fp_6.26) */
+{
+ int i = 0;
+
+ if (value <= 0)
+ {
+ return -32767;
+ }
+ else if (value > (1L << 26))
+ {
+ while (value >= (2L << 26))
+ {
+ value >>= 1;
+ i++;
+ }
+ }
+ else
+ {
+ while (value < (1L<<26))
+ {
+ value <<= 1;
+ i--;
+ }
+ }
+ return i;
+}
+
+static void recalc_parameters(void)
+{
+ ctx.x_step = (ctx.x_max - ctx.x_min) / LCD_WIDTH;
+ ctx.x_delta = (ctx.x_step * LCD_WIDTH) / 8;
+ ctx.y_step = (ctx.y_max - ctx.y_min) / LCD_HEIGHT;
+ ctx.y_delta = (ctx.y_step * LCD_HEIGHT) / 8;
+ ctx.step_log2 = ilog2_fp(MIN(ctx.x_step, ctx.y_step));
+ ctx.max_iter = MAX(15, -15 * ctx.step_log2 - 45);
+
+ ctx.ops->calc = (ctx.step_log2 <= -10) ?
+ mandelbrot_calc_high_prec : mandelbrot_calc_low_prec;
+}
+
+static void mandelbrot_init(void)
+{
+ ctx.ops = &mandelbrot_ops;
+
+ ctx.x_min = MB_XOFS - MB_XFAC;
+ ctx.x_max = MB_XOFS + MB_XFAC;
+ ctx.y_min = -MB_YFAC;
+ ctx.y_max = MB_YFAC;
+
+ recalc_parameters();
+}
+
+static int mandelbrot_calc_low_prec(struct fractal_rect *rect,
+ int (*button_yield_cb)(void *), void *button_yield_ctx)
+{
+#ifndef USEGSLIB
+ long next_update = *rb->current_tick;
+ int last_px = rect->px_min;
+#endif
+ unsigned n_iter;
+ long a32, b32;
+ short x, x2, y, y2, a, b;
+ int p_x, p_y;
+ unsigned long last_yield = *rb->current_tick;
+ unsigned long last_button_yield = *rb->current_tick;
+
+ a32 = ctx.x_min + ctx.x_step * rect->px_min;
+
+ for (p_x = rect->px_min; p_x < rect->px_max; p_x++)
+ {
+ a = a32 >> 16;
+
+ b32 = ctx.y_min + ctx.y_step * (LCD_HEIGHT - rect->py_max);
+
+ for (p_y = rect->py_max - 1; p_y >= rect->py_min; p_y--)
+ {
+ b = b32 >> 16;
+ x = a;
+ y = b;
+ n_iter = 0;
+
+ while (++n_iter <= ctx.max_iter)
+ {
+ x2 = MULS16_ASR10(x, x);
+ y2 = MULS16_ASR10(y, y);
+
+ if (x2 + y2 > (4<<10)) break;
+
+ y = 2 * MULS16_ASR10(x, y) + b;
+ x = x2 - y2 + a;
+ }
+
+ if (n_iter > ctx.max_iter)
+ imgbuffer[p_y] = color[8];
+ else
+ imgbuffer[p_y] = color[n_iter & 7];
+
+ /* be nice to other threads:
+ * if at least one tick has passed, yield */
+ if (TIME_AFTER(*rb->current_tick, last_yield))
+ {
+ rb->yield();
+ last_yield = *rb->current_tick;
+ }
+
+ if (TIME_AFTER(*rb->current_tick, last_button_yield))
+ {
+ if (button_yield_cb(button_yield_ctx))
+ {
+#ifndef USEGSLIB
+ /* update screen part that was changed since last yield */
+ rb->lcd_update_rect(last_px, rect->py_min,
+ p_x - last_px + 1, rect->py_max - rect->py_min);
+#endif
+ rect->px_min = (p_x == 0) ? 0 : p_x - 1;
+
+ return 1;
+ }
+
+ last_button_yield = *rb->current_tick + BUTTON_YIELD_TIMEOUT;
+ }
+
+ b32 += ctx.y_step;
+ }
+#ifdef USEGSLIB
+ grey_ub_gray_bitmap_part(imgbuffer, 0, rect->py_min, 1,
+ p_x, rect->py_min, 1, rect->py_max - rect->py_min);
+#else
+ rb->lcd_bitmap_part(imgbuffer, 0, rect->py_min, 1,
+ p_x, rect->py_min, 1, rect->py_max - rect->py_min);
+
+ if ((p_x == rect->px_max - 1) ||
+ TIME_AFTER(*rb->current_tick, next_update))
+ {
+ next_update = *rb->current_tick + UPDATE_FREQ;
+
+ /* update screen part that was changed since last yield */
+ rb->lcd_update_rect(last_px, rect->py_min,
+ p_x - last_px + 1, rect->py_max - rect->py_min);
+ last_px = p_x;
+ }
+#endif
+
+ a32 += ctx.x_step;
+ }
+
+ rect->valid = 0;
+
+ return 0;
+}
+
+static int mandelbrot_calc_high_prec(struct fractal_rect *rect,
+ int (*button_yield_cb)(void *), void *button_yield_ctx)
+{
+#ifndef USEGSLIB
+ long next_update = *rb->current_tick;
+ int last_px = rect->px_min;
+#endif
+ unsigned n_iter;
+ long x, x2, y, y2, a, b;
+ int p_x, p_y;
+ unsigned long last_yield = *rb->current_tick;
+ unsigned long last_button_yield = *rb->current_tick;
+
+ MULS32_INIT();
+
+ a = ctx.x_min + ctx.x_step * rect->px_min;
+
+ for (p_x = rect->px_min; p_x < rect->px_max; p_x++)
+ {
+ b = ctx.y_min + ctx.y_step * (LCD_HEIGHT - rect->py_max);
+
+ for (p_y = rect->py_max - 1; p_y >= rect->py_min; p_y--)
+ {
+ x = a;
+ y = b;
+ n_iter = 0;
+
+ while (++n_iter <= ctx.max_iter)
+ {
+ x2 = MULS32_ASR26(x, x);
+ y2 = MULS32_ASR26(y, y);
+
+ if (x2 + y2 > (4L<<26)) break;
+
+ y = 2 * MULS32_ASR26(x, y) + b;
+ x = x2 - y2 + a;
+ }
+
+ if (n_iter > ctx.max_iter)
+ imgbuffer[p_y] = color[8];
+ else
+ imgbuffer[p_y] = color[n_iter & 7];
+
+ /* be nice to other threads:
+ * if at least one tick has passed, yield */
+ if (TIME_AFTER(*rb->current_tick, last_yield))
+ {
+ rb->yield();
+ last_yield = *rb->current_tick;
+ }
+
+ if (TIME_AFTER(*rb->current_tick, last_button_yield))
+ {
+ if (button_yield_cb(button_yield_ctx))
+ {
+#ifndef USEGSLIB
+ /* update screen part that was changed since last yield */
+ rb->lcd_update_rect(last_px, rect->py_min,
+ p_x - last_px + 1, rect->py_max - rect->py_min);
+#endif
+ rect->px_min = (p_x == 0) ? 0 : p_x - 1;
+
+ return 1;
+ }
+
+ last_button_yield = *rb->current_tick + BUTTON_YIELD_TIMEOUT;
+ }
+
+ b += ctx.y_step;
+ }
+#ifdef USEGSLIB
+ grey_ub_gray_bitmap_part(imgbuffer, 0, rect->py_min, 1,
+ p_x, rect->py_min, 1, rect->py_max - rect->py_min);
+#else
+ rb->lcd_bitmap_part(imgbuffer, 0, rect->py_min, 1,
+ p_x, rect->py_min, 1, rect->py_max - rect->py_min);
+
+ if ((p_x == rect->px_max - 1) ||
+ TIME_AFTER(*rb->current_tick, next_update))
+ {
+ next_update = *rb->current_tick + UPDATE_FREQ;
+
+ /* update screen part that was changed since last yield */
+ rb->lcd_update_rect(last_px, rect->py_min,
+ p_x - last_px + 1, rect->py_max - rect->py_min);
+ last_px = p_x;
+ }
+#endif
+ a += ctx.x_step;
+ }
+
+ rect->valid = 0;
+
+ return 0;
+}
+
+static void mandelbrot_move(int dx, int dy)
+{
+ long d_x = (long)dx * ctx.x_delta;
+ long d_y = (long)dy * ctx.y_delta;
+
+ ctx.x_min += d_x;
+ ctx.x_max += d_x;
+ ctx.y_min += d_y;
+ ctx.y_max += d_y;
+}
+
+static void mandelbrot_zoom(int factor)
+{
+ long factor_x = (long)factor * ctx.x_delta;
+ long factor_y = (long)factor * ctx.y_delta;
+
+ ctx.x_min += factor_x;
+ ctx.x_max -= factor_x;
+ ctx.y_min += factor_y;
+ ctx.y_max -= factor_y;
+
+ recalc_parameters();
+}
+
+static int mandelbrot_precision(int d)
+{
+ int changed = 0;
+
+ /* Precision increase */
+ for (; d > 0; d--)
+ {
+ ctx.max_iter += ctx.max_iter / 2;
+ changed = 1;
+ }
+
+ /* Precision decrease */
+ for (; d < 0 && ctx.max_iter >= 15; d++)
+ {
+ ctx.max_iter -= ctx.max_iter / 3;
+ changed = 1;
+ }
+
+ return changed;
+}
+
diff --git a/apps/plugins/fractals/mandelbrot_set.h b/apps/plugins/fractals/mandelbrot_set.h
new file mode 100644
index 0000000000..4eeb68461b
--- /dev/null
+++ b/apps/plugins/fractals/mandelbrot_set.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Tomer Shalev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _MANDELBROT_SET_H
+#define _MANDELBROT_SET_H
+
+#include "fractal_sets.h"
+
+/* CPU stuff */
+#if CONFIG_CPU == SH7034
+#include "cpu_sh7043.h"
+#elif defined CPU_COLDFIRE
+#include "cpu_coldfire.h"
+#elif defined CPU_ARM
+#include "cpu_arm.h"
+#endif
+
+#if CONFIG_CPU == SH7034
+#define MULS16_ASR10(a, b) muls16_asr10(a, b)
+#define MULS32_ASR26(a, b) muls32_asr26(a, b)
+#elif defined CPU_COLDFIRE
+/* Needs the EMAC initialised to fractional mode w/o rounding and saturation */
+#define MULS32_INIT() coldfire_set_macsr(EMAC_FRACTIONAL)
+#define MULS16_ASR10(a, b) muls16_asr10(a, b)
+#define MULS32_ASR26(a, b) muls32_asr26(a, b)
+#elif defined CPU_ARM
+#define MULS32_ASR26(a, b) muls32_asr26(a, b)
+#endif
+
+/* default macros */
+#ifndef MULS16_ASR10
+#define MULS16_ASR10(a, b) ((short)(((long)(a) * (long)(b)) >> 10))
+#endif
+#ifndef MULS32_ASR26
+#define MULS32_ASR26(a, b) ((long)(((long long)(a) * (long long)(b)) >> 26))
+#endif
+#ifndef MULS32_INIT
+#define MULS32_INIT()
+#endif
+
+extern struct fractal_ops mandelbrot_ops;
+
+#endif
diff --git a/manual/plugins/mandelbrot.tex b/manual/plugins/fractals.tex
index 7a1f945eb5..99a2ac0f41 100644
--- a/manual/plugins/mandelbrot.tex
+++ b/manual/plugins/fractals.tex
@@ -1,4 +1,4 @@
-\subsection{Mandelbrot}
+\subsection{Fractals}
\screenshot{plugins/images/ss-mandelbrot}{Mandelbrot}{img:mandelbrot}
This demonstration draws fractal images from the Mandelbrot set
\opt{archos,iriverh100}{using the greyscale engine}.
diff --git a/manual/plugins/main.tex b/manual/plugins/main.tex
index 62271161e9..a7dc3d7bf0 100644
--- a/manual/plugins/main.tex
+++ b/manual/plugins/main.tex
@@ -102,9 +102,9 @@ text files%
\opt{lcd_bitmap}{\input{plugins/fire.tex}}
-{\input{plugins/logo.tex}}
+\opt{lcd_bitmap}{\input{plugins/fractals.tex}}
-\opt{lcd_bitmap}{\input{plugins/mandelbrot.tex}}
+{\input{plugins/logo.tex}}
{\input{plugins/mosaic.tex}}