1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Kevin Ferrare
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 ****************************************************************************/
26 #ifdef HAVE_LCD_BITMAP
28 #include "pluginlib_actions.h"
29 #include "fixedpoint.h"
31 #ifndef HAVE_LCD_COLOR
35 #if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64)
36 /* Archos has not enough plugin RAM for full-width fire :( */
37 #define FIRE_WIDTH 106
40 #define FIRE_WIDTH LCD_WIDTH
46 static const struct plugin_api
* rb
; /* global api struct pointer */
48 #ifndef HAVE_LCD_COLOR
50 static unsigned char draw_buffer
[FIRE_WIDTH
];
55 const struct button_mapping
* plugin_contexts
[]= {
56 generic_increase_decrease
,
58 #if defined(HAVE_REMOTE_LCD)
63 #define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0])
65 #define FIRE_QUIT PLA_QUIT
66 #define FIRE_SWITCH_FLAMES_TYPE PLA_LEFT
67 #define FIRE_SWITCH_FLAMES_MOVING PLA_RIGHT
68 #define FIRE_INCREASE_MULT PLA_INC
69 #define FIRE_DECREASE_MULT PLA_DEC
71 #define MIN_FLAME_VALUE 0
72 #define COOL_MAX (440/LCD_HEIGHT+2)
74 #ifndef HAVE_LCD_COLOR
75 static unsigned char palette
[256];
77 void color_palette_init(unsigned char* palette
)
80 for(i
=0;i
<=160;i
++)//palette[i]=(3/2)*i
83 /* 'regular' fire doesn't exceed this value */
84 for(;i
<=255;i
++)//palette[i]=(3/20)*i+216
85 palette
[i
]=(i
*3+20*217)/20;
89 static fb_data palette
[256];
92 * Color palette generation algorithm taken from
93 * the "The Demo Effects Collection" GPL project
94 * Copyright (C) 2002 W.P. van Paassen
96 void color_palette_init(fb_data
* palette
)
99 for (i
= 0; i
< 32; i
++){
100 /* black to blue, 32 values*/
101 palette
[i
]=LCD_RGBPACK(0, 0, 2*i
);
103 /* blue to red, 32 values*/
104 palette
[i
+ 32]=LCD_RGBPACK(8*i
, 0, 64 - 2*i
);
106 /* red to yellow, 32 values*/
107 palette
[i
+ 64]=LCD_RGBPACK(255, 8*i
, 0);
109 /* yellow to white, 162 values */
110 palette
[i
+ 96]=LCD_RGBPACK(255, 255, 0 + 4*i
);
111 palette
[i
+ 128]=LCD_RGBPACK(255, 255, 64 + 4*i
);
112 palette
[i
+ 160]=LCD_RGBPACK(255, 255, 128 + 4*i
);
113 palette
[i
+ 192]=LCD_RGBPACK(255, 255, 192 + i
);
114 palette
[i
+ 224]=LCD_RGBPACK(255, 255, 224 + i
);
120 static void tab_init_rand(unsigned char *tab
, unsigned int tab_size
,
123 unsigned char *end
= tab
+ tab_size
;
126 *tab
++ = (unsigned char)rb
->rand() % rand_max
;
130 unsigned char fire
[LCD_HEIGHT
+3][FIRE_WIDTH
];
131 unsigned char cooling_map
[LCD_HEIGHT
][FIRE_WIDTH
];
136 /* makes the instance a global variable since it's too big to fit on the target's stack */
137 static struct fire fire
;
139 static inline void fire_convolve(struct fire
* fire
)
141 unsigned int pixel_value
;
142 unsigned int cooling_value
;
143 unsigned char *ptr
, *end
, *cool
;
144 unsigned int mult
=fire
->mult
;
147 /* Convolve the pixels and handle cooling (to add nice shapes effects later) */
148 cool
= &fire
->cooling_map
[0][0];
149 ptr
= &fire
->fire
[0][0];
150 end
= ptr
+ LCD_HEIGHT
*FIRE_WIDTH
;
152 switch (fire
->flames_type
){
155 pixel_value
= ptr
[FIRE_WIDTH
-1] /* fire[y+1][x-1] */
156 + ptr
[2*FIRE_WIDTH
] /* fire[y+2][x] */
157 + ptr
[FIRE_WIDTH
+1] /* fire[y+1][x+1] */
158 + ptr
[3*FIRE_WIDTH
]; /* fire[y+3][x] */
159 pixel_value
= FMULU(pixel_value
, mult
) >> 10;
161 cooling_value
= *cool
++;
162 if (cooling_value
<= pixel_value
)
163 pixel_value
-= cooling_value
;
164 /* else it's too cold, don't frost the pixels !!! */
166 if (pixel_value
> 255)
169 *ptr
++ = pixel_value
;
176 pixel_value
= ptr
[FIRE_WIDTH
-1] /* fire[y+1][x-1] */
177 + ptr
[FIRE_WIDTH
] /* fire[y+1][x] */
178 + ptr
[FIRE_WIDTH
+1] /* fire[y+1][x+1] */
179 + ptr
[2*FIRE_WIDTH
]; /* fire[y+2][x] */
180 pixel_value
= FMULU(pixel_value
, mult
) >> 10;
182 cooling_value
= *cool
++;
183 if (cooling_value
<= pixel_value
)
184 pixel_value
-= cooling_value
;
185 /* else it's too cold, don't frost the pixels !!! */
187 if (pixel_value
> 255)
190 *ptr
++ = pixel_value
;
194 default: /* We should never reach this */
200 static void fire_generate_bottom_seed(struct fire
* fire
)
202 unsigned char *ptr
, *end
;
203 ptr
= &fire
->fire
[LCD_HEIGHT
][0];
204 end
= ptr
+ FIRE_WIDTH
;
206 *ptr
++ = (MIN_FLAME_VALUE
+ rb
->rand() % (256-MIN_FLAME_VALUE
));
210 static inline void fire_step(struct fire
* fire
)
213 /* Randomize the bottom line */
214 fire_generate_bottom_seed(fire
);
215 /* Add here further effects like fire letters, ball ... */
220 static void fire_init(struct fire
* fire
)
225 rb
->memset(&fire
->fire
[0][0], 0, sizeof(fire
->fire
));
226 tab_init_rand(&fire
->cooling_map
[0][0], LCD_HEIGHT
*FIRE_WIDTH
, COOL_MAX
);
227 fire_generate_bottom_seed(fire
);
230 static inline void fire_draw(struct fire
* fire
)
233 unsigned char *src
= &fire
->fire
[0][0];
234 #ifndef HAVE_LCD_COLOR
235 unsigned char *dest
, *end
;
240 for (y
= 0; y
< LCD_HEIGHT
; y
++){
241 #ifndef HAVE_LCD_COLOR
244 dest
= rb
->lcd_framebuffer
+ LCD_WIDTH
* y
+ FIRE_XPOS
;
246 end
= dest
+ FIRE_WIDTH
;
249 *dest
++ = palette
[*src
++];
251 #ifndef HAVE_LCD_COLOR
252 grey_ub_gray_bitmap(draw_buffer
, 0, y
, FIRE_WIDTH
, 1);
255 #ifdef HAVE_LCD_COLOR
260 void cleanup(void *parameter
)
263 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
264 rb
->cpu_boost(false);
266 #ifndef HAVE_LCD_COLOR
269 /* Turn on backlight timeout (revert to settings) */
270 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
274 #ifndef HAVE_LCD_COLOR
278 size_t gbuf_size
= 0;
280 /* get the remainder of the plugin buffer */
281 gbuf
= (unsigned char *) rb
->plugin_get_buffer(&gbuf_size
);
283 if (!grey_init(rb
, gbuf
, gbuf_size
, GREY_ON_COP
,
284 FIRE_WIDTH
, LCD_HEIGHT
, NULL
)){
285 rb
->splash(HZ
, "not enough memory");
288 /* switch on greyscale overlay */
289 grey_set_position(FIRE_XPOS
, 0);
299 #ifndef HAVE_LCD_COLOR
300 if(init_grey()!=PLUGIN_OK
)
301 return(PLUGIN_ERROR
);
303 color_palette_init(palette
);
305 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
315 action
= pluginlib_getaction(rb
, 0, plugin_contexts
, PLA_ARRAY_COUNT
);
322 case FIRE_INCREASE_MULT
:
326 case FIRE_DECREASE_MULT
:
331 case FIRE_SWITCH_FLAMES_TYPE
:
332 fire
.flames_type
= (fire
.flames_type
+ 1) % 2;
335 case FIRE_SWITCH_FLAMES_MOVING
:
336 fire
.moving
= !fire
.moving
;
340 if (rb
->default_event_handler_ex(action
, cleanup
, NULL
)
341 == SYS_USB_CONNECTED
)
342 return PLUGIN_USB_CONNECTED
;
347 /*************************** Plugin entry point ****************************/
349 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
353 rb
= api
; //copy to global api pointer
356 rb
->lcd_set_backdrop(NULL
);
358 /* Turn off backlight timeout */
359 backlight_force_on(rb
); /* backlight control in lib/helper.c */
366 #endif /* #ifdef HAVE_LCD_BITMAP */