A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * LCD scrolling thread and scheduler
13 *
14 * Much collected and combined from the various Rockbox LCD drivers.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
20 *
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
23 *
24 ****************************************************************************/
25
26#include <stdio.h>
27#include "config.h"
28#include "gcc_extensions.h"
29#include "cpu.h"
30#include "kernel.h"
31#include "thread.h"
32#include "usb.h"
33#include "lcd.h"
34#include "font.h"
35#if !defined(BOOTLOADER)
36#include "misc.h"
37#include "settings.h"
38#endif
39#ifdef HAVE_REMOTE_LCD
40#include "lcd-remote.h"
41#endif
42#include "scroll_engine.h"
43
44#if !defined(BOOTLOADER)
45static const char scroll_tick_table[18] = {
46 /* Hz values [f(x)=100.8/(x+.048)]:
47 1, 1.25, 1.55, 2, 2.5, 3.12, 4, 5, 6.25, 8.33, 10, 12.5, 16.7, 20, 25, 33, 49.2, 96.2 */
48 100, 80, 64, 50, 40, 32, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 1
49};
50#endif
51
52#include "drivers/lcd-scroll.c"
53
54#ifdef HAVE_REMOTE_LCD
55/* copied from lcd-remote-1bit.c */
56/* Compile 1 bit vertical packing LCD driver for remote LCD */
57#undef LCDFN
58#define LCDFN(fn) lcd_remote_ ## fn
59#undef LCDM
60#define LCDM(ma) LCD_REMOTE_ ## ma
61
62#include "drivers/lcd-scroll.c"
63#endif /* HAVE_REMOTE_LCD */
64
65#if defined(HAVE_REMOTE_LCD) && !defined(BOOTLOADER)
66static struct event_queue scroll_queue SHAREDBSS_ATTR;
67
68static void sync_display_ticks(void)
69{
70 lcd_scroll_info.last_scroll =
71 lcd_remote_scroll_info.last_scroll = current_tick;
72}
73
74static bool scroll_process_message(int delay)
75{
76 struct queue_event ev;
77
78 /* just poll once for negative delays */
79 if (delay < 0)
80 delay = TIMEOUT_NOBLOCK;
81
82 do
83 {
84 long tick = current_tick;
85 queue_wait_w_tmo(&scroll_queue, &ev, delay);
86
87 switch (ev.id)
88 {
89 case SYS_TIMEOUT:
90 return false;
91 case SYS_USB_CONNECTED:
92 usb_acknowledge(SYS_USB_CONNECTED_ACK);
93 usb_wait_for_disconnect(&scroll_queue);
94 sync_display_ticks();
95 return true;
96#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
97 case SYS_REMOTE_PLUGGED:
98 if (!remote_initialized)
99 sync_display_ticks();
100#endif
101 }
102
103 delay -= current_tick - tick;
104 }
105 while (delay > 0);
106
107 return false;
108}
109#endif /* HAVE_REMOTE_LCD && !BOOTLOADER */
110
111#if !defined(BOOTLOADER)
112static void scroll_thread(void);
113static const char scroll_name[] = "scroll";
114static void scroll_thread(void) NORETURN_ATTR;
115
116#ifdef HAVE_REMOTE_LCD
117static void scroll_thread(void)
118{
119 enum
120 {
121 SCROLL_LCD = 0x1,
122 SCROLL_LCD_REMOTE = 0x2,
123 };
124
125 sync_display_ticks();
126
127 while ( 1 )
128 {
129 long delay;
130 int scroll;
131 long tick_lcd, tick_remote;
132
133 tick_lcd = lcd_scroll_info.last_scroll + lcd_scroll_info.ticks;
134 delay = current_tick;
135
136 if (
137#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
138 !remote_initialized ||
139#endif
140 (tick_remote = lcd_remote_scroll_info.last_scroll +
141 lcd_remote_scroll_info.ticks,
142 TIME_BEFORE(tick_lcd, tick_remote)))
143 {
144 scroll = SCROLL_LCD;
145 delay = tick_lcd - delay;
146 }
147 /* TIME_BEFORE(tick_remote, tick_lcd) */
148 else if (tick_lcd != tick_remote)
149 {
150 scroll = SCROLL_LCD_REMOTE;
151 delay = tick_remote - delay;
152 }
153 else
154 {
155 scroll = SCROLL_LCD | SCROLL_LCD_REMOTE;
156 delay = tick_lcd - delay;
157 }
158
159 if (scroll_process_message(delay))
160 continue;
161
162 if (scroll & SCROLL_LCD)
163 {
164#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
165 if (lcd_active())
166#endif
167 lcd_scroll_worker();
168 lcd_scroll_info.last_scroll = current_tick;
169 }
170
171 if (scroll == (SCROLL_LCD | SCROLL_LCD_REMOTE))
172 yield();
173
174 if (scroll & SCROLL_LCD_REMOTE)
175 {
176 lcd_remote_scroll_worker();
177 lcd_remote_scroll_info.last_scroll = current_tick;
178 }
179 }
180}
181#else /* !HAVE_REMOTE_LCD */
182static void scroll_thread(void)
183{
184 while (1)
185 {
186 sleep(lcd_scroll_info.ticks);
187#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
188 if (lcd_active())
189#endif
190 lcd_scroll_worker();
191 }
192}
193#endif /* !HAVE_REMOTE_LCD */
194
195void scroll_init(void)
196{
197 static long scroll_stack[(DEFAULT_STACK_SIZE*3)/sizeof(long)];
198#ifdef HAVE_REMOTE_LCD
199 queue_init(&scroll_queue, true);
200#endif
201 create_thread(scroll_thread, scroll_stack,
202 sizeof(scroll_stack), 0, scroll_name
203 IF_PRIO(, PRIORITY_USER_INTERFACE)
204 IF_COP(, CPU));
205}
206#else /* BOOTLOADER */
207void scroll_init(void)
208{
209 /* DUMMY */
210}
211#endif /* BOOTLOADER*/