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 + +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 similarity index 99% rename from manual/plugins/mandelbrot.tex rename to 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}}