1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by Michael Sevakis
12 * LCD scrolling driver and scheduler
14 * Much collected and combined from the various Rockbox LCD drivers.
16 * All files in this archive are subject to the GNU General Public License.
17 * See the file COPYING in the source tree root for full license agreement.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
30 #ifdef HAVE_REMOTE_LCD
31 #include "lcd-remote.h"
33 #include "scroll_engine.h"
35 static const char scroll_tick_table
[16] = {
37 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33 */
38 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3
41 static void scroll_thread(void);
42 static char scroll_stack
[DEFAULT_STACK_SIZE
*3];
43 static const char scroll_name
[] = "scroll";
45 struct scrollinfo lcd_scroll
[LCD_SCROLLABLE_LINES
];
47 #ifdef HAVE_REMOTE_LCD
48 struct scrollinfo lcd_remote_scroll
[LCD_REMOTE_SCROLLABLE_LINES
];
49 struct event_queue scroll_queue
;
52 struct scroll_screen_info lcd_scroll_info
=
59 #ifdef HAVE_LCD_BITMAP
62 #ifdef HAVE_LCD_CHARCELLS
63 .jump_scroll_delay
= HZ
/4,
68 #ifdef HAVE_REMOTE_LCD
69 struct scroll_screen_info lcd_remote_scroll_info
=
71 .scroll
= lcd_remote_scroll
,
78 #endif /* HAVE_REMOTE_LCD */
80 void lcd_stop_scroll(void)
82 lcd_scroll_info
.lines
= 0;
85 void lcd_scroll_speed(int speed
)
87 lcd_scroll_info
.ticks
= scroll_tick_table
[speed
];
90 #if defined(HAVE_LCD_BITMAP)
91 /* Reverse the invert setting of the scrolling line (if any) at given char
92 position. Setting will go into affect next time line scrolls. */
93 void lcd_invertscroll(int x
, int y
)
99 if((unsigned)y
>=LCD_SCROLLABLE_LINES
) return;
101 s
= &lcd_scroll_info
.scroll
[y
];
102 s
->invert
= !s
->invert
;
105 void lcd_scroll_step(int step
)
107 lcd_scroll_info
.step
= step
;
111 void lcd_scroll_delay(int ms
)
113 lcd_scroll_info
.delay
= ms
/ (HZ
/ 10);
116 void lcd_bidir_scroll(int percent
)
118 lcd_scroll_info
.bidir_limit
= percent
;
121 #ifdef HAVE_LCD_CHARCELLS
122 void lcd_jump_scroll(int mode
) /* 0=off, 1=once, ..., JUMP_SCROLL_ALWAYS */
124 lcd_scroll_info
.jump_scroll
= mode
;
127 void lcd_jump_scroll_delay(int ms
)
129 lcd_scroll_info
.jump_scroll_delay
= ms
/ (HZ
/ 10);
133 #ifdef HAVE_REMOTE_LCD
134 /* Reverse the invert setting of the scrolling line (if any) at given char
135 position. Setting will go into affect next time line scrolls. */
136 void lcd_remote_invertscroll(int x
, int y
)
138 struct scrollinfo
*s
;
142 if((unsigned)y
>=LCD_REMOTE_SCROLLABLE_LINES
) return;
144 s
= &lcd_remote_scroll_info
.scroll
[y
];
145 s
->invert
= !s
->invert
;
148 void lcd_remote_stop_scroll(void)
150 lcd_remote_scroll_info
.lines
= 0;
153 void lcd_remote_scroll_speed(int speed
)
155 lcd_remote_scroll_info
.ticks
= scroll_tick_table
[speed
];
158 void lcd_remote_scroll_step(int step
)
160 lcd_remote_scroll_info
.step
= step
;
163 void lcd_remote_scroll_delay(int ms
)
165 lcd_remote_scroll_info
.delay
= ms
/ (HZ
/ 10);
168 void lcd_remote_bidir_scroll(int percent
)
170 lcd_remote_scroll_info
.bidir_limit
= percent
;
173 static void sync_display_ticks(void)
175 lcd_scroll_info
.last_scroll
=
176 lcd_remote_scroll_info
.last_scroll
= current_tick
;
179 static bool scroll_process_message(int delay
)
185 long tick
= current_tick
;
186 queue_wait_w_tmo(&scroll_queue
, &ev
, delay
);
192 case SYS_USB_CONNECTED
:
193 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
194 usb_wait_for_disconnect(&scroll_queue
);
195 sync_display_ticks();
198 case SYS_REMOTE_PLUGGED
:
199 if (!remote_initialized
)
200 sync_display_ticks();
204 delay
-= current_tick
- tick
;
210 #endif /* HAVE_REMOTE_LCD */
212 static void scroll_thread(void) __attribute__((noreturn
));
213 #ifdef HAVE_REMOTE_LCD
215 static void scroll_thread(void)
220 SCROLL_LCD_REMOTE
= 0x2,
223 sync_display_ticks();
229 long tick_lcd
, tick_remote
;
231 tick_lcd
= lcd_scroll_info
.last_scroll
+ lcd_scroll_info
.ticks
;
232 delay
= current_tick
;
236 !remote_initialized
||
238 (tick_remote
= lcd_remote_scroll_info
.last_scroll
+
239 lcd_remote_scroll_info
.ticks
,
240 TIME_BEFORE(tick_lcd
, tick_remote
)))
243 delay
= tick_lcd
- delay
;
245 /* TIME_BEFORE(tick_remote, tick_lcd) */
246 else if (tick_lcd
!= tick_remote
)
248 scroll
= SCROLL_LCD_REMOTE
;
249 delay
= tick_remote
- delay
;
253 scroll
= SCROLL_LCD
| SCROLL_LCD_REMOTE
;
254 delay
= tick_lcd
- delay
;
257 if (scroll_process_message(delay
))
260 if (scroll
& SCROLL_LCD
)
262 #ifdef HAVE_LCD_ENABLE
266 lcd_scroll_info
.last_scroll
= current_tick
;
269 if (scroll
== (SCROLL_LCD
| SCROLL_LCD_REMOTE
))
272 if (scroll
& SCROLL_LCD_REMOTE
)
274 lcd_remote_scroll_fn();
275 lcd_remote_scroll_info
.last_scroll
= current_tick
;
280 static void scroll_thread(void)
284 sleep(lcd_scroll_info
.ticks
);
285 #ifdef HAVE_LCD_ENABLE
291 #endif /* HAVE_REMOTE_LCD */
293 void scroll_init(void)
295 #ifdef HAVE_REMOTE_LCD
296 queue_init(&scroll_queue
, true);
298 create_thread(scroll_thread
, scroll_stack
,
299 sizeof(scroll_stack
), scroll_name
300 IF_PRIO(, PRIORITY_USER_INTERFACE
)
301 IF_COP(, CPU
, false));