Reverting parts of r19760 that was mistakenly committed.
[kugel-rb.git] / apps / plugins / matrix.c
blob986eb72e48d5b29df2265d4dde6633c1d6e299f2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 1999 Chris Allegretta
11 * Copyright (C) 2005 Alastair S - ported to podzilla
12 * Copyright (C) 2005 Jonas Häggqvist - ported to rockbox
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
26 * TODO:
27 * - The font is a bit large, create smaller one
28 * - For colour/greyscale displays, the font from the xscreensaver xmatrix
29 * should be converted and used
30 * BUGS:
31 * - The animation "dies" after a few seconds, not sure why. Works in sim.
32 * Symtom Fixed Oct 2007 GRaTT (Gerritt Gonzales)
36 #include "plugin.h"
37 PLUGIN_HEADER
39 /* Images */
40 #define MAXCHARS 27 - 1
41 extern const fb_data matrix_bold[];
42 extern const fb_data matrix_normal[];
43 #define COL_W 14
44 #define COL_H 15
46 #define COLS LCD_WIDTH/COL_W
47 #define ROWS LCD_HEIGHT/COL_H
49 #define LEFTMARGIN (LCD_WIDTH-(COLS*COL_W))/2
50 #define TOPMARGIN (LCD_HEIGHT-(ROWS*COL_H))/2
52 /* FIXME: could use plugin lib actions */
53 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
54 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
55 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
56 #define MATRIX_EXIT BUTTON_MENU
57 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
58 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
59 #define MATRIX_PAUSE BUTTON_PLAY
60 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
61 (CONFIG_KEYPAD == IRIVER_H300_PAD)
62 #define MATRIX_EXIT BUTTON_OFF
63 #define MATRIX_SLEEP_MORE BUTTON_UP
64 #define MATRIX_SLEEP_LESS BUTTON_DOWN
65 #define MATRIX_PAUSE BUTTON_SELECT
66 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
67 #define MATRIX_EXIT BUTTON_POWER
68 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_UP|BUTTON_REPEAT
69 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_DOWN|BUTTON_REPEAT
70 #define MATRIX_PAUSE BUTTON_PLAY
71 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
72 #define MATRIX_EXIT BUTTON_POWER
73 #define MATRIX_SLEEP_MORE BUTTON_UP
74 #define MATRIX_SLEEP_LESS BUTTON_DOWN
75 #define MATRIX_PAUSE BUTTON_PLAY
76 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
77 #define MATRIX_EXIT BUTTON_POWER
78 #define MATRIX_SLEEP_MORE BUTTON_UP
79 #define MATRIX_SLEEP_LESS BUTTON_DOWN
80 #define MATRIX_PAUSE BUTTON_SELECT
81 #elif CONFIG_KEYPAD == SANSA_E200_PAD
82 #define MATRIX_EXIT BUTTON_POWER
83 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
84 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
85 #define MATRIX_PAUSE BUTTON_SELECT
86 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
87 #define MATRIX_EXIT BUTTON_DOWN
88 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
89 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
90 #define MATRIX_PAUSE BUTTON_SELECT
91 #elif CONFIG_KEYPAD == SANSA_C200_PAD
92 #define MATRIX_EXIT BUTTON_POWER
93 #define MATRIX_SLEEP_MORE BUTTON_UP
94 #define MATRIX_SLEEP_LESS BUTTON_DOWN
95 #define MATRIX_PAUSE BUTTON_SELECT
96 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
97 #define MATRIX_EXIT BUTTON_BACK
98 #define MATRIX_SLEEP_MORE BUTTON_UP
99 #define MATRIX_SLEEP_LESS BUTTON_DOWN
100 #define MATRIX_PAUSE BUTTON_SELECT
101 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
102 #define MATRIX_EXIT BUTTON_RC_REC
103 #define MATRIX_SLEEP_MORE BUTTON_RC_VOL_UP
104 #define MATRIX_SLEEP_LESS BUTTON_RC_VOL_DOWN
105 #define MATRIX_PAUSE BUTTON_RC_PLAY
106 #elif (CONFIG_KEYPAD == COWOND2_PAD)
107 #define MATRIX_EXIT BUTTON_POWER
108 #elif CONFIG_KEYPAD == IAUDIO67_PAD
109 #define MATRIX_EXIT BUTTON_POWER
110 #define MATRIX_SLEEP_MORE BUTTON_VOLUP
111 #define MATRIX_SLEEP_LESS BUTTON_VOLDOWN
112 #define MATRIX_PAUSE BUTTON_PLAY
113 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
114 #define MATRIX_EXIT BUTTON_BACK
115 #define MATRIX_SLEEP_MORE BUTTON_UP
116 #define MATRIX_SLEEP_LESS BUTTON_DOWN
117 #define MATRIX_PAUSE BUTTON_PLAY
118 #else
119 #error Unsupported keypad
120 #endif
122 #ifdef HAVE_TOUCHSCREEN
123 #ifndef MATRIX_EXIT
124 #define MATRIX_EXIT BUTTON_TOPLEFT
125 #endif
126 #ifndef MATRIX_SLEEP_MORE
127 #define MATRIX_SLEEP_MORE BUTTON_MIDRIGHT
128 #endif
129 #ifndef MATRIX_SLEEP_LESS
130 #define MATRIX_SLEEP_LESS BUTTON_MIDLEFT
131 #endif
132 #ifndef MATRIX_PAUSE
133 #define MATRIX_PAUSE BUTTON_CENTER
134 #endif
135 #endif
137 #define SLEEP HZ/50
139 /* Codec api pointer */
140 static const struct plugin_api* rb;
142 /* Each position is of this type */
143 typedef struct cmatrix {
144 int val;
145 int bold;
146 } cmatrix;
148 /* The matrix - who'd have guessed it was just a few hundred bytes? */
149 static cmatrix matrix[ROWS][COLS];
150 static int length[COLS];
151 static int spaces[COLS];
152 static int updates[COLS];
154 static void matrix_init(void) {
155 int i,j;
157 /* Seed rand */
158 rb->srand(*rb->current_tick);
160 /* Make the matrix */
161 for (i = 0; i <= ROWS; i++) {
162 for (j = 0; j <= COLS - 1; j++ ) {
163 matrix[i][j].val = -1;
164 matrix[i][j].bold = 0;
168 for (j = 0; j <= COLS - 1; j++) {
169 /* Set up spaces[] array of how many spaces to skip */
170 spaces[j] = rb->rand() % ROWS + 1;
172 /* And length of the stream */
173 length[j] = rb->rand() % (ROWS - 3) + 3;
175 /* Sentinel value for creation of new objects */
176 matrix[1][j].val = 129;
178 /* And set updates[] array for update speed. */
179 updates[j] = rb->rand() % 3 + 1;
183 static void matrix_blit_char(const int row, const int col, int cha)
185 if (cha == 129 || cha == 2 || cha > MAXCHARS)
186 cha = 0;
188 if (matrix[row][col].bold == 1) {
189 rb->lcd_bitmap_part(matrix_bold, cha*COL_W, 0, 392,
190 col*COL_W + LEFTMARGIN, row*COL_H + TOPMARGIN, COL_W, COL_H);
192 else {
193 rb->lcd_bitmap_part(matrix_normal, cha*COL_W, 0, 392,
194 col*COL_W + LEFTMARGIN, row*COL_H + TOPMARGIN, COL_W, COL_H);
198 static void matrix_loop(void)
200 int i, j = 0, y, z, firstcoldone = 0;
201 static int count = 0;
202 int randomness = 6;
204 count++;
205 if (count > 4)
206 count = 1;
208 for (j = 0; j <= COLS - 1; j++) {
209 if (count > updates[j]) {
210 /* New style scrolling */
211 if (matrix[0][j].val == -1 && matrix[1][j].val == 129
212 && spaces[j] > 0) {
213 matrix[0][j].val = -1;
214 spaces[j]--;
215 } else if (matrix[0][j].val == -1 && matrix[1][j].val == 129){
216 length[j] = rb->rand() % (ROWS - 3) + 3;
217 matrix[0][j].val = rb->rand() % (MAXCHARS-1) + 1;
218 if (rb->rand() % 2 == 1)
219 matrix[0][j].bold = 2;
220 spaces[j] = rb->rand() % ROWS + 1;
222 i = 0;
223 y = 0;
224 firstcoldone = 0;
225 while (i <= ROWS) {
226 /* Skip over spaces */
227 /* this is whear the characters were disappearing */
229 while (i <= ROWS && (matrix[i][j].val == 129 ||
230 matrix[i][j].val == -1))
231 i++;
233 /* A little more random now for spaces */
234 if (rb->rand() % randomness == 1){
235 while (i <= ROWS && (matrix[i][j].val == 129 ||
236 matrix[i][j].val == -1)){
237 i++;
238 randomness--;
239 if(randomness <=1)
240 randomness = 6;}
241 }else{
242 randomness++;
243 if(randomness >6)
244 randomness = 6;
248 if (i > ROWS)
249 break;
251 /* Go to the head of this collumn */
252 z = i;
253 y = 0;
254 while (i <= ROWS && (matrix[i][j].val != 129 &&
255 matrix[i][j].val != -1)) {
256 i++;
257 y++;
260 if (i > ROWS) {
261 matrix[z][j].val = 129;
262 matrix[ROWS][j].bold = 1;
263 matrix_blit_char(z - 1, j, matrix[z][j].val);
264 continue;
267 matrix[i][j].val = rb->rand() % (MAXCHARS-1) + 1;
269 if (matrix[i - 1][j].bold == 2) {
270 matrix[i - 1][j].bold = 1;
271 matrix[i][j].bold = 2;
274 /* If we're at the top of the collumn and it's reached its
275 * full length (about to start moving down), we do this
276 * to get it moving. This is also how we keep segments
277 * not already growing from growing accidentally =>
279 if (y > length[j] || firstcoldone) {
280 matrix[z][j].val = 129;
281 matrix[0][j].val = -1;
283 firstcoldone = 1;
284 i++;
286 for (i = 1; i <= ROWS; i++) {
287 if (matrix[i][j].val == 0 || matrix[i][j].bold == 2) {
288 if (matrix[i][j].val == 0)
289 matrix_blit_char(i - 1, j, 20);
290 else
291 matrix_blit_char(i - 1, j, matrix[i][j].val);
292 } else {
293 if (matrix[i][j].val == 1)
294 matrix_blit_char(i - 1, j, 2);
295 else if (matrix[i][j].val == -1)
296 matrix_blit_char(i - 1, j, 129);
297 else
298 matrix_blit_char(i - 1, j, matrix[i][j].val);
305 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter) {
306 int button;
307 int sleep = SLEEP;
308 bool frozen = false;
310 (void)parameter;
311 rb = api;
313 rb->lcd_set_background(LCD_BLACK);
314 rb->lcd_set_backdrop(NULL);
315 rb->lcd_clear_display();
316 matrix_init();
318 while (1) {
319 if (!frozen) {
320 matrix_loop();
321 rb->lcd_update();
322 rb->sleep(sleep);
324 button = rb->button_get(frozen);
325 switch(button) {
326 case MATRIX_PAUSE:
327 frozen = !frozen;
328 break;
329 case MATRIX_EXIT:
330 return PLUGIN_OK;
331 break;
332 case MATRIX_SLEEP_MORE:
333 /* Sleep longer */
334 sleep += SLEEP;
335 break;
336 case MATRIX_SLEEP_LESS:
337 /* Sleep less */
338 sleep -= SLEEP;
339 if (sleep < 0) sleep = 0;
340 break;
341 default:
342 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) {
343 return PLUGIN_USB_CONNECTED;
345 break;
348 return PLUGIN_OK;