summaryrefslogtreecommitdiff
path: root/apps/plugins/mandelbrot.c
diff options
context:
space:
mode:
authorJörg Hohensohn <hohensoh@rockbox.org>2004-04-14 23:48:26 +0000
committerJörg Hohensohn <hohensoh@rockbox.org>2004-04-14 23:48:26 +0000
commit4d3aa154c647d8da78bf904756d1632c973bdbd6 (patch)
tree7d9747c9c34ddfaf661da3a05f328dea052e5135 /apps/plugins/mandelbrot.c
parent354e31828b57c2659dac365369beca7963bf97a2 (diff)
a Mandelbrot set plugin from Matthias
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4504 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mandelbrot.c')
-rw-r--r--apps/plugins/mandelbrot.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/apps/plugins/mandelbrot.c b/apps/plugins/mandelbrot.c
new file mode 100644
index 0000000000..3585af80f9
--- /dev/null
+++ b/apps/plugins/mandelbrot.c
@@ -0,0 +1,195 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2004 Matthias Wientapper
+ *
+ * Thanks to Jens Arnold and Joerg Hohensohn for the speed tips.
+ * Boy, that was a hell of a code review ;-)
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ *
+ * further optimization ideas:
+ * - incremental recalculation when moving
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+#ifdef HAVE_LCD_BITMAP // this is not fun on the player
+
+static struct plugin_api* rb;
+static char buff[32];
+static int lcd_aspect_ratio;
+static int x_min;
+static int x_max;
+static int y_min;
+static int y_max;
+static int delta;
+static int max_iter;
+
+void init_mandelbrot_set(void){
+ x_min = -5<<27; // -2.5<<28
+ x_max = 1<<28; // 1.0<<28
+ y_min = -1<<28; // -1.0<<28
+ y_max = 1<<28; // 1.0<<28
+ delta = (x_max - x_min) >> 3; // /8
+ max_iter = 25;
+}
+
+void calc_mandelbrot_set(void){
+
+ unsigned int start_tick;
+ int n_iter;
+ int x_pixel, y_pixel;
+ int x, x2, y, y2, a, b;
+ int x_fact, y_fact;
+
+ start_tick = *rb->current_tick;
+
+ rb->lcd_clear_display();
+ rb->lcd_update();
+
+ x_fact = (x_max - x_min) / LCD_WIDTH;
+ y_fact = (y_max - y_min) / LCD_HEIGHT;
+
+ for(y_pixel = LCD_HEIGHT-1; y_pixel>=0; y_pixel--){
+ b = (y_pixel * y_fact) + y_min;
+ for (x_pixel = LCD_WIDTH-1; x_pixel>=0; x_pixel--){
+ a = (x_pixel * x_fact) + x_min;
+ x = 0;
+ y = 0;
+ n_iter = 0;
+
+ while (++n_iter<=max_iter) {
+ x >>= 14;
+ y >>= 14;
+ x2 = x * x;
+ y2 = y * y;
+
+ if (x2 + y2 > (4<<28)) break;
+
+ y = 2 * x * y + b;
+ x = x2 - y2 + a;
+ }
+
+ // "coloring"
+ if ( (n_iter > max_iter) ||
+ (n_iter == (max_iter >> 1)) ||
+ (n_iter == (max_iter >> 2)) ||
+ (n_iter == (max_iter >> 3))
+ ){
+ rb->lcd_drawpixel(x_pixel,y_pixel);
+ }
+ }
+
+ /* update block of 8 lines */
+ if ((y_pixel & 0x7) == 0)
+ rb->lcd_update_rect(0, y_pixel, LCD_WIDTH, 8);
+ }
+
+ /* we want to know how long we had to wait */
+ rb->lcd_setfont(FONT_SYSFIXED);
+ rb->snprintf(buff, sizeof(buff), "%d", (*rb->current_tick - start_tick));
+ rb->lcd_puts(0,0,buff);
+ rb->snprintf(buff, sizeof(buff), "%d", max_iter);
+ rb->lcd_puts(0,1,buff);
+ rb->lcd_update_rect(0,0,24,16);
+}
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+
+ TEST_PLUGIN_API(api);
+ (void)parameter;
+ rb = api;
+
+ init_mandelbrot_set();
+ lcd_aspect_ratio = ((LCD_WIDTH<<14) / LCD_HEIGHT)<<14;
+
+ /* main loop */
+ while (true){
+
+ calc_mandelbrot_set();
+
+ /* FIXME: is this the right way to empty the key-queue?
+ (Otherwise we have to process things twice :-/ ?! */
+
+ rb->button_get(true);
+
+
+ switch (rb->button_get(true)) {
+ case BUTTON_OFF:
+ return PLUGIN_OK;
+
+ case BUTTON_ON:
+ x_min -= ((delta>>14)*(lcd_aspect_ratio>>14));
+ x_max += ((delta>>14)*(lcd_aspect_ratio>>14));
+ y_min -= delta;
+ y_max += delta;
+ delta = (x_max - x_min) >> 3;
+ break;
+
+
+ case BUTTON_PLAY:
+ x_min += ((delta>>14)*(lcd_aspect_ratio>>14));
+ x_max -= ((delta>>14)*(lcd_aspect_ratio>>14));
+ y_min += delta;
+ y_max -= delta;
+ delta = (x_max - x_min) >> 3;
+ break;
+
+ case BUTTON_UP:
+ y_min -= delta;
+ y_max -= delta;
+ break;
+
+ case BUTTON_DOWN:
+ y_min += delta;
+ y_max += delta;
+ break;
+
+ case BUTTON_LEFT:
+ x_min -= delta;
+ x_max -= delta;
+ break;
+
+ case BUTTON_RIGHT:
+ x_min += delta;
+ x_max += delta;
+ break;
+
+ case BUTTON_F1:
+ if (max_iter>5){
+ max_iter -= 5;
+ }
+ break;
+
+ case BUTTON_F2:
+ if (max_iter < 195){
+ max_iter += 5;
+ }
+ break;
+
+ case BUTTON_F3:
+ init_mandelbrot_set();
+ break;
+
+
+ case SYS_USB_CONNECTED:
+ rb->usb_screen();
+ return PLUGIN_USB_CONNECTED;
+ }
+ }
+ return false;
+}
+#endif