1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
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
31 * - The animation "dies" after a few seconds, not sure why. Works in sim.
32 * Symtom Fixed Oct 2007 GRaTT (Gerritt Gonzales)
40 #include "pluginbitmaps/matrix_bold.h"
41 #include "pluginbitmaps/matrix_normal.h"
42 #define MAXCHARS 27 - 1
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 #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \
53 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
54 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
55 #define MATRIX_EXIT BUTTON_MENU
56 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
57 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
58 #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
67 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
68 #define MATRIX_EXIT BUTTON_POWER
69 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_UP|BUTTON_REPEAT
70 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_DOWN|BUTTON_REPEAT
71 #define MATRIX_PAUSE BUTTON_PLAY
73 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
74 #define MATRIX_EXIT BUTTON_POWER
75 #define MATRIX_SLEEP_MORE BUTTON_UP
76 #define MATRIX_SLEEP_LESS BUTTON_DOWN
77 #define MATRIX_PAUSE BUTTON_PLAY
79 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
80 #define MATRIX_EXIT BUTTON_POWER
81 #define MATRIX_SLEEP_MORE BUTTON_UP
82 #define MATRIX_SLEEP_LESS BUTTON_DOWN
83 #define MATRIX_PAUSE BUTTON_SELECT
85 #elif CONFIG_KEYPAD == SANSA_E200_PAD
86 #define MATRIX_EXIT BUTTON_POWER
87 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
88 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
89 #define MATRIX_PAUSE BUTTON_SELECT
91 #elif CONFIG_KEYPAD == SANSA_FUZE_PAD
92 #define MATRIX_EXIT (BUTTON_HOME|BUTTON_REPEAT)
93 #define MATRIX_SLEEP_MORE BUTTON_SCROLL_BACK|BUTTON_REPEAT
94 #define MATRIX_SLEEP_LESS BUTTON_SCROLL_FWD|BUTTON_REPEAT
95 #define MATRIX_PAUSE BUTTON_SELECT
97 #elif CONFIG_KEYPAD == SANSA_C200_PAD
98 #define MATRIX_EXIT BUTTON_POWER
99 #define MATRIX_SLEEP_MORE BUTTON_UP
100 #define MATRIX_SLEEP_LESS BUTTON_DOWN
101 #define MATRIX_PAUSE BUTTON_SELECT
103 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
104 #define MATRIX_EXIT BUTTON_BACK
105 #define MATRIX_SLEEP_MORE BUTTON_UP
106 #define MATRIX_SLEEP_LESS BUTTON_DOWN
107 #define MATRIX_PAUSE BUTTON_SELECT
109 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
110 #define MATRIX_EXIT BUTTON_RC_REC
111 #define MATRIX_SLEEP_MORE BUTTON_RC_VOL_UP
112 #define MATRIX_SLEEP_LESS BUTTON_RC_VOL_DOWN
113 #define MATRIX_PAUSE BUTTON_RC_PLAY
115 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
116 #define MATRIX_EXIT BUTTON_POWER
118 #elif CONFIG_KEYPAD == IAUDIO67_PAD
119 #define MATRIX_EXIT BUTTON_POWER
120 #define MATRIX_SLEEP_MORE BUTTON_VOLUP
121 #define MATRIX_SLEEP_LESS BUTTON_VOLDOWN
122 #define MATRIX_PAUSE BUTTON_PLAY
124 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
125 #define MATRIX_EXIT BUTTON_BACK
126 #define MATRIX_SLEEP_MORE BUTTON_UP
127 #define MATRIX_SLEEP_LESS BUTTON_DOWN
128 #define MATRIX_PAUSE BUTTON_PLAY
130 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
131 #define MATRIX_EXIT BUTTON_POWER
132 #define MATRIX_SLEEP_MORE BUTTON_UP
133 #define MATRIX_SLEEP_LESS BUTTON_DOWN
134 #define MATRIX_PAUSE BUTTON_SELECT
136 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
137 #define MATRIX_EXIT BUTTON_POWER
138 #define MATRIX_SLEEP_MORE BUTTON_UP
139 #define MATRIX_SLEEP_LESS BUTTON_DOWN
140 #define MATRIX_PAUSE BUTTON_PLAY
142 #elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \
143 CONFIG_KEYPAD == ONDAVX777_PAD || \
144 CONFIG_KEYPAD == MROBE500_PAD
145 #define MATRIX_EXIT BUTTON_POWER
147 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
148 #define MATRIX_EXIT BUTTON_REC
149 #define MATRIX_SLEEP_MORE BUTTON_UP
150 #define MATRIX_SLEEP_LESS BUTTON_DOWN
151 #define MATRIX_PAUSE BUTTON_PLAY
153 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
154 #define MATRIX_EXIT BUTTON_REC
155 #define MATRIX_SLEEP_MORE BUTTON_PREV
156 #define MATRIX_SLEEP_LESS BUTTON_NEXT
157 #define MATRIX_PAUSE BUTTON_PLAY
159 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
160 #define MATRIX_EXIT (BUTTON_REC|BUTTON_PLAY)
161 #define MATRIX_SLEEP_MORE BUTTON_VOL_UP
162 #define MATRIX_SLEEP_LESS BUTTON_VOL_DOWN
163 #define MATRIX_PAUSE BUTTON_PLAY
166 #error Unsupported keypad
169 #ifdef HAVE_TOUCHSCREEN
171 #define MATRIX_EXIT BUTTON_TOPLEFT
173 #ifndef MATRIX_SLEEP_MORE
174 #define MATRIX_SLEEP_MORE BUTTON_MIDRIGHT
176 #ifndef MATRIX_SLEEP_LESS
177 #define MATRIX_SLEEP_LESS BUTTON_MIDLEFT
180 #define MATRIX_PAUSE BUTTON_CENTER
186 /* Each position is of this type */
187 typedef struct cmatrix
{
192 /* The matrix - who'd have guessed it was just a few hundred bytes? */
193 static cmatrix matrix
[ROWS
][COLS
];
194 static int length
[COLS
];
195 static int spaces
[COLS
];
196 static int updates
[COLS
];
198 static void matrix_init(void) {
202 rb
->srand(*rb
->current_tick
);
204 /* Make the matrix */
205 for (i
= 0; i
<= ROWS
; i
++) {
206 for (j
= 0; j
<= COLS
- 1; j
++ ) {
207 matrix
[i
][j
].val
= -1;
208 matrix
[i
][j
].bold
= 0;
212 for (j
= 0; j
<= COLS
- 1; j
++) {
213 /* Set up spaces[] array of how many spaces to skip */
214 spaces
[j
] = rb
->rand() % ROWS
+ 1;
216 /* And length of the stream */
217 length
[j
] = rb
->rand() % (ROWS
- 3) + 3;
219 /* Sentinel value for creation of new objects */
220 matrix
[1][j
].val
= 129;
222 /* And set updates[] array for update speed. */
223 updates
[j
] = rb
->rand() % 3 + 1;
227 static void matrix_blit_char(const int row
, const int col
, int cha
)
229 if (cha
== 129 || cha
== 2 || cha
> MAXCHARS
)
232 if (matrix
[row
][col
].bold
== 1) {
233 rb
->lcd_bitmap_part(matrix_bold
, cha
*COL_W
, 0,
235 BMPWIDTH_matrix_bold
, BMPHEIGHT_matrix_bold
),
236 col
*COL_W
+ LEFTMARGIN
, row
*COL_H
+ TOPMARGIN
, COL_W
, COL_H
);
239 rb
->lcd_bitmap_part(matrix_normal
, cha
*COL_W
, 0,
241 BMPWIDTH_matrix_normal
, BMPHEIGHT_matrix_normal
),
242 col
*COL_W
+ LEFTMARGIN
, row
*COL_H
+ TOPMARGIN
, COL_W
, COL_H
);
246 static void matrix_loop(void)
248 int i
, j
= 0, y
, z
, firstcoldone
= 0;
249 static int count
= 0;
256 for (j
= 0; j
<= COLS
- 1; j
++) {
257 if (count
> updates
[j
]) {
258 /* New style scrolling */
259 if (matrix
[0][j
].val
== -1 && matrix
[1][j
].val
== 129
261 matrix
[0][j
].val
= -1;
263 } else if (matrix
[0][j
].val
== -1 && matrix
[1][j
].val
== 129){
264 length
[j
] = rb
->rand() % (ROWS
- 3) + 3;
265 matrix
[0][j
].val
= rb
->rand() % (MAXCHARS
-1) + 1;
266 if (rb
->rand() % 2 == 1)
267 matrix
[0][j
].bold
= 2;
268 spaces
[j
] = rb
->rand() % ROWS
+ 1;
274 /* Skip over spaces */
275 /* this is whear the characters were disappearing */
277 while (i <= ROWS && (matrix[i][j].val == 129 ||
278 matrix[i][j].val == -1))
281 /* A little more random now for spaces */
282 if (rb
->rand() % randomness
== 1){
283 while (i
<= ROWS
&& (matrix
[i
][j
].val
== 129 ||
284 matrix
[i
][j
].val
== -1)){
299 /* Go to the head of this collumn */
302 while (i
<= ROWS
&& (matrix
[i
][j
].val
!= 129 &&
303 matrix
[i
][j
].val
!= -1)) {
309 matrix
[z
][j
].val
= 129;
310 matrix
[ROWS
- 1][j
].bold
= 1;
311 matrix_blit_char(z
- 1, j
, matrix
[z
][j
].val
);
315 matrix
[i
][j
].val
= rb
->rand() % (MAXCHARS
-1) + 1;
317 if (matrix
[i
- 1][j
].bold
== 2) {
318 matrix
[i
- 1][j
].bold
= 1;
319 matrix
[i
][j
].bold
= 2;
322 /* If we're at the top of the collumn and it's reached its
323 * full length (about to start moving down), we do this
324 * to get it moving. This is also how we keep segments
325 * not already growing from growing accidentally =>
327 if (y
> length
[j
] || firstcoldone
) {
328 matrix
[z
][j
].val
= 129;
329 matrix
[0][j
].val
= -1;
334 for (i
= 1; i
<= ROWS
; i
++) {
335 if (matrix
[i
][j
].val
== 0 || matrix
[i
][j
].bold
== 2) {
336 if (matrix
[i
][j
].val
== 0)
337 matrix_blit_char(i
- 1, j
, 20);
339 matrix_blit_char(i
- 1, j
, matrix
[i
][j
].val
);
341 if (matrix
[i
][j
].val
== 1)
342 matrix_blit_char(i
- 1, j
, 2);
343 else if (matrix
[i
][j
].val
== -1)
344 matrix_blit_char(i
- 1, j
, 129);
346 matrix_blit_char(i
- 1, j
, matrix
[i
][j
].val
);
353 enum plugin_status
plugin_start(const void* parameter
) {
360 rb
->lcd_set_background(LCD_BLACK
);
361 rb
->lcd_set_backdrop(NULL
);
362 rb
->lcd_clear_display();
371 button
= rb
->button_get(frozen
);
379 case MATRIX_SLEEP_MORE
:
383 case MATRIX_SLEEP_LESS
:
386 if (sleep
< 0) sleep
= 0;
389 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
390 return PLUGIN_USB_CONNECTED
;