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)
37 #include "lib/pluginlib_actions.h"
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 /* this set the context to use with PLA */
53 static const struct button_mapping
*plugin_contexts
[] = { pla_main_ctx
};
55 #ifdef HAVE_SCROLLWHEEL
56 #define MATRIX_SLEEP_MORE PLA_SCROLL_BACK
57 #define MATRIX_SLEEP_MORE_REPEAT PLA_SCROLL_BACK_REPEAT
58 #define MATRIX_SLEEP_LESS PLA_SCROLL_FWD
59 #define MATRIX_SLEEP_LESS_REPEAT PLA_SCROLL_FWD_REPEAT
61 #define MATRIX_SLEEP_MORE PLA_UP
62 #define MATRIX_SLEEP_MORE_REPEAT PLA_UP_REPEAT
63 #define MATRIX_SLEEP_LESS PLA_DOWN
64 #define MATRIX_SLEEP_LESS_REPEAT PLA_DOWN_REPEAT
65 #endif /* HAVE_SCROLLWHEEL */
66 #define MATRIX_PAUSE PLA_SELECT
67 #define MATRIX_EXIT PLA_EXIT
68 #define MATRIX_EXIT2 PLA_CANCEL
72 /* Each position is of this type */
73 typedef struct cmatrix
{
78 /* The matrix - who'd have guessed it was just a few hundred bytes? */
79 static cmatrix matrix
[ROWS
][COLS
];
80 static int length
[COLS
];
81 static int spaces
[COLS
];
82 static int updates
[COLS
];
84 static void matrix_init(void) {
88 rb
->srand(*rb
->current_tick
);
91 for (i
= 0; i
< ROWS
; i
++) {
92 for (j
= 0; j
< COLS
; j
++) {
93 matrix
[i
][j
].val
= -1;
94 matrix
[i
][j
].bold
= 0;
98 for (j
= 0; j
< COLS
; j
++) {
99 /* Set up spaces[] array of how many spaces to skip */
100 spaces
[j
] = rb
->rand() % ROWS
+ 1;
102 /* And length of the stream */
103 length
[j
] = rb
->rand() % (ROWS
- 3) + 3;
105 /* Sentinel value for creation of new objects */
106 matrix
[1][j
].val
= 129;
108 /* And set updates[] array for update speed. */
109 updates
[j
] = rb
->rand() % 3 + 1;
113 static void matrix_blit_char(const int row
, const int col
, int cha
)
115 if (cha
== 129 || cha
== 2 || cha
> MAXCHARS
)
118 if (matrix
[row
][col
].bold
== 1) {
119 rb
->lcd_bitmap_part(matrix_bold
, cha
*COL_W
, 0,
121 BMPWIDTH_matrix_bold
, BMPHEIGHT_matrix_bold
),
122 col
*COL_W
+ LEFTMARGIN
, row
*COL_H
+ TOPMARGIN
, COL_W
, COL_H
);
125 rb
->lcd_bitmap_part(matrix_normal
, cha
*COL_W
, 0,
127 BMPWIDTH_matrix_normal
, BMPHEIGHT_matrix_normal
),
128 col
*COL_W
+ LEFTMARGIN
, row
*COL_H
+ TOPMARGIN
, COL_W
, COL_H
);
132 static void matrix_loop(void)
134 int i
, j
= 0, y
, z
, firstcoldone
= 0;
135 static int count
= 0;
142 for (j
= 0; j
< COLS
; j
++) {
143 if (count
> updates
[j
]) {
144 /* New style scrolling */
145 if (matrix
[0][j
].val
== -1 && matrix
[1][j
].val
== 129
147 matrix
[0][j
].val
= -1;
149 } else if (matrix
[0][j
].val
== -1 && matrix
[1][j
].val
== 129){
150 length
[j
] = rb
->rand() % (ROWS
- 3) + 3;
151 matrix
[0][j
].val
= rb
->rand() % (MAXCHARS
-1) + 1;
152 if (rb
->rand() % 2 == 1)
153 matrix
[0][j
].bold
= 2;
154 spaces
[j
] = rb
->rand() % ROWS
+ 1;
160 /* Skip over spaces */
161 /* this is whear the characters were disappearing */
163 while (i <= ROWS && (matrix[i][j].val == 129 ||
164 matrix[i][j].val == -1))
167 /* A little more random now for spaces */
168 if (rb
->rand() % randomness
== 1){
169 while (i
<= ROWS
&& (matrix
[i
][j
].val
== 129 ||
170 matrix
[i
][j
].val
== -1)){
185 /* Go to the head of this collumn */
188 while (i
<= ROWS
&& (matrix
[i
][j
].val
!= 129 &&
189 matrix
[i
][j
].val
!= -1)) {
195 matrix
[z
][j
].val
= 129;
196 matrix
[ROWS
- 1][j
].bold
= 1;
197 matrix_blit_char(z
- 1, j
, matrix
[z
][j
].val
);
201 matrix
[i
][j
].val
= rb
->rand() % (MAXCHARS
-1) + 1;
203 if (matrix
[i
- 1][j
].bold
== 2) {
204 matrix
[i
- 1][j
].bold
= 1;
205 matrix
[i
][j
].bold
= 2;
208 /* If we're at the top of the collumn and it's reached its
209 * full length (about to start moving down), we do this
210 * to get it moving. This is also how we keep segments
211 * not already growing from growing accidentally =>
213 if (y
> length
[j
] || firstcoldone
) {
214 matrix
[z
][j
].val
= 129;
215 matrix
[0][j
].val
= -1;
220 for (i
= 1; i
< ROWS
; i
++) {
221 if (matrix
[i
][j
].val
== 0 || matrix
[i
][j
].bold
== 2) {
222 if (matrix
[i
][j
].val
== 0)
223 matrix_blit_char(i
- 1, j
, 20);
225 matrix_blit_char(i
- 1, j
, matrix
[i
][j
].val
);
227 if (matrix
[i
][j
].val
== 1)
228 matrix_blit_char(i
- 1, j
, 2);
229 else if (matrix
[i
][j
].val
== -1)
230 matrix_blit_char(i
- 1, j
, 129);
232 matrix_blit_char(i
- 1, j
, matrix
[i
][j
].val
);
239 enum plugin_status
plugin_start(const void* parameter
) {
246 rb
->lcd_set_background(LCD_BLACK
);
247 rb
->lcd_set_backdrop(NULL
);
248 rb
->lcd_clear_display();
258 button
= pluginlib_getaction(frozen
? TIMEOUT_BLOCK
: TIMEOUT_NOBLOCK
,
259 plugin_contexts
, ARRAYLEN(plugin_contexts
));
269 case MATRIX_SLEEP_MORE
:
270 case MATRIX_SLEEP_MORE_REPEAT
:
274 case MATRIX_SLEEP_LESS
:
275 case MATRIX_SLEEP_LESS_REPEAT
:
278 if (sleep
< 0) sleep
= 0;
281 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
) {
282 return PLUGIN_USB_CONNECTED
;