Fix ipod nano 2g bootloader link problem, caused by my previous commit
[kugel-rb.git] / apps / plugins / mandelbrot.c
blobdbab55579dcbb07d7fba23e2a11eb9f7a3159f8c
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 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "plugin.h"
25 #ifdef HAVE_LCD_BITMAP
26 #include "lib/grey.h"
27 #include "lib/xlcd.h"
29 PLUGIN_HEADER
31 /* variable button definitions */
32 #if CONFIG_KEYPAD == RECORDER_PAD
33 #define MANDELBROT_QUIT BUTTON_OFF
34 #define MANDELBROT_UP BUTTON_UP
35 #define MANDELBROT_DOWN BUTTON_DOWN
36 #define MANDELBROT_LEFT BUTTON_LEFT
37 #define MANDELBROT_RIGHT BUTTON_RIGHT
38 #define MANDELBROT_ZOOM_IN BUTTON_PLAY
39 #define MANDELBROT_ZOOM_OUT BUTTON_ON
40 #define MANDELBROT_MAXITER_INC BUTTON_F2
41 #define MANDELBROT_MAXITER_DEC BUTTON_F1
42 #define MANDELBROT_RESET BUTTON_F3
44 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
45 #define MANDELBROT_QUIT BUTTON_OFF
46 #define MANDELBROT_UP BUTTON_UP
47 #define MANDELBROT_DOWN BUTTON_DOWN
48 #define MANDELBROT_LEFT BUTTON_LEFT
49 #define MANDELBROT_RIGHT BUTTON_RIGHT
50 #define MANDELBROT_ZOOM_IN BUTTON_SELECT
51 #define MANDELBROT_ZOOM_OUT BUTTON_ON
52 #define MANDELBROT_MAXITER_INC BUTTON_F2
53 #define MANDELBROT_MAXITER_DEC BUTTON_F1
54 #define MANDELBROT_RESET BUTTON_F3
56 #elif CONFIG_KEYPAD == ONDIO_PAD
57 #define MANDELBROT_QUIT BUTTON_OFF
58 #define MANDELBROT_UP BUTTON_UP
59 #define MANDELBROT_DOWN BUTTON_DOWN
60 #define MANDELBROT_LEFT BUTTON_LEFT
61 #define MANDELBROT_RIGHT BUTTON_RIGHT
62 #define MANDELBROT_ZOOM_IN_PRE BUTTON_MENU
63 #define MANDELBROT_ZOOM_IN (BUTTON_MENU | BUTTON_REL)
64 #define MANDELBROT_ZOOM_IN2 (BUTTON_MENU | BUTTON_UP)
65 #define MANDELBROT_ZOOM_OUT (BUTTON_MENU | BUTTON_DOWN)
66 #define MANDELBROT_MAXITER_INC (BUTTON_MENU | BUTTON_RIGHT)
67 #define MANDELBROT_MAXITER_DEC (BUTTON_MENU | BUTTON_LEFT)
68 #define MANDELBROT_RESET (BUTTON_MENU | BUTTON_OFF)
70 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
71 (CONFIG_KEYPAD == IRIVER_H300_PAD)
72 #define MANDELBROT_QUIT BUTTON_OFF
73 #define MANDELBROT_UP BUTTON_UP
74 #define MANDELBROT_DOWN BUTTON_DOWN
75 #define MANDELBROT_LEFT BUTTON_LEFT
76 #define MANDELBROT_RIGHT BUTTON_RIGHT
77 #define MANDELBROT_ZOOM_IN BUTTON_SELECT
78 #define MANDELBROT_ZOOM_OUT BUTTON_MODE
79 #define MANDELBROT_MAXITER_INC (BUTTON_ON | BUTTON_RIGHT)
80 #define MANDELBROT_MAXITER_DEC (BUTTON_ON | BUTTON_LEFT)
81 #define MANDELBROT_RESET BUTTON_REC
83 #define MANDELBROT_RC_QUIT BUTTON_RC_STOP
85 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
86 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
87 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
88 #define MANDELBROT_QUIT (BUTTON_SELECT | BUTTON_MENU)
89 #define MANDELBROT_UP BUTTON_MENU
90 #define MANDELBROT_DOWN BUTTON_PLAY
91 #define MANDELBROT_LEFT BUTTON_LEFT
92 #define MANDELBROT_RIGHT BUTTON_RIGHT
93 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
94 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
95 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
96 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
97 #define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_PLAY)
99 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
100 #define MANDELBROT_QUIT BUTTON_POWER
101 #define MANDELBROT_UP BUTTON_UP
102 #define MANDELBROT_DOWN BUTTON_DOWN
103 #define MANDELBROT_LEFT BUTTON_LEFT
104 #define MANDELBROT_RIGHT BUTTON_RIGHT
105 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
106 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
107 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
108 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
109 #define MANDELBROT_MAXITER_INC_PRE BUTTON_PLAY
110 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_REL)
111 #define MANDELBROT_MAXITER_DEC_PRE BUTTON_PLAY
112 #define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_REPEAT)
113 #define MANDELBROT_RESET BUTTON_REC
115 #elif CONFIG_KEYPAD == GIGABEAT_PAD
116 #define MANDELBROT_QUIT BUTTON_POWER
117 #define MANDELBROT_UP BUTTON_UP
118 #define MANDELBROT_DOWN BUTTON_DOWN
119 #define MANDELBROT_LEFT BUTTON_LEFT
120 #define MANDELBROT_RIGHT BUTTON_RIGHT
121 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
122 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
123 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
124 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
125 #define MANDELBROT_MAXITER_INC BUTTON_VOL_UP
126 #define MANDELBROT_MAXITER_DEC BUTTON_VOL_DOWN
127 #define MANDELBROT_RESET BUTTON_A
129 #elif CONFIG_KEYPAD == SANSA_E200_PAD
130 #define MANDELBROT_QUIT BUTTON_POWER
131 #define MANDELBROT_UP BUTTON_UP
132 #define MANDELBROT_DOWN BUTTON_DOWN
133 #define MANDELBROT_LEFT BUTTON_LEFT
134 #define MANDELBROT_RIGHT BUTTON_RIGHT
135 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
136 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
137 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
138 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
139 #define MANDELBROT_RESET BUTTON_REC
141 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
142 #define MANDELBROT_QUIT (BUTTON_HOME|BUTTON_REPEAT)
143 #define MANDELBROT_UP BUTTON_UP
144 #define MANDELBROT_DOWN BUTTON_DOWN
145 #define MANDELBROT_LEFT BUTTON_LEFT
146 #define MANDELBROT_RIGHT BUTTON_RIGHT
147 #define MANDELBROT_ZOOM_IN BUTTON_SCROLL_FWD
148 #define MANDELBROT_ZOOM_OUT BUTTON_SCROLL_BACK
149 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
150 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
151 #define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_REPEAT)
153 #elif CONFIG_KEYPAD == SANSA_C200_PAD
154 #define MANDELBROT_QUIT BUTTON_POWER
155 #define MANDELBROT_UP BUTTON_UP
156 #define MANDELBROT_DOWN BUTTON_DOWN
157 #define MANDELBROT_LEFT BUTTON_LEFT
158 #define MANDELBROT_RIGHT BUTTON_RIGHT
159 #define MANDELBROT_ZOOM_IN BUTTON_VOL_UP
160 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
161 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
162 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
163 #define MANDELBROT_RESET BUTTON_REC
165 #elif CONFIG_KEYPAD == SANSA_CLIP_PAD
166 #define MANDELBROT_QUIT BUTTON_POWER
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 BUTTON_VOL_UP
172 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
173 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
174 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
175 #define MANDELBROT_RESET BUTTON_HOME
177 #elif CONFIG_KEYPAD == SANSA_M200_PAD
178 #define MANDELBROT_QUIT BUTTON_POWER
179 #define MANDELBROT_UP BUTTON_UP
180 #define MANDELBROT_DOWN BUTTON_DOWN
181 #define MANDELBROT_LEFT BUTTON_LEFT
182 #define MANDELBROT_RIGHT BUTTON_RIGHT
183 #define MANDELBROT_ZOOM_IN BUTTON_VOL_UP
184 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
185 #define MANDELBROT_MAXITER_INC (BUTTON_SELECT | BUTTON_RIGHT)
186 #define MANDELBROT_MAXITER_DEC (BUTTON_SELECT | BUTTON_LEFT)
187 #define MANDELBROT_RESET (BUTTON_SELECT | BUTTON_UP)
189 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
190 #define MANDELBROT_QUIT BUTTON_POWER
191 #define MANDELBROT_UP BUTTON_SCROLL_UP
192 #define MANDELBROT_DOWN BUTTON_SCROLL_DOWN
193 #define MANDELBROT_LEFT BUTTON_LEFT
194 #define MANDELBROT_RIGHT BUTTON_RIGHT
195 #define MANDELBROT_ZOOM_IN_PRE BUTTON_PLAY
196 #define MANDELBROT_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
197 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_PLAY
198 #define MANDELBROT_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
199 #define MANDELBROT_MAXITER_INC BUTTON_FF
200 #define MANDELBROT_MAXITER_DEC BUTTON_REW
201 #define MANDELBROT_RESET (BUTTON_PLAY | BUTTON_REW)
203 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
204 #define MANDELBROT_QUIT BUTTON_EQ
205 #define MANDELBROT_UP BUTTON_UP
206 #define MANDELBROT_DOWN BUTTON_DOWN
207 #define MANDELBROT_LEFT BUTTON_LEFT
208 #define MANDELBROT_RIGHT BUTTON_RIGHT
209 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
210 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
211 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
212 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
213 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_RIGHT)
214 #define MANDELBROT_MAXITER_DEC (BUTTON_PLAY | BUTTON_LEFT)
215 #define MANDELBROT_RESET BUTTON_MODE
217 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
218 #define MANDELBROT_QUIT BUTTON_BACK
219 #define MANDELBROT_UP BUTTON_UP
220 #define MANDELBROT_DOWN BUTTON_DOWN
221 #define MANDELBROT_LEFT BUTTON_LEFT
222 #define MANDELBROT_RIGHT BUTTON_RIGHT
223 #define MANDELBROT_ZOOM_IN BUTTON_VOL_UP
224 #define MANDELBROT_ZOOM_OUT BUTTON_VOL_DOWN
225 #define MANDELBROT_MAXITER_INC BUTTON_PREV
226 #define MANDELBROT_MAXITER_DEC BUTTON_NEXT
227 #define MANDELBROT_RESET BUTTON_MENU
229 #elif CONFIG_KEYPAD == MROBE100_PAD
230 #define MANDELBROT_QUIT BUTTON_POWER
231 #define MANDELBROT_UP BUTTON_UP
232 #define MANDELBROT_DOWN BUTTON_DOWN
233 #define MANDELBROT_LEFT BUTTON_LEFT
234 #define MANDELBROT_RIGHT BUTTON_RIGHT
235 #define MANDELBROT_ZOOM_IN_PRE BUTTON_SELECT
236 #define MANDELBROT_ZOOM_IN (BUTTON_SELECT | BUTTON_REL)
237 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_SELECT
238 #define MANDELBROT_ZOOM_OUT (BUTTON_SELECT | BUTTON_REPEAT)
239 #define MANDELBROT_MAXITER_INC BUTTON_MENU
240 #define MANDELBROT_MAXITER_DEC BUTTON_PLAY
241 #define MANDELBROT_RESET BUTTON_DISPLAY
243 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
244 #define MANDELBROT_QUIT BUTTON_RC_REC
245 #define MANDELBROT_UP BUTTON_RC_VOL_UP
246 #define MANDELBROT_DOWN BUTTON_RC_VOL_DOWN
247 #define MANDELBROT_LEFT BUTTON_RC_REW
248 #define MANDELBROT_RIGHT BUTTON_RC_FF
249 #define MANDELBROT_ZOOM_IN_PRE BUTTON_RC_PLAY
250 #define MANDELBROT_ZOOM_IN (BUTTON_RC_PLAY | BUTTON_REL)
251 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_RC_PLAY
252 #define MANDELBROT_ZOOM_OUT (BUTTON_RC_PLAY | BUTTON_REPEAT)
253 #define MANDELBROT_MAXITER_INC_PRE BUTTON_RC_MODE
254 #define MANDELBROT_MAXITER_INC (BUTTON_RC_MODE|BUTTON_REL)
255 #define MANDELBROT_MAXITER_DEC_PRE BUTTON_RC_MODE
256 #define MANDELBROT_MAXITER_DEC (BUTTON_RC_MODE|BUTTON_REPEAT)
257 #define MANDELBROT_RESET BUTTON_RC_MENU
259 #elif CONFIG_KEYPAD == COWOND2_PAD
260 #define MANDELBROT_QUIT BUTTON_POWER
262 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
263 #define MANDELBROT_QUIT BUTTON_BACK
264 #define MANDELBROT_UP BUTTON_UP
265 #define MANDELBROT_DOWN BUTTON_DOWN
266 #define MANDELBROT_LEFT BUTTON_LEFT
267 #define MANDELBROT_RIGHT BUTTON_RIGHT
268 #define MANDELBROT_ZOOM_IN BUTTON_PLAY
269 #define MANDELBROT_ZOOM_OUT BUTTON_MENU
270 #define MANDELBROT_MAXITER_INC (BUTTON_UP | BUTTON_CUSTOM)
271 #define MANDELBROT_MAXITER_DEC (BUTTON_DOWN | BUTTON_CUSTOM)
272 #define MANDELBROT_RESET BUTTON_SELECT
274 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
275 #define MANDELBROT_QUIT BUTTON_POWER
276 #define MANDELBROT_UP BUTTON_UP
277 #define MANDELBROT_DOWN BUTTON_DOWN
278 #define MANDELBROT_LEFT BUTTON_LEFT
279 #define MANDELBROT_RIGHT BUTTON_RIGHT
280 #define MANDELBROT_ZOOM_IN BUTTON_VIEW
281 #define MANDELBROT_ZOOM_OUT BUTTON_PLAYLIST
282 #define MANDELBROT_MAXITER_INC BUTTON_VOL_UP
283 #define MANDELBROT_MAXITER_DEC BUTTON_VOL_DOWN
284 #define MANDELBROT_RESET BUTTON_MENU
286 #elif CONFIG_KEYPAD == ONDAVX747_PAD || CONFIG_KEYPAD == MROBE500_PAD
287 #define MANDELBROT_QUIT BUTTON_POWER
289 #elif CONFIG_KEYPAD == ONDAVX777_PAD
290 #define MANDELBROT_QUIT BUTTON_POWER
292 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
293 #define MANDELBROT_QUIT BUTTON_REC
294 #define MANDELBROT_UP BUTTON_UP
295 #define MANDELBROT_DOWN BUTTON_DOWN
296 #define MANDELBROT_LEFT BUTTON_LEFT
297 #define MANDELBROT_RIGHT BUTTON_RIGHT
298 #define MANDELBROT_ZOOM_IN_PRE (BUTTON_FFWD | BUTTON_UP)
299 #define MANDELBROT_ZOOM_IN (BUTTON_REW | BUTTON_UP)
300 #define MANDELBROT_ZOOM_OUT_PRE (BUTTON_FFWD | BUTTON_DOWN)
301 #define MANDELBROT_ZOOM_OUT (BUTTON_REW | BUTTON_DOWN)
302 #define MANDELBROT_MAXITER_INC (BUTTON_PLAY | BUTTON_UP)
303 #define MANDELBROT_MAXITER_DEC (BUTTON_FFWD | BUTTON_DOWN)
304 #define MANDELBROT_RESET (BUTTON_PLAY | BUTTON_RIGHT)
306 #else
307 #error No keymap defined!
308 #endif
310 #ifdef HAVE_TOUCHSCREEN
311 #ifndef MANDELBROT_UP
312 #define MANDELBROT_UP BUTTON_TOPMIDDLE
313 #endif
314 #ifndef MANDELBROT_DOWN
315 #define MANDELBROT_DOWN BUTTON_BOTTOMMIDDLE
316 #endif
317 #ifndef MANDELBROT_LEFT
318 #define MANDELBROT_LEFT BUTTON_MIDLEFT
319 #endif
320 #ifndef MANDELBROT_RIGHT
321 #define MANDELBROT_RIGHT BUTTON_MIDRIGHT
322 #endif
323 #ifndef MANDELBROT_ZOOM_IN_PRE
324 #define MANDELBROT_ZOOM_IN_PRE BUTTON_TOPRIGHT
325 #endif
326 #ifndef MANDELBROT_ZOOM_IN
327 #define MANDELBROT_ZOOM_IN (BUTTON_TOPRIGHT | BUTTON_REL)
328 #endif
329 #ifndef MANDELBROT_ZOOM_OUT_PRE
330 #define MANDELBROT_ZOOM_OUT_PRE BUTTON_TOPLEFT
331 #endif
332 #ifndef MANDELBROT_ZOOM_OUT
333 #define MANDELBROT_ZOOM_OUT (BUTTON_TOPLEFT | BUTTON_REL)
334 #endif
335 #ifndef MANDELBROT_MAXITER_INC
336 #define MANDELBROT_MAXITER_INC BUTTON_BOTTOMRIGHT
337 #endif
338 #ifndef MANDELBROT_MAXITER_DEC
339 #define MANDELBROT_MAXITER_DEC BUTTON_BOTTOMLEFT
340 #endif
341 #ifndef MANDELBROT_RESET
342 #define MANDELBROT_RESET BUTTON_CENTER
343 #endif
344 #endif
346 #if LCD_DEPTH < 8
347 #define USEGSLIB
348 #define MYLCD(fn) grey_ub_ ## fn
349 #define MYLCD_UPDATE()
350 #define MYXLCD(fn) grey_ub_ ## fn
351 #else
352 #define UPDATE_FREQ (HZ/50)
353 #define MYLCD(fn) rb->lcd_ ## fn
354 #define MYLCD_UPDATE() rb->lcd_update();
355 #define MYXLCD(fn) xlcd_ ## fn
356 #endif
358 /* Fixed point format s5.26: sign, 5 bits integer part, 26 bits fractional part */
359 static long x_min;
360 static long x_max;
361 static long x_step;
362 static long x_delta;
363 static long y_min;
364 static long y_max;
365 static long y_step;
366 static long y_delta;
368 static int px_min = 0;
369 static int px_max = LCD_WIDTH;
370 static int py_min = 0;
371 static int py_max = LCD_HEIGHT;
373 static int step_log2;
374 static unsigned max_iter;
376 #ifdef USEGSLIB
377 GREY_INFO_STRUCT
378 static unsigned char *gbuf;
379 static size_t gbuf_size = 0;
380 static unsigned char imgbuffer[LCD_HEIGHT];
381 #else
382 static fb_data imgbuffer[LCD_HEIGHT];
383 #endif
385 /* 8 entries cyclical, last entry is black (convergence) */
386 #ifdef HAVE_LCD_COLOR
387 static const fb_data color[9] = {
388 LCD_RGBPACK(255, 0, 159), LCD_RGBPACK(159, 0, 255), LCD_RGBPACK(0, 0, 255),
389 LCD_RGBPACK(0, 159, 255), LCD_RGBPACK(0, 255, 128), LCD_RGBPACK(128, 255, 0),
390 LCD_RGBPACK(255, 191, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 0, 0)
392 #else /* greyscale */
393 static const unsigned char color[9] = {
394 255, 223, 191, 159, 128, 96, 64, 32, 0
396 #endif
398 #if CONFIG_CPU == SH7034
400 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
401 static inline short muls16_asr10(short a, short b)
403 short r;
404 asm (
405 "muls %[a],%[b] \n"
406 "sts macl,%[r] \n"
407 "shlr8 %[r] \n"
408 "shlr2 %[r] \n"
409 : /* outputs */
410 [r]"=r"(r)
411 : /* inputs */
412 [a]"r"(a),
413 [b]"r"(b)
415 return r;
418 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
419 static inline long muls32_asr26(long a, long b)
421 long r, t1, t2, t3;
422 asm (
423 /* Signed 32bit * 32bit -> 64bit multiplication.
424 Notation: xxab * xxcd, where each letter represents 16 bits.
425 xx is the 64 bit sign extension. */
426 "swap.w %[a],%[t1] \n" /* t1 = ba */
427 "mulu %[t1],%[b] \n" /* a * d */
428 "swap.w %[b],%[t3] \n" /* t3 = dc */
429 "sts macl,%[t2] \n" /* t2 = a * d */
430 "mulu %[t1],%[t3] \n" /* a * c */
431 "sts macl,%[r] \n" /* hi = a * c */
432 "mulu %[a],%[t3] \n" /* b * c */
433 "clrt \n"
434 "sts macl,%[t3] \n" /* t3 = b * c */
435 "addc %[t2],%[t3] \n" /* t3 += t2, carry -> t2 */
436 "movt %[t2] \n"
437 "mulu %[a],%[b] \n" /* b * d */
438 "mov %[t3],%[t1] \n" /* t1t3 = t2t3 << 16 */
439 "xtrct %[t2],%[t1] \n"
440 "shll16 %[t3] \n"
441 "sts macl,%[t2] \n" /* lo = b * d */
442 "clrt \n" /* hi.lo += t1t3 */
443 "addc %[t3],%[t2] \n"
444 "addc %[t1],%[r] \n"
445 "cmp/pz %[a] \n" /* ab >= 0 ? */
446 "bt 1f \n"
447 "sub %[b],%[r] \n" /* no: hi -= cd (sign extension of ab is -1) */
448 "1: \n"
449 "cmp/pz %[b] \n" /* cd >= 0 ? */
450 "bt 2f \n"
451 "sub %[a],%[r] \n" /* no: hi -= ab (sign extension of cd is -1) */
452 "2: \n"
453 /* Shift right by 26 and return low 32 bits */
454 "shll2 %[r] \n" /* hi <<= 6 */
455 "shll2 %[r] \n"
456 "shll2 %[r] \n"
457 "shlr16 %[t2] \n" /* (unsigned)lo >>= 26 */
458 "shlr8 %[t2] \n"
459 "shlr2 %[t2] \n"
460 "or %[t2],%[r] \n" /* combine result */
461 : /* outputs */
462 [r] "=&r"(r),
463 [t1]"=&r"(t1),
464 [t2]"=&r"(t2),
465 [t3]"=&r"(t3)
466 : /* inputs */
467 [a] "r" (a),
468 [b] "r" (b)
470 return r;
473 #elif defined CPU_COLDFIRE
475 #define MULS16_ASR10(a, b) muls16_asr10(a, b)
476 static inline short muls16_asr10(short a, short b)
478 asm (
479 "muls.w %[a],%[b] \n"
480 "asr.l #8,%[b] \n"
481 "asr.l #2,%[b] \n"
482 : /* outputs */
483 [b]"+d"(b)
484 : /* inputs */
485 [a]"d" (a)
487 return b;
490 /* Needs the EMAC initialised to fractional mode w/o rounding and saturation */
491 #define MULS32_INIT() coldfire_set_macsr(EMAC_FRACTIONAL)
492 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
493 static inline long muls32_asr26(long a, long b)
495 long r, t1;
496 asm (
497 "mac.l %[a], %[b], %%acc0 \n" /* multiply */
498 "move.l %%accext01, %[t1] \n" /* get low part */
499 "movclr.l %%acc0, %[r] \n" /* get high part */
500 "asl.l #5, %[r] \n" /* hi <<= 5, plus one free */
501 "lsr.l #3, %[t1] \n" /* lo >>= 3 */
502 "and.l #0x1f, %[t1] \n" /* mask out unrelated bits */
503 "or.l %[t1], %[r] \n" /* combine result */
504 : /* outputs */
505 [r] "=d"(r),
506 [t1]"=d"(t1)
507 : /* inputs */
508 [a] "d" (a),
509 [b] "d" (b)
511 return r;
514 #elif defined CPU_ARM
516 #define MULS32_ASR26(a, b) muls32_asr26(a, b)
517 static inline long muls32_asr26(long a, long b)
519 long r, t1;
520 asm (
521 "smull %[r], %[t1], %[a], %[b] \n"
522 "mov %[r], %[r], lsr #26 \n"
523 "orr %[r], %[r], %[t1], lsl #6 \n"
524 : /* outputs */
525 [r] "=&r,&r,&r"(r),
526 [t1]"=&r,&r,&r"(t1)
527 : /* inputs */
528 [a] "%r,%r,%r" (a),
529 [b] "r,0,1" (b)
531 return r;
534 #endif /* CPU */
536 /* default macros */
537 #ifndef MULS16_ASR10
538 #define MULS16_ASR10(a, b) ((short)(((long)(a) * (long)(b)) >> 10))
539 #endif
540 #ifndef MULS32_ASR26
541 #define MULS32_ASR26(a, b) ((long)(((long long)(a) * (long long)(b)) >> 26))
542 #endif
543 #ifndef MULS32_INIT
544 #define MULS32_INIT()
545 #endif
547 int ilog2_fp(long value) /* calculate integer log2(value_fp_6.26) */
549 int i = 0;
551 if (value <= 0) {
552 return -32767;
553 } else if (value > (1L<<26)) {
554 while (value >= (2L<<26)) {
555 value >>= 1;
556 i++;
558 } else {
559 while (value < (1L<<26)) {
560 value <<= 1;
561 i--;
564 return i;
567 void recalc_parameters(void)
569 x_step = (x_max - x_min) / LCD_WIDTH;
570 x_delta = (x_step * LCD_WIDTH) / 8;
571 y_step = (y_max - y_min) / LCD_HEIGHT;
572 y_delta = (y_step * LCD_HEIGHT) / 8;
573 step_log2 = ilog2_fp(MIN(x_step, y_step));
574 max_iter = MAX(15, -15 * step_log2 - 45);
577 #if CONFIG_LCD == LCD_SSD1815
578 /* Recorder, Ondio: pixel_height == 1.25 * pixel_width */
579 #define MB_HEIGHT (LCD_HEIGHT*5/4)
580 #else
581 /* square pixels */
582 #define MB_HEIGHT LCD_HEIGHT
583 #endif
585 #define MB_XOFS (-0x03000000L) /* -0.75 (s5.26) */
586 #if 3000*MB_HEIGHT/LCD_WIDTH >= 2400 /* width is limiting factor */
587 #define MB_XFAC (0x06000000LL) /* 1.5 (s5.26) */
588 #define MB_YFAC (MB_XFAC*MB_HEIGHT/LCD_WIDTH)
589 #else /* height is limiting factor */
590 #define MB_YFAC (0x04cccccdLL) /* 1.2 (s5.26) */
591 #define MB_XFAC (MB_YFAC*LCD_WIDTH/MB_HEIGHT)
592 #endif
594 void init_mandelbrot_set(void)
596 x_min = MB_XOFS-MB_XFAC;
597 x_max = MB_XOFS+MB_XFAC;
598 y_min = -MB_YFAC;
599 y_max = MB_YFAC;
600 recalc_parameters();
603 void calc_mandelbrot_low_prec(void)
605 long start_tick, last_yield;
606 #ifndef USEGSLIB
607 long next_update = *rb->current_tick;
608 int last_px = px_min;
609 #endif
610 unsigned n_iter;
611 long a32, b32;
612 short x, x2, y, y2, a, b;
613 int p_x, p_y;
615 start_tick = last_yield = *rb->current_tick;
617 for (p_x = 0, a32 = x_min; p_x < px_max; p_x++, a32 += x_step) {
618 if (p_x < px_min)
619 continue;
620 a = a32 >> 16;
621 for (p_y = LCD_HEIGHT-1, b32 = y_min; p_y >= py_min; p_y--, b32 += y_step) {
622 if (p_y >= py_max)
623 continue;
624 b = b32 >> 16;
625 x = a;
626 y = b;
627 n_iter = 0;
629 while (++n_iter <= max_iter) {
630 x2 = MULS16_ASR10(x, x);
631 y2 = MULS16_ASR10(y, y);
633 if (x2 + y2 > (4<<10)) break;
635 y = 2 * MULS16_ASR10(x, y) + b;
636 x = x2 - y2 + a;
639 if (n_iter > max_iter)
640 imgbuffer[p_y] = color[8];
641 else
642 imgbuffer[p_y] = color[n_iter & 7];
644 /* be nice to other threads:
645 * if at least one tick has passed, yield */
646 if (TIME_AFTER(*rb->current_tick, last_yield)) {
647 rb->yield();
648 last_yield = *rb->current_tick;
651 #ifdef USEGSLIB
652 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
653 p_x, py_min, 1, py_max - py_min);
654 #else
655 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
656 p_x, py_min, 1, py_max - py_min);
657 if ((p_x == px_max - 1) || TIME_AFTER(*rb->current_tick, next_update))
659 next_update = *rb->current_tick + UPDATE_FREQ;
660 rb->lcd_update_rect(last_px, py_min, p_x - last_px + 1,
661 py_max - py_min);
662 last_px = p_x;
664 #endif
668 void calc_mandelbrot_high_prec(void)
670 long start_tick, last_yield;
671 #ifndef USEGSLIB
672 long next_update = *rb->current_tick;
673 int last_px = px_min;
674 #endif
675 unsigned n_iter;
676 long x, x2, y, y2, a, b;
677 int p_x, p_y;
679 MULS32_INIT();
680 start_tick = last_yield = *rb->current_tick;
682 for (p_x = 0, a = x_min; p_x < px_max; p_x++, a += x_step) {
683 if (p_x < px_min)
684 continue;
685 for (p_y = LCD_HEIGHT-1, b = y_min; p_y >= py_min; p_y--, b += y_step) {
686 if (p_y >= py_max)
687 continue;
688 x = a;
689 y = b;
690 n_iter = 0;
692 while (++n_iter <= max_iter) {
693 x2 = MULS32_ASR26(x, x);
694 y2 = MULS32_ASR26(y, y);
696 if (x2 + y2 > (4L<<26)) break;
698 y = 2 * MULS32_ASR26(x, y) + b;
699 x = x2 - y2 + a;
702 if (n_iter > max_iter)
703 imgbuffer[p_y] = color[8];
704 else
705 imgbuffer[p_y] = color[n_iter & 7];
707 /* be nice to other threads:
708 * if at least one tick has passed, yield */
709 if (TIME_AFTER(*rb->current_tick, last_yield)) {
710 rb->yield();
711 last_yield = *rb->current_tick;
714 #ifdef USEGSLIB
715 grey_ub_gray_bitmap_part(imgbuffer, 0, py_min, 1,
716 p_x, py_min, 1, py_max - py_min);
717 #else
718 rb->lcd_bitmap_part(imgbuffer, 0, py_min, 1,
719 p_x, py_min, 1, py_max-py_min);
720 if ((p_x == px_max - 1) || TIME_AFTER(*rb->current_tick, next_update))
722 next_update = *rb->current_tick + UPDATE_FREQ;
723 rb->lcd_update_rect(last_px, py_min, p_x - last_px + 1,
724 py_max - py_min);
725 last_px = p_x;
727 #endif
731 void cleanup(void *parameter)
733 (void)parameter;
734 #ifdef USEGSLIB
735 grey_release();
736 #endif
739 #define REDRAW_NONE 0
740 #define REDRAW_PARTIAL 1
741 #define REDRAW_FULL 2
743 enum plugin_status plugin_start(const void* parameter)
745 int button;
746 int lastbutton = BUTTON_NONE;
747 int redraw = REDRAW_FULL;
749 (void)parameter;
751 #ifdef USEGSLIB
752 /* get the remainder of the plugin buffer */
753 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
755 /* initialize the greyscale buffer.*/
756 if (!grey_init(gbuf, gbuf_size, GREY_ON_COP,
757 LCD_WIDTH, LCD_HEIGHT, NULL))
759 rb->splash(HZ, "Couldn't init greyscale display");
760 return 0;
762 grey_show(true); /* switch on greyscale overlay */
763 #endif
765 #if LCD_DEPTH > 1
766 rb->lcd_set_backdrop(NULL);
767 #endif
769 init_mandelbrot_set();
771 /* main loop */
772 while (true) {
773 if (redraw > REDRAW_NONE) {
774 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
775 rb->cpu_boost(true);
776 #endif
777 if (redraw == REDRAW_FULL) {
778 MYLCD(clear_display)();
779 MYLCD_UPDATE();
782 if (step_log2 <= -10) /* select precision */
783 calc_mandelbrot_high_prec();
784 else
785 calc_mandelbrot_low_prec();
787 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
788 rb->cpu_boost(false);
789 #endif
790 px_min = 0;
791 px_max = LCD_WIDTH;
792 py_min = 0;
793 py_max = LCD_HEIGHT;
794 redraw = REDRAW_NONE;
797 button = rb->button_get(true);
798 switch (button) {
799 #ifdef MANDELBROT_RC_QUIT
800 case MANDELBROT_RC_QUIT:
801 #endif
802 case MANDELBROT_QUIT:
803 #ifdef USEGSLIB
804 grey_release();
805 #endif
806 return PLUGIN_OK;
808 case MANDELBROT_ZOOM_OUT:
809 #ifdef MANDELBROT_ZOOM_OUT_PRE
810 if (lastbutton != MANDELBROT_ZOOM_OUT_PRE)
811 break;
812 #endif
813 x_min -= x_delta;
814 x_max += x_delta;
815 y_min -= y_delta;
816 y_max += y_delta;
817 recalc_parameters();
818 redraw = REDRAW_FULL;
819 break;
822 case MANDELBROT_ZOOM_IN:
823 #ifdef MANDELBROT_ZOOM_IN_PRE
824 if (lastbutton != MANDELBROT_ZOOM_IN_PRE)
825 break;
826 #endif
827 #ifdef MANDELBROT_ZOOM_IN2
828 case MANDELBROT_ZOOM_IN2:
829 #endif
830 x_min += x_delta;
831 x_max -= x_delta;
832 y_min += y_delta;
833 y_max -= y_delta;
834 recalc_parameters();
835 redraw = REDRAW_FULL;
836 break;
838 case MANDELBROT_UP:
839 y_min += y_delta;
840 y_max += y_delta;
841 MYXLCD(scroll_down)(LCD_HEIGHT/8);
842 MYLCD_UPDATE();
843 py_max = (LCD_HEIGHT/8);
844 redraw = REDRAW_PARTIAL;
845 break;
847 case MANDELBROT_DOWN:
848 y_min -= y_delta;
849 y_max -= y_delta;
850 MYXLCD(scroll_up)(LCD_HEIGHT/8);
851 MYLCD_UPDATE();
852 py_min = (LCD_HEIGHT-LCD_HEIGHT/8);
853 redraw = REDRAW_PARTIAL;
854 break;
856 case MANDELBROT_LEFT:
857 x_min -= x_delta;
858 x_max -= x_delta;
859 MYXLCD(scroll_right)(LCD_WIDTH/8);
860 MYLCD_UPDATE();
861 px_max = (LCD_WIDTH/8);
862 redraw = REDRAW_PARTIAL;
863 break;
865 case MANDELBROT_RIGHT:
866 x_min += x_delta;
867 x_max += x_delta;
868 MYXLCD(scroll_left)(LCD_WIDTH/8);
869 MYLCD_UPDATE();
870 px_min = (LCD_WIDTH-LCD_WIDTH/8);
871 redraw = REDRAW_PARTIAL;
872 break;
874 case MANDELBROT_MAXITER_DEC:
875 #ifdef MANDELBROT_MAXITER_DEC_PRE
876 if (lastbutton != MANDELBROT_MAXITER_DEC_PRE)
877 break;
878 #endif
879 if (max_iter >= 15) {
880 max_iter -= max_iter / 3;
881 redraw = REDRAW_FULL;
883 break;
885 case MANDELBROT_MAXITER_INC:
886 #ifdef MANDELBROT_MAXITER_INC_PRE
887 if (lastbutton != MANDELBROT_MAXITER_INC_PRE)
888 break;
889 #endif
890 max_iter += max_iter / 2;
891 redraw = REDRAW_FULL;
892 break;
894 case MANDELBROT_RESET:
895 init_mandelbrot_set();
896 redraw = REDRAW_FULL;
897 break;
899 default:
900 if (rb->default_event_handler_ex(button, cleanup, NULL)
901 == SYS_USB_CONNECTED)
902 return PLUGIN_USB_CONNECTED;
903 break;
905 if (button != BUTTON_NONE)
906 lastbutton = button;
908 #ifdef USEGSLIB
909 grey_release();
910 #endif
911 return PLUGIN_OK;
913 #endif