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
This commit is contained in:
Tomer Shalev 2010-01-15 05:53:15 +00:00
parent 51630cbac1
commit 7719d297f2
20 changed files with 1676 additions and 5 deletions

View file

@ -41,7 +41,7 @@ keybox,apps
lamp,apps
logo,demos
lua,viewers
mandelbrot,demos
fractals,demos
matrix,demos
maze,games
mazezam,games

View file

@ -77,7 +77,6 @@ codebuster.c
/* Plugins needing the grayscale lib on low-depth LCDs */
fire.c
mandelbrot.c
plasma.c
blackjack.c

View file

@ -20,6 +20,7 @@ rockboy
pictureflow
#endif
chessbox
fractals
jpeg
sudoku
reversi

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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;
}

View file

@ -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

View file

@ -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}.

View file

@ -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}}