Adapt the remaining plugins to put the greyscale isr on cop. Now they can be used...
[Rockbox.git] / apps / plugins / mandelbrot.c
blob244d94b157b4538d4321f4db23cbbe5942ae19d2
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 "grey.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 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
86 #define MANDELBROT_QUIT (BUTTON_SELECT | BUTTON_MENU)
87 #define MANDELBROT_UP BUTTON_MENU
88 #define MANDELBROT_DOWN BUTTON_PLAY
89 #define MANDELBROT_LEFT BUTTON_LEFT
90 #define MANDELBROT_RIGHT BUTTON_RIGHT
91 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
92 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
93 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
94 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
95 #define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_PLAY)
97 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
98 #define MANDELBROT_QUIT BUTTON_POWER
99 #define MANDELBROT_UP BUTTON_UP
100 #define MANDELBROT_DOWN BUTTON_DOWN
101 #define MANDELBROT_LEFT BUTTON_LEFT
102 #define MANDELBROT_RIGHT BUTTON_RIGHT
103 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
104 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
105 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
106 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
107 #define MANDELBROT_MAXITER_INC_PRE BUTTON_PLAY
108 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_REL)
109 #define MANDELBROT_MAXITER_DEC_PRE BUTTON_PLAY
110 #define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_REPEAT)
111 #define MANDELBROT_RESET BUTTON_REC
113 #elif CONFIG_KEYPAD == GIGABEAT_PAD
114 #define MANDELBROT_QUIT BUTTON_POWER
115 #define MANDELBROT_UP BUTTON_UP
116 #define MANDELBROT_DOWN BUTTON_DOWN
117 #define MANDELBROT_LEFT BUTTON_LEFT
118 #define MANDELBROT_RIGHT BUTTON_RIGHT
119 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
120 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
121 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
122 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
123 #define MANDELBROT_MAXITER_INC BUTTON_VOL_UP
124 #define MANDELBROT_MAXITER_DEC BUTTON_VOL_DOWN
125 #define MANDELBROT_RESET BUTTON_A
127 #elif CONFIG_KEYPAD == SANSA_E200_PAD
128 #define MANDELBROT_QUIT BUTTON_POWER
129 #define MANDELBROT_UP BUTTON_UP
130 #define MANDELBROT_DOWN BUTTON_DOWN
131 #define MANDELBROT_LEFT BUTTON_LEFT
132 #define MANDELBROT_RIGHT BUTTON_RIGHT
133 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
134 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
135 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
136 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
137 #define MANDELBROT_RESET BUTTON_REC
139 #elif CONFIG_KEYPAD == SANSA_C200_PAD
140 #define MANDELBROT_QUIT BUTTON_POWER
141 #define MANDELBROT_UP BUTTON_UP
142 #define MANDELBROT_DOWN BUTTON_DOWN
143 #define MANDELBROT_LEFT BUTTON_LEFT
144 #define MANDELBROT_RIGHT BUTTON_RIGHT
145 #define MANDELBROT_ZOOM_IN BUTTON_VOL_UP
146 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
147 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
148 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
149 #define MANDELBROT_RESET BUTTON_REC
151 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
152 #define MANDELBROT_QUIT BUTTON_POWER
153 #define MANDELBROT_UP BUTTON_SCROLL_UP
154 #define MANDELBROT_DOWN BUTTON_SCROLL_DOWN
155 #define MANDELBROT_LEFT BUTTON_LEFT
156 #define MANDELBROT_RIGHT BUTTON_RIGHT
157 #define MANDELBROT_ZOOM_IN_PRE BUTTON_PLAY
158 #define MANDELBROT_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
159 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_PLAY
160 #define MANDELBROT_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
161 #define MANDELBROT_MAXITER_INC BUTTON_FF
162 #define MANDELBROT_MAXITER_DEC BUTTON_REW
163 #define MANDELBROT_RESET (BUTTON_PLAY | BUTTON_REW)
165 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
166 #define MANDELBROT_QUIT BUTTON_EQ
167 #define MANDELBROT_UP BUTTON_UP
168 #define MANDELBROT_DOWN BUTTON_DOWN
169 #define MANDELBROT_LEFT BUTTON_LEFT
170 #define MANDELBROT_RIGHT BUTTON_RIGHT
171 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
172 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
173 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
174 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
175 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_RIGHT)
176 #define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_LEFT)
177 #define MANDELBROT_RESET BUTTON_MODE
179 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
180 #define MANDELBROT_QUIT BUTTON_BACK
181 #define MANDELBROT_UP BUTTON_UP
182 #define MANDELBROT_DOWN BUTTON_DOWN
183 #define MANDELBROT_LEFT BUTTON_LEFT
184 #define MANDELBROT_RIGHT BUTTON_RIGHT
185 #define MANDELBROT_ZOOM_IN BUTTON_VOL_UP
186 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
187 #define MANDELBROT_MAXITER_INC BUTTON_PREV
188 #define MANDELBROT_MAXITER_DEC BUTTON_NEXT
189 #define MANDELBROT_RESET BUTTON_MENU
191 #elif CONFIG_KEYPAD == MROBE100_PAD
192 #define MANDELBROT_QUIT BUTTON_POWER
193 #define MANDELBROT_UP BUTTON_UP
194 #define MANDELBROT_DOWN BUTTON_DOWN
195 #define MANDELBROT_LEFT BUTTON_LEFT
196 #define MANDELBROT_RIGHT BUTTON_RIGHT
197 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
198 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
199 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
200 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
201 #define MANDELBROT_MAXITER_INC BUTTON_MENU
202 #define MANDELBROT_MAXITER_DEC BUTTON_PLAY
203 #define MANDELBROT_RESET BUTTON_DISPLAY
205 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
206 #define MANDELBROT_QUIT BUTTON_RC_REC
207 #define MANDELBROT_UP BUTTON_RC_VOL_UP
208 #define MANDELBROT_DOWN BUTTON_RC_VOL_DOWN
209 #define MANDELBROT_LEFT BUTTON_RC_REW
210 #define MANDELBROT_RIGHT BUTTON_RC_FF
211 #define MANDELBROT_ZOOM_IN_PRE BUTTON_RC_PLAY
212 #define MANDELBROT_ZOOM_IN (BUTTON_RC_PLAY | BUTTON_REL)
213 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_RC_PLAY
214 #define MANDELBROT_ZOOM_OUT (BUTTON_RC_PLAY | BUTTON_REPEAT)
215 #define MANDELBROT_MAXITER_INC_PRE BUTTON_RC_MODE
216 #define MANDELBROT_MAXITER_INC (BUTTON_RC_MODE|BUTTON_REL)
217 #define MANDELBROT_MAXITER_DEC_PRE BUTTON_RC_MODE
218 #define MANDELBROT_MAXITER_DEC (BUTTON_RC_MODE|BUTTON_REPEAT)
219 #define MANDELBROT_RESET BUTTON_RC_MENU
221 #elif CONFIG_KEYPAD == COWOND2_PAD
222 #define MANDELBROT_QUIT BUTTON_POWER
223 #define MANDELBROT_UP BUTTON_UP
224 #define MANDELBROT_DOWN BUTTON_DOWN
225 #define MANDELBROT_LEFT BUTTON_LEFT
226 #define MANDELBROT_RIGHT BUTTON_RIGHT
227 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
228 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_PLUS)
229 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
230 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_MINUS)
231 #define MANDELBROT_MAXITER_INC BUTTON_PLUS
232 #define MANDELBROT_MAXITER_DEC BUTTON_MINUS
233 #define MANDELBROT_RESET BUTTON_MENU
235 #else
236 #error No keymap defined!
237 #endif
239 #if LCD_DEPTH < 8
240 #define USEGSLIB
241 #define MYLCD(fn) grey_ub_ ## fn
242 #define MYLCD_UPDATE()
243 #define MYXLCD(fn) grey_ub_ ## fn
244 #else
245 #define UPDATE_FREQ (HZ/50)
246 #define MYLCD(fn) rb->lcd_ ## fn
247 #define MYLCD_UPDATE() rb->lcd_update();
248 #define MYXLCD(fn) xlcd_ ## fn
249 #endif
251 static struct plugin_api* rb;
253 /* Fixed point format s5.26: sign, 5 bits integer part, 26 bits fractional part */
254 static long x_min;
255 static long x_max;
256 static long x_step;
257 static long x_delta;
258 static long y_min;
259 static long y_max;
260 static long y_step;
261 static long y_delta;
263 static int px_min = 0;
264 static int px_max = LCD_WIDTH;
265 static int py_min = 0;
266 static int py_max = LCD_HEIGHT;
268 static int step_log2;
269 static unsigned max_iter;
271 #ifdef USEGSLIB
272 GREY_INFO_STRUCT
273 static unsigned char *gbuf;
274 static size_t gbuf_size = 0;
275 static unsigned char imgbuffer[LCD_HEIGHT];
276 #else
277 static fb_data imgbuffer[LCD_HEIGHT];
278 #endif
280 /* 8 entries cyclical, last entry is black (convergence) */
281 #ifdef HAVE_LCD_COLOR
282 static const fb_data color[9] = {
283 LCD_RGBPACK(255, 0, 159), LCD_RGBPACK(159, 0, 255), LCD_RGBPACK(0, 0, 255),
284 LCD_RGBPACK(0, 159, 255), LCD_RGBPACK(0, 255, 128), LCD_RGBPACK(128, 255, 0),
285 LCD_RGBPACK(255, 191, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 0, 0)
287 #else /* greyscale */
288 static const fb_data color[9] = {
289 255, 223, 191, 159, 128, 96, 64, 32, 0
291 #endif
293 #if CONFIG_CPU == SH7034
295 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
296 static inline short muls16_asr10(short a, short b)
298 short r;
299 asm (
300 "muls %[a],%[b] \n"
301 "sts macl,%[r] \n"
302 "shlr8 %[r] \n"
303 "shlr2 %[r] \n"
304 : /* outputs */
305 [r]"=r"(r)
306 : /* inputs */
307 [a]"r"(a),
308 [b]"r"(b)
310 return r;
313 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
314 static inline long muls32_asr26(long a, long b)
316 long r, t1, t2, t3;
317 asm (
318 /* Signed 32bit * 32bit -> 64bit multiplication.
319 Notation: xxab * xxcd, where each letter represents 16 bits.
320 xx is the 64 bit sign extension. */
321 "swap.w %[a],%[t1] \n" /* t1 = ba */
322 "mulu %[t1],%[b] \n" /* a * d */
323 "swap.w %[b],%[t3] \n" /* t3 = dc */
324 "sts macl,%[t2] \n" /* t2 = a * d */
325 "mulu %[t1],%[t3] \n" /* a * c */
326 "sts macl,%[r] \n" /* hi = a * c */
327 "mulu %[a],%[t3] \n" /* b * c */
328 "clrt \n"
329 "sts macl,%[t3] \n" /* t3 = b * c */
330 "addc %[t2],%[t3] \n" /* t3 += t2, carry -> t2 */
331 "movt %[t2] \n"
332 "mulu %[a],%[b] \n" /* b * d */
333 "mov %[t3],%[t1] \n" /* t2t3 <<= 16 */
334 "xtrct %[t2],%[t1] \n"
335 "mov %[t1],%[t2] \n"
336 "shll16 %[t3] \n"
337 "sts macl,%[t1] \n" /* lo = b * d */
338 "clrt \n" /* hi.lo += t2t3 */
339 "addc %[t3],%[t1] \n"
340 "addc %[t2],%[r] \n"
341 "cmp/pz %[a] \n" /* ab >= 0 ? */
342 "bt 1f \n"
343 "sub %[b],%[r] \n" /* no: hi -= cd (sign extension of ab is -1) */
344 "1: \n"
345 "cmp/pz %[b] \n" /* cd >= 0 ? */
346 "bt 2f \n"
347 "sub %[a],%[r] \n" /* no: hi -= ab (sign extension of cd is -1) */
348 "2: \n"
349 /* Shift right by 26 and return low 32 bits */
350 "shll2 %[r] \n" /* hi <<= 6 */
351 "shll2 %[r] \n"
352 "shll2 %[r] \n"
353 "shlr16 %[t1] \n" /* (unsigned)lo >>= 26 */
354 "shlr8 %[t1] \n"
355 "shlr2 %[t1] \n"
356 "or %[t1],%[r] \n" /* combine result */
357 : /* outputs */
358 [r] "=&r"(r),
359 [t1]"=&r"(t1),
360 [t2]"=&r"(t2),
361 [t3]"=&r"(t3)
362 : /* inputs */
363 [a] "r" (a),
364 [b] "r" (b)
366 return r;
369 #elif defined CPU_COLDFIRE
371 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
372 static inline short muls16_asr10(short a, short b)
374 asm (
375 "muls.w %[a],%[b] \n"
376 "asr.l #8,%[b] \n"
377 "asr.l #2,%[b] \n"
378 : /* outputs */
379 [b]"+d"(b)
380 : /* inputs */
381 [a]"d" (a)
383 return b;
386 /* Needs the EMAC initialised to fractional mode w/o rounding and saturation */
387 #define MULS32_INIT() coldfire_set_macsr(EMAC_FRACTIONAL)
388 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
389 static inline long muls32_asr26(long a, long b)
391 long r, t1;
392 asm (
393 "mac.l %[a], %[b], %%acc0 \n" /* multiply */
394 "move.l %%accext01, %[t1] \n" /* get low part */
395 "movclr.l %%acc0, %[r] \n" /* get high part */
396 "asl.l #5, %[r] \n" /* hi <<= 5, plus one free */
397 "lsr.l #3, %[t1] \n" /* lo >>= 3 */
398 "and.l #0x1f, %[t1] \n" /* mask out unrelated bits */
399 "or.l %[t1], %[r] \n" /* combine result */
400 : /* outputs */
401 [r] "=d"(r),
402 [t1]"=d"(t1)
403 : /* inputs */
404 [a] "d" (a),
405 [b] "d" (b)
407 return r;
410 #elif defined CPU_ARM
412 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
413 static inline long muls32_asr26(long a, long b)
415 long r, t1;
416 asm (
417 "smull %[r], %[t1], %[a], %[b] \n"
418 "mov %[r], %[r], lsr #26 \n"
419 "orr %[r], %[r], %[t1], lsl #6 \n"
420 : /* outputs */
421 [r] "=&r"(r),
422 [t1]"=&r"(t1)
423 : /* inputs */
424 [a] "r" (a),
425 [b] "r" (b)
427 return r;
430 #endif /* CPU */
432 /* default macros */
433 #ifndef MULS16_ASR10
434 #define MULS16_ASR10(a, b) ((short)(((long)(a) * (long)(b)) >> 10))
435 #endif
436 #ifndef MULS32_ASR26
437 #define MULS32_ASR26(a, b) ((long)(((long long)(a) * (long long)(b)) >> 26))
438 #endif
439 #ifndef MULS32_INIT
440 #define MULS32_INIT()
441 #endif
443 int ilog2_fp(long value) /* calculate integer log2(value_fp_6.26) */
445 int i = 0;
447 if (value <= 0) {
448 return -32767;
449 } else if (value > (1L<<26)) {
450 while (value >= (2L<<26)) {
451 value >>= 1;
452 i++;
454 } else {
455 while (value < (1L<<26)) {
456 value <<= 1;
457 i--;
460 return i;
463 void recalc_parameters(void)
465 x_step = (x_max - x_min) / LCD_WIDTH;
466 x_delta = (x_step * LCD_WIDTH) / 8;
467 y_step = (y_max - y_min) / LCD_HEIGHT;
468 y_delta = (y_step * LCD_HEIGHT) / 8;
469 step_log2 = ilog2_fp(MIN(x_step, y_step));
470 max_iter = MAX(15, -15 * step_log2 - 45);
473 #if CONFIG_LCD == LCD_SSD1815
474 /* Recorder, Ondio: pixel_height == 1.25 * pixel_width */
475 #define MB_HEIGHT (LCD_HEIGHT*5/4)
476 #else
477 /* square pixels */
478 #define MB_HEIGHT LCD_HEIGHT
479 #endif
481 #define MB_XOFS (-0x03000000L) /* -0.75 (s5.26) */
482 #if 3000*MB_HEIGHT/LCD_WIDTH >= 2400 /* width is limiting factor */
483 #define MB_XFAC (0x06000000LL) /* 1.5 (s5.26) */
484 #define MB_YFAC (MB_XFAC*MB_HEIGHT/LCD_WIDTH)
485 #else /* height is limiting factor */
486 #define MB_YFAC (0x04cccccdLL) /* 1.2 (s5.26) */
487 #define MB_XFAC (MB_YFAC*LCD_WIDTH/MB_HEIGHT)
488 #endif
490 void init_mandelbrot_set(void)
492 x_min = MB_XOFS-MB_XFAC;
493 x_max = MB_XOFS+MB_XFAC;
494 y_min = -MB_YFAC;
495 y_max = MB_YFAC;
496 recalc_parameters();
499 void calc_mandelbrot_low_prec(void)
501 long start_tick, last_yield;
502 #ifndef USEGSLIB
503 long next_update = *rb->current_tick;
504 int last_px = px_min;
505 #endif
506 unsigned n_iter;
507 long a32, b32;
508 short x, x2, y, y2, a, b;
509 int p_x, p_y;
511 start_tick = last_yield = *rb->current_tick;
513 for (p_x = 0, a32 = x_min; p_x < px_max; p_x++, a32 += x_step) {
514 if (p_x < px_min)
515 continue;
516 a = a32 >> 16;
517 for (p_y = LCD_HEIGHT-1, b32 = y_min; p_y >= py_min; p_y--, b32 += y_step) {
518 if (p_y >= py_max)
519 continue;
520 b = b32 >> 16;
521 x = a;
522 y = b;
523 n_iter = 0;
525 while (++n_iter <= max_iter) {
526 x2 = MULS16_ASR10(x, x);
527 y2 = MULS16_ASR10(y, y);
529 if (x2 + y2 > (4<<10)) break;
531 y = 2 * MULS16_ASR10(x, y) + b;
532 x = x2 - y2 + a;
535 if (n_iter > max_iter)
536 imgbuffer[p_y] = color[8];
537 else
538 imgbuffer[p_y] = color[n_iter & 7];
540 /* be nice to other threads:
541 * if at least one tick has passed, yield */
542 if (*rb->current_tick > last_yield) {
543 rb->yield();
544 last_yield = *rb->current_tick;
547 #ifdef USEGSLIB
548 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
549 p_x, py_min, 1, py_max - py_min);
550 #else
551 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
552 p_x, py_min, 1, py_max - py_min);
553 if ((p_x == px_max - 1) || TIME_AFTER(*rb->current_tick, next_update))
555 next_update = *rb->current_tick + UPDATE_FREQ;
556 rb->lcd_update_rect(last_px, py_min, p_x - last_px + 1,
557 py_max - py_min);
558 last_px = p_x;
560 #endif
564 void calc_mandelbrot_high_prec(void)
566 long start_tick, last_yield;
567 #ifndef USEGSLIB
568 long next_update = *rb->current_tick;
569 int last_px = px_min;
570 #endif
571 unsigned n_iter;
572 long x, x2, y, y2, a, b;
573 int p_x, p_y;
575 MULS32_INIT();
576 start_tick = last_yield = *rb->current_tick;
578 for (p_x = 0, a = x_min; p_x < px_max; p_x++, a += x_step) {
579 if (p_x < px_min)
580 continue;
581 for (p_y = LCD_HEIGHT-1, b = y_min; p_y >= py_min; p_y--, b += y_step) {
582 if (p_y >= py_max)
583 continue;
584 x = a;
585 y = b;
586 n_iter = 0;
588 while (++n_iter <= max_iter) {
589 x2 = MULS32_ASR26(x, x);
590 y2 = MULS32_ASR26(y, y);
592 if (x2 + y2 > (4L<<26)) break;
594 y = 2 * MULS32_ASR26(x, y) + b;
595 x = x2 - y2 + a;
598 if (n_iter > max_iter)
599 imgbuffer[p_y] = color[8];
600 else
601 imgbuffer[p_y] = color[n_iter & 7];
603 /* be nice to other threads:
604 * if at least one tick has passed, yield */
605 if (*rb->current_tick > last_yield) {
606 rb->yield();
607 last_yield = *rb->current_tick;
610 #ifdef USEGSLIB
611 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
612 p_x, py_min, 1, py_max - py_min);
613 #else
614 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
615 p_x, py_min, 1, py_max-py_min);
616 if ((p_x == px_max - 1) || TIME_AFTER(*rb->current_tick, next_update))
618 next_update = *rb->current_tick + UPDATE_FREQ;
619 rb->lcd_update_rect(last_px, py_min, p_x - last_px + 1,
620 py_max - py_min);
621 last_px = p_x;
623 #endif
627 void cleanup(void *parameter)
629 (void)parameter;
630 #ifdef USEGSLIB
631 grey_release();
632 #endif
635 #define REDRAW_NONE 0
636 #define REDRAW_PARTIAL 1
637 #define REDRAW_FULL 2
639 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
641 int button;
642 int lastbutton = BUTTON_NONE;
643 int redraw = REDRAW_FULL;
645 rb = api;
646 (void)parameter;
648 #ifdef USEGSLIB
649 /* get the remainder of the plugin buffer */
650 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
652 /* initialize the greyscale buffer.*/
653 if (!grey_init(rb, gbuf, gbuf_size, GREY_ON_COP,
654 LCD_WIDTH, LCD_HEIGHT, NULL))
656 rb->splash(HZ, "Couldn't init greyscale display");
657 return 0;
659 grey_show(true); /* switch on greyscale overlay */
660 #else
661 xlcd_init(rb);
662 #endif
664 #if LCD_DEPTH > 1
665 rb->lcd_set_backdrop(NULL);
666 #endif
668 init_mandelbrot_set();
670 /* main loop */
671 while (true) {
672 if (redraw > REDRAW_NONE) {
673 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
674 rb->cpu_boost(true);
675 #endif
676 if (redraw == REDRAW_FULL) {
677 MYLCD(clear_display)();
678 MYLCD_UPDATE();
681 if (step_log2 <= -10) /* select precision */
682 calc_mandelbrot_high_prec();
683 else
684 calc_mandelbrot_low_prec();
686 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
687 rb->cpu_boost(false);
688 #endif
689 px_min = 0;
690 px_max = LCD_WIDTH;
691 py_min = 0;
692 py_max = LCD_HEIGHT;
693 redraw = REDRAW_NONE;
696 button = rb->button_get(true);
697 switch (button) {
698 #ifdef MANDELBROT_RC_QUIT
699 case MANDELBROT_RC_QUIT:
700 #endif
701 case MANDELBROT_QUIT:
702 #ifdef USEGSLIB
703 grey_release();
704 #endif
705 return PLUGIN_OK;
707 case MANDELBROT_ZOOM_OUT:
708 #ifdef MANDELBROT_ZOOM_OUT_PRE
709 if (lastbutton != MANDELBROT_ZOOM_OUT_PRE)
710 break;
711 #endif
712 x_min -= x_delta;
713 x_max += x_delta;
714 y_min -= y_delta;
715 y_max += y_delta;
716 recalc_parameters();
717 redraw = REDRAW_FULL;
718 break;
721 case MANDELBROT_ZOOM_IN:
722 #ifdef MANDELBROT_ZOOM_IN_PRE
723 if (lastbutton != MANDELBROT_ZOOM_IN_PRE)
724 break;
725 #endif
726 #ifdef MANDELBROT_ZOOM_IN2
727 case MANDELBROT_ZOOM_IN2:
728 #endif
729 x_min += x_delta;
730 x_max -= x_delta;
731 y_min += y_delta;
732 y_max -= y_delta;
733 recalc_parameters();
734 redraw = REDRAW_FULL;
735 break;
737 case MANDELBROT_UP:
738 y_min += y_delta;
739 y_max += y_delta;
740 MYXLCD(scroll_down)(LCD_HEIGHT/8);
741 MYLCD_UPDATE();
742 py_max = (LCD_HEIGHT/8);
743 redraw = REDRAW_PARTIAL;
744 break;
746 case MANDELBROT_DOWN:
747 y_min -= y_delta;
748 y_max -= y_delta;
749 MYXLCD(scroll_up)(LCD_HEIGHT/8);
750 MYLCD_UPDATE();
751 py_min = (LCD_HEIGHT-LCD_HEIGHT/8);
752 redraw = REDRAW_PARTIAL;
753 break;
755 case MANDELBROT_LEFT:
756 x_min -= x_delta;
757 x_max -= x_delta;
758 MYXLCD(scroll_right)(LCD_WIDTH/8);
759 MYLCD_UPDATE();
760 px_max = (LCD_WIDTH/8);
761 redraw = REDRAW_PARTIAL;
762 break;
764 case MANDELBROT_RIGHT:
765 x_min += x_delta;
766 x_max += x_delta;
767 MYXLCD(scroll_left)(LCD_WIDTH/8);
768 MYLCD_UPDATE();
769 px_min = (LCD_WIDTH-LCD_WIDTH/8);
770 redraw = REDRAW_PARTIAL;
771 break;
773 case MANDELBROT_MAXITER_DEC:
774 #ifdef MANDELBROT_MAXITER_DEC_PRE
775 if (lastbutton != MANDELBROT_MAXITER_DEC_PRE)
776 break;
777 #endif
778 if (max_iter >= 15) {
779 max_iter -= max_iter / 3;
780 redraw = REDRAW_FULL;
782 break;
784 case MANDELBROT_MAXITER_INC:
785 #ifdef MANDELBROT_MAXITER_INC_PRE
786 if (lastbutton != MANDELBROT_MAXITER_INC_PRE)
787 break;
788 #endif
789 max_iter += max_iter / 2;
790 redraw = REDRAW_FULL;
791 break;
793 case MANDELBROT_RESET:
794 init_mandelbrot_set();
795 redraw = REDRAW_FULL;
796 break;
798 default:
799 if (rb->default_event_handler_ex(button, cleanup, NULL)
800 == SYS_USB_CONNECTED)
801 return PLUGIN_USB_CONNECTED;
802 break;
804 if (button != BUTTON_NONE)
805 lastbutton = button;
807 #ifdef USEGSLIB
808 grey_release();
809 #endif
810 return PLUGIN_OK;
812 #endif