General housekeeping: Make plugin buffer functions take size_t * instead of int ...
[Rockbox.git] / apps / plugins / mandelbrot.c
blob2c538fb37a2dafcf724926e49ea3cdc2e2e39a06
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Matthias Wientapper
11 * Heavily extended 2005 Jens Arnold
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
23 #ifdef HAVE_LCD_BITMAP
24 #include "gray.h"
25 #include "xlcd.h"
27 PLUGIN_HEADER
29 /* variable button definitions */
30 #if CONFIG_KEYPAD == RECORDER_PAD
31 #define MANDELBROT_QUIT BUTTON_OFF
32 #define MANDELBROT_UP BUTTON_UP
33 #define MANDELBROT_DOWN BUTTON_DOWN
34 #define MANDELBROT_LEFT BUTTON_LEFT
35 #define MANDELBROT_RIGHT BUTTON_RIGHT
36 #define MANDELBROT_ZOOM_IN BUTTON_PLAY
37 #define MANDELBROT_ZOOM_OUT BUTTON_ON
38 #define MANDELBROT_MAXITER_INC BUTTON_F2
39 #define MANDELBROT_MAXITER_DEC BUTTON_F1
40 #define MANDELBROT_RESET BUTTON_F3
42 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
43 #define MANDELBROT_QUIT BUTTON_OFF
44 #define MANDELBROT_UP BUTTON_UP
45 #define MANDELBROT_DOWN BUTTON_DOWN
46 #define MANDELBROT_LEFT BUTTON_LEFT
47 #define MANDELBROT_RIGHT BUTTON_RIGHT
48 #define MANDELBROT_ZOOM_IN BUTTON_SELECT
49 #define MANDELBROT_ZOOM_OUT BUTTON_ON
50 #define MANDELBROT_MAXITER_INC BUTTON_F2
51 #define MANDELBROT_MAXITER_DEC BUTTON_F1
52 #define MANDELBROT_RESET BUTTON_F3
54 #elif CONFIG_KEYPAD == ONDIO_PAD
55 #define MANDELBROT_QUIT BUTTON_OFF
56 #define MANDELBROT_UP BUTTON_UP
57 #define MANDELBROT_DOWN BUTTON_DOWN
58 #define MANDELBROT_LEFT BUTTON_LEFT
59 #define MANDELBROT_RIGHT BUTTON_RIGHT
60 #define MANDELBROT_ZOOM_IN_PRE BUTTON_MENU
61 #define MANDELBROT_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
62 #define MANDELBROT_ZOOM_IN2 (BUTTON_MENU | BUTTON_UP)
63 #define MANDELBROT_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
64 #define MANDELBROT_MAXITER_INC (BUTTON_MENU | BUTTON_RIGHT)
65 #define MANDELBROT_MAXITER_DEC (BUTTON_MENU | BUTTON_LEFT)
66 #define MANDELBROT_RESET (BUTTON_MENU | BUTTON_OFF)
68 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
69 (CONFIG_KEYPAD == IRIVER_H300_PAD)
70 #define MANDELBROT_QUIT BUTTON_OFF
71 #define MANDELBROT_UP BUTTON_UP
72 #define MANDELBROT_DOWN BUTTON_DOWN
73 #define MANDELBROT_LEFT BUTTON_LEFT
74 #define MANDELBROT_RIGHT BUTTON_RIGHT
75 #define MANDELBROT_ZOOM_IN BUTTON_SELECT
76 #define MANDELBROT_ZOOM_OUT BUTTON_MODE
77 #define MANDELBROT_MAXITER_INC (BUTTON_ON | BUTTON_RIGHT)
78 #define MANDELBROT_MAXITER_DEC (BUTTON_ON | BUTTON_LEFT)
79 #define MANDELBROT_RESET BUTTON_REC
81 #define MANDELBROT_RC_QUIT BUTTON_RC_STOP
83 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
84 (CONFIG_KEYPAD == IPOD_3G_PAD)
85 #define MANDELBROT_QUIT (BUTTON_SELECT | BUTTON_MENU)
86 #define MANDELBROT_UP BUTTON_MENU
87 #define MANDELBROT_DOWN BUTTON_PLAY
88 #define MANDELBROT_LEFT BUTTON_LEFT
89 #define MANDELBROT_RIGHT BUTTON_RIGHT
90 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
91 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
92 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
93 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
94 #define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_PLAY)
96 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
97 #define MANDELBROT_QUIT BUTTON_POWER
98 #define MANDELBROT_UP BUTTON_UP
99 #define MANDELBROT_DOWN BUTTON_DOWN
100 #define MANDELBROT_LEFT BUTTON_LEFT
101 #define MANDELBROT_RIGHT BUTTON_RIGHT
102 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
103 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
104 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
105 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_RIGHT)
106 #define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_LEFT)
107 #define MANDELBROT_RESET BUTTON_REC
109 #elif CONFIG_KEYPAD == GIGABEAT_PAD
110 #define MANDELBROT_QUIT BUTTON_A
111 #define MANDELBROT_UP BUTTON_UP
112 #define MANDELBROT_DOWN BUTTON_DOWN
113 #define MANDELBROT_LEFT BUTTON_LEFT
114 #define MANDELBROT_RIGHT BUTTON_RIGHT
115 #define MANDELBROT_ZOOM_IN_PRE BUTTON_MENU
116 #define MANDELBROT_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
117 #define MANDELBROT_ZOOM_OUT (BUTTON_MENU | BUTTON_REPEAT)
118 #define MANDELBROT_MAXITER_INC (BUTTON_POWER | BUTTON_RIGHT)
119 #define MANDELBROT_MAXITER_DEC (BUTTON_POWER | BUTTON_LEFT)
120 #define MANDELBROT_RESET BUTTON_SELECT
122 #elif CONFIG_KEYPAD == SANSA_E200_PAD
123 #define MANDELBROT_QUIT BUTTON_POWER
124 #define MANDELBROT_UP BUTTON_UP
125 #define MANDELBROT_DOWN BUTTON_DOWN
126 #define MANDELBROT_LEFT BUTTON_LEFT
127 #define MANDELBROT_RIGHT BUTTON_RIGHT
128 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_DOWN
129 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_UP
130 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
131 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
132 #define MANDELBROT_RESET BUTTON_REC
134 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
135 #define MANDELBROT_QUIT BUTTON_POWER
136 #define MANDELBROT_UP BUTTON_SCROLL_UP
137 #define MANDELBROT_DOWN BUTTON_SCROLL_DOWN
138 #define MANDELBROT_LEFT BUTTON_LEFT
139 #define MANDELBROT_RIGHT BUTTON_RIGHT
140 #define MANDELBROT_ZOOM_IN_PRE BUTTON_PLAY
141 #define MANDELBROT_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
142 #define MANDELBROT_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
143 #define MANDELBROT_MAXITER_INC BUTTON_FF
144 #define MANDELBROT_MAXITER_DEC BUTTON_REW
145 #define MANDELBROT_RESET (BUTTON_PLAY | BUTTON_REW)
147 #endif
149 #if LCD_DEPTH < 8
150 #define USEGSLIB
151 #define MYLCD(fn) gray_ub_ ## fn
152 #define MYLCD_UPDATE()
153 #define MYXLCD(fn) gray_ub_ ## fn
154 #else
155 #define MYLCD(fn) rb->lcd_ ## fn
156 #define MYLCD_UPDATE() rb->lcd_update();
157 #define MYXLCD(fn) xlcd_ ## fn
158 #endif
160 static struct plugin_api* rb;
162 /* Fixed point format s5.26: sign, 5 bits integer part, 26 bits fractional part */
163 static long x_min;
164 static long x_max;
165 static long x_step;
166 static long x_delta;
167 static long y_min;
168 static long y_max;
169 static long y_step;
170 static long y_delta;
172 static int px_min = 0;
173 static int px_max = LCD_WIDTH;
174 static int py_min = 0;
175 static int py_max = LCD_HEIGHT;
177 static int step_log2;
178 static unsigned max_iter;
180 #ifdef USEGSLIB
181 static unsigned char *gbuf;
182 static size_t gbuf_size = 0;
183 static unsigned char imgbuffer[LCD_HEIGHT];
184 #else
185 static fb_data imgbuffer[LCD_HEIGHT];
186 #endif
188 /* 8 entries cyclical, last entry is black (convergence) */
189 #ifdef HAVE_LCD_COLOR
190 static const fb_data color[9] = {
191 LCD_RGBPACK(255, 0, 159), LCD_RGBPACK(159, 0, 255), LCD_RGBPACK(0, 0, 255),
192 LCD_RGBPACK(0, 159, 255), LCD_RGBPACK(0, 255, 128), LCD_RGBPACK(128, 255, 0),
193 LCD_RGBPACK(255, 191, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 0, 0)
195 #else /* greyscale */
196 static const fb_data color[9] = {
197 255, 223, 191, 159, 128, 96, 64, 32, 0
199 #endif
201 #if CONFIG_CPU == SH7034
203 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
204 static inline short muls16_asr10(short a, short b)
206 short r;
207 asm (
208 "muls %[a],%[b] \n"
209 "sts macl,%[r] \n"
210 "shlr8 %[r] \n"
211 "shlr2 %[r] \n"
212 : /* outputs */
213 [r]"=r"(r)
214 : /* inputs */
215 [a]"r"(a),
216 [b]"r"(b)
218 return r;
221 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
222 static inline long muls32_asr26(long a, long b)
224 long r, t1, t2, t3;
225 asm (
226 /* Signed 32bit * 32bit -> 64bit multiplication.
227 Notation: xxab * xxcd, where each letter represents 16 bits.
228 xx is the 64 bit sign extension. */
229 "swap.w %[a],%[t1] \n" /* t1 = ba */
230 "mulu %[t1],%[b] \n" /* a * d */
231 "swap.w %[b],%[t3] \n" /* t3 = dc */
232 "sts macl,%[t2] \n" /* t2 = a * d */
233 "mulu %[t1],%[t3] \n" /* a * c */
234 "sts macl,%[r] \n" /* hi = a * c */
235 "mulu %[a],%[t3] \n" /* b * c */
236 "clrt \n"
237 "sts macl,%[t3] \n" /* t3 = b * c */
238 "addc %[t2],%[t3] \n" /* t3 += t2, carry -> t2 */
239 "movt %[t2] \n"
240 "mulu %[a],%[b] \n" /* b * d */
241 "mov %[t3],%[t1] \n" /* t2t3 <<= 16 */
242 "xtrct %[t2],%[t1] \n"
243 "mov %[t1],%[t2] \n"
244 "shll16 %[t3] \n"
245 "sts macl,%[t1] \n" /* lo = b * d */
246 "clrt \n" /* hi.lo += t2t3 */
247 "addc %[t3],%[t1] \n"
248 "addc %[t2],%[r] \n"
249 "cmp/pz %[a] \n" /* ab >= 0 ? */
250 "bt 1f \n"
251 "sub %[b],%[r] \n" /* no: hi -= cd (sign extension of ab is -1) */
252 "1: \n"
253 "cmp/pz %[b] \n" /* cd >= 0 ? */
254 "bt 2f \n"
255 "sub %[a],%[r] \n" /* no: hi -= ab (sign extension of cd is -1) */
256 "2: \n"
257 /* Shift right by 26 and return low 32 bits */
258 "shll2 %[r] \n" /* hi <<= 6 */
259 "shll2 %[r] \n"
260 "shll2 %[r] \n"
261 "shlr16 %[t1] \n" /* (unsigned)lo >>= 26 */
262 "shlr8 %[t1] \n"
263 "shlr2 %[t1] \n"
264 "or %[t1],%[r] \n" /* combine result */
265 : /* outputs */
266 [r] "=&r"(r),
267 [t1]"=&r"(t1),
268 [t2]"=&r"(t2),
269 [t3]"=&r"(t3)
270 : /* inputs */
271 [a] "r" (a),
272 [b] "r" (b)
274 return r;
277 #elif defined CPU_COLDFIRE
279 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
280 static inline short muls16_asr10(short a, short b)
282 asm (
283 "muls.w %[a],%[b] \n"
284 "asr.l #8,%[b] \n"
285 "asr.l #2,%[b] \n"
286 : /* outputs */
287 [b]"+d"(b)
288 : /* inputs */
289 [a]"d" (a)
291 return b;
294 /* Needs the EMAC initialised to fractional mode w/o rounding and saturation */
295 #define MULS32_INIT() coldfire_set_macsr(EMAC_FRACTIONAL)
296 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
297 static inline long muls32_asr26(long a, long b)
299 long r, t1;
300 asm (
301 "mac.l %[a],%[b],%%acc0\n" /* multiply */
302 "mulu.l %[a],%[b] \n" /* get lower half */
303 "movclr.l %%acc0,%[r] \n" /* get higher half */
304 "asl.l #5,%[r] \n" /* hi <<= 5, plus one free */
305 "moveq.l #26,%[t1] \n"
306 "lsr.l %[t1],%[b] \n" /* (unsigned)lo >>= 26 */
307 "or.l %[b],%[r] \n" /* combine result */
308 : /* outputs */
309 [r]"=&d"(r),
310 [t1]"=&d"(t1),
311 [b] "+d" (b)
312 : /* inputs */
313 [a] "d" (a)
315 return r;
318 #elif defined CPU_ARM
320 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
321 static inline long muls32_asr26(long a, long b)
323 long r, t1;
324 asm (
325 "smull %[r], %[t1], %[a], %[b] \n"
326 "mov %[r], %[r], lsr #26 \n"
327 "orr %[r], %[r], %[t1], lsl #6 \n"
328 : /* outputs */
329 [r] "=&r"(r),
330 [t1]"=&r"(t1)
331 : /* inputs */
332 [a] "r" (a),
333 [b] "r" (b)
335 return r;
338 #endif /* CPU */
340 /* default macros */
341 #ifndef MULS16_ASR10
342 #define MULS16_ASR10(a, b) ((short)(((long)(a) * (long)(b)) >> 10))
343 #endif
344 #ifndef MULS32_ASR26
345 #define MULS32_ASR26(a, b) ((long)(((long long)(a) * (long long)(b)) >> 26))
346 #endif
347 #ifndef MULS32_INIT
348 #define MULS32_INIT()
349 #endif
351 int ilog2_fp(long value) /* calculate integer log2(value_fp_6.26) */
353 int i = 0;
355 if (value <= 0) {
356 return -32767;
357 } else if (value > (1L<<26)) {
358 while (value >= (2L<<26)) {
359 value >>= 1;
360 i++;
362 } else {
363 while (value < (1L<<26)) {
364 value <<= 1;
365 i--;
368 return i;
371 void recalc_parameters(void)
373 x_step = (x_max - x_min) / LCD_WIDTH;
374 x_delta = (x_step * LCD_WIDTH) / 8;
375 y_step = (y_max - y_min) / LCD_HEIGHT;
376 y_delta = (y_step * LCD_HEIGHT) / 8;
377 step_log2 = ilog2_fp(MIN(x_step, y_step));
378 max_iter = MAX(15, -15 * step_log2 - 45);
381 #if CONFIG_LCD == LCD_SSD1815
382 /* Recorder, Ondio: pixel_height == 1.25 * pixel_width */
383 #define MB_HEIGHT (LCD_HEIGHT*5/4)
384 #else
385 /* square pixels */
386 #define MB_HEIGHT LCD_HEIGHT
387 #endif
389 #define MB_XOFS (-0x03000000L) /* -0.75 (s5.26) */
390 #if 3000*MB_HEIGHT/LCD_WIDTH >= 2400 /* width is limiting factor */
391 #define MB_XFAC (0x06000000LL) /* 1.5 (s5.26) */
392 #define MB_YFAC (MB_XFAC*MB_HEIGHT/LCD_WIDTH)
393 #else /* height is limiting factor */
394 #define MB_YFAC (0x04cccccdLL) /* 1.2 (s5.26) */
395 #define MB_XFAC (MB_YFAC*LCD_WIDTH/MB_HEIGHT)
396 #endif
398 void init_mandelbrot_set(void)
400 x_min = MB_XOFS-MB_XFAC;
401 x_max = MB_XOFS+MB_XFAC;
402 y_min = -MB_YFAC;
403 y_max = MB_YFAC;
404 recalc_parameters();
407 void calc_mandelbrot_low_prec(void)
409 long start_tick, last_yield;
410 unsigned n_iter;
411 long a32, b32;
412 short x, x2, y, y2, a, b;
413 int p_x, p_y;
415 start_tick = last_yield = *rb->current_tick;
417 for (p_x = 0, a32 = x_min; p_x < px_max; p_x++, a32 += x_step) {
418 if (p_x < px_min)
419 continue;
420 a = a32 >> 16;
421 for (p_y = LCD_HEIGHT-1, b32 = y_min; p_y >= py_min; p_y--, b32 += y_step) {
422 if (p_y >= py_max)
423 continue;
424 b = b32 >> 16;
425 x = a;
426 y = b;
427 n_iter = 0;
429 while (++n_iter <= max_iter) {
430 x2 = MULS16_ASR10(x, x);
431 y2 = MULS16_ASR10(y, y);
433 if (x2 + y2 > (4<<10)) break;
435 y = 2 * MULS16_ASR10(x, y) + b;
436 x = x2 - y2 + a;
439 if (n_iter > max_iter)
440 imgbuffer[p_y] = color[8];
441 else
442 imgbuffer[p_y] = color[n_iter & 7];
444 /* be nice to other threads:
445 * if at least one tick has passed, yield */
446 if (*rb->current_tick > last_yield) {
447 rb->yield();
448 last_yield = *rb->current_tick;
451 #ifdef USEGSLIB
452 gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
453 p_x, py_min, 1, py_max-py_min);
454 #else
455 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
456 p_x, py_min, 1, py_max-py_min);
457 rb->lcd_update_rect(p_x, py_min, 1, py_max-py_min);
458 #endif
462 void calc_mandelbrot_high_prec(void)
464 long start_tick, last_yield;
465 unsigned n_iter;
466 long x, x2, y, y2, a, b;
467 int p_x, p_y;
469 MULS32_INIT();
470 start_tick = last_yield = *rb->current_tick;
472 for (p_x = 0, a = x_min; p_x < px_max; p_x++, a += x_step) {
473 if (p_x < px_min)
474 continue;
475 for (p_y = LCD_HEIGHT-1, b = y_min; p_y >= py_min; p_y--, b += y_step) {
476 if (p_y >= py_max)
477 continue;
478 x = a;
479 y = b;
480 n_iter = 0;
482 while (++n_iter <= max_iter) {
483 x2 = MULS32_ASR26(x, x);
484 y2 = MULS32_ASR26(y, y);
486 if (x2 + y2 > (4L<<26)) break;
488 y = 2 * MULS32_ASR26(x, y) + b;
489 x = x2 - y2 + a;
492 if (n_iter > max_iter)
493 imgbuffer[p_y] = color[8];
494 else
495 imgbuffer[p_y] = color[n_iter & 7];
497 /* be nice to other threads:
498 * if at least one tick has passed, yield */
499 if (*rb->current_tick > last_yield) {
500 rb->yield();
501 last_yield = *rb->current_tick;
504 #ifdef USEGSLIB
505 gray_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
506 p_x, py_min, 1, py_max-py_min);
507 #else
508 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
509 p_x, py_min, 1, py_max-py_min);
510 rb->lcd_update_rect(p_x, py_min, 1, py_max-py_min);
511 #endif
515 void cleanup(void *parameter)
517 (void)parameter;
518 #ifdef USEGSLIB
519 gray_release();
520 #endif
523 #define REDRAW_NONE 0
524 #define REDRAW_PARTIAL 1
525 #define REDRAW_FULL 2
527 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
529 int button;
530 int lastbutton = BUTTON_NONE;
531 int redraw = REDRAW_FULL;
532 #ifdef USEGSLIB
533 int grayscales;
534 char buff[32];
535 #endif
537 rb = api;
538 (void)parameter;
540 #ifdef USEGSLIB
541 /* get the remainder of the plugin buffer */
542 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
544 /* initialize the grayscale buffer:
545 * 8 bitplanes for 9 shades of gray.*/
546 grayscales = gray_init(rb, gbuf, gbuf_size, false, LCD_WIDTH, LCD_HEIGHT,
547 8, 0, NULL) + 1;
548 if (grayscales != 9) {
549 rb->snprintf(buff, sizeof(buff), "%d", grayscales);
550 rb->lcd_puts(0, 1, buff);
551 rb->lcd_update();
552 rb->sleep(HZ*2);
553 return(0);
556 gray_show(true); /* switch on grayscale overlay */
557 #else
558 xlcd_init(rb);
559 #endif
561 #if LCD_DEPTH > 1
562 rb->lcd_set_backdrop(NULL);
563 #endif
565 init_mandelbrot_set();
567 /* main loop */
568 while (true) {
569 if (redraw > REDRAW_NONE) {
570 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
571 rb->cpu_boost(true);
572 #endif
573 if (redraw == REDRAW_FULL) {
574 MYLCD(clear_display)();
575 MYLCD_UPDATE();
578 if (step_log2 <= -10) /* select precision */
579 calc_mandelbrot_high_prec();
580 else
581 calc_mandelbrot_low_prec();
583 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
584 rb->cpu_boost(false);
585 #endif
586 px_min = 0;
587 px_max = LCD_WIDTH;
588 py_min = 0;
589 py_max = LCD_HEIGHT;
590 redraw = REDRAW_NONE;
593 button = rb->button_get(true);
594 switch (button) {
595 #ifdef MANDELBROT_RC_QUIT
596 case MANDELBROT_RC_QUIT:
597 #endif
598 case MANDELBROT_QUIT:
599 #ifdef USEGSLIB
600 gray_release();
601 #endif
602 return PLUGIN_OK;
604 case MANDELBROT_ZOOM_OUT:
605 x_min -= x_delta;
606 x_max += x_delta;
607 y_min -= y_delta;
608 y_max += y_delta;
609 recalc_parameters();
610 redraw = REDRAW_FULL;
611 break;
614 case MANDELBROT_ZOOM_IN:
615 #ifdef MANDELBROT_ZOOM_IN_PRE
616 if (lastbutton != MANDELBROT_ZOOM_IN_PRE)
617 break;
618 #endif
619 #ifdef MANDELBROT_ZOOM_IN2
620 case MANDELBROT_ZOOM_IN2:
621 #endif
622 x_min += x_delta;
623 x_max -= x_delta;
624 y_min += y_delta;
625 y_max -= y_delta;
626 recalc_parameters();
627 redraw = REDRAW_FULL;
628 break;
630 case MANDELBROT_UP:
631 y_min += y_delta;
632 y_max += y_delta;
633 MYXLCD(scroll_down)(LCD_HEIGHT/8);
634 MYLCD_UPDATE();
635 py_max = (LCD_HEIGHT/8);
636 redraw = REDRAW_PARTIAL;
637 break;
639 case MANDELBROT_DOWN:
640 y_min -= y_delta;
641 y_max -= y_delta;
642 MYXLCD(scroll_up)(LCD_HEIGHT/8);
643 MYLCD_UPDATE();
644 py_min = (LCD_HEIGHT-LCD_HEIGHT/8);
645 redraw = REDRAW_PARTIAL;
646 break;
648 case MANDELBROT_LEFT:
649 x_min -= x_delta;
650 x_max -= x_delta;
651 MYXLCD(scroll_right)(LCD_WIDTH/8);
652 MYLCD_UPDATE();
653 px_max = (LCD_WIDTH/8);
654 redraw = REDRAW_PARTIAL;
655 break;
657 case MANDELBROT_RIGHT:
658 x_min += x_delta;
659 x_max += x_delta;
660 MYXLCD(scroll_left)(LCD_WIDTH/8);
661 MYLCD_UPDATE();
662 px_min = (LCD_WIDTH-LCD_WIDTH/8);
663 redraw = REDRAW_PARTIAL;
664 break;
666 case MANDELBROT_MAXITER_DEC:
667 if (max_iter >= 15) {
668 max_iter -= max_iter / 3;
669 redraw = REDRAW_FULL;
671 break;
673 case MANDELBROT_MAXITER_INC:
674 max_iter += max_iter / 2;
675 redraw = REDRAW_FULL;
676 break;
678 case MANDELBROT_RESET:
679 init_mandelbrot_set();
680 redraw = REDRAW_FULL;
681 break;
683 default:
684 if (rb->default_event_handler_ex(button, cleanup, NULL)
685 == SYS_USB_CONNECTED)
686 return PLUGIN_USB_CONNECTED;
687 break;
689 if (button != BUTTON_NONE)
690 lastbutton = button;
692 #ifdef USEGSLIB
693 gray_release();
694 #endif
695 return PLUGIN_OK;
697 #endif