Implement the Sansa e200v2 manual. Please let me know about any errors/omissions.
[kugel-rb.git] / apps / main.c
blobc7510801d4ef7577c24989281c892a6dce7b082e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
23 #include "storage.h"
24 #include "disk.h"
25 #include "fat.h"
26 #include "lcd.h"
27 #include "rtc.h"
28 #include "debug.h"
29 #include "led.h"
30 #include "kernel.h"
31 #include "button.h"
32 #include "tree.h"
33 #include "filetypes.h"
34 #include "panic.h"
35 #include "menu.h"
36 #include "system.h"
37 #include "usb.h"
38 #include "powermgmt.h"
39 #include "adc.h"
40 #include "i2c.h"
41 #ifndef DEBUG
42 #include "serial.h"
43 #endif
44 #include "audio.h"
45 #include "mp3_playback.h"
46 #include "thread.h"
47 #include "settings.h"
48 #include "backlight.h"
49 #include "status.h"
50 #include "debug_menu.h"
51 #include "version.h"
52 #include "sprintf.h"
53 #include "font.h"
54 #include "language.h"
55 #include "wps.h"
56 #include "playlist.h"
57 #include "buffer.h"
58 #include "rolo.h"
59 #include "screens.h"
60 #include "power.h"
61 #include "talk.h"
62 #include "plugin.h"
63 #include "misc.h"
64 #include "dircache.h"
65 #ifdef HAVE_TAGCACHE
66 #include "tagcache.h"
67 #include "tagtree.h"
68 #endif
69 #include "lang.h"
70 #include "string.h"
71 #include "splash.h"
72 #include "eeprom_settings.h"
73 #include "scrobbler.h"
74 #include "icon.h"
75 #include "viewport.h"
77 #ifdef IPOD_ACCESSORY_PROTOCOL
78 #include "iap.h"
79 #endif
81 #if (CONFIG_CODEC == SWCODEC)
82 #include "playback.h"
83 #include "tdspeed.h"
84 #endif
85 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
86 #include "pcm_record.h"
87 #endif
89 #ifdef BUTTON_REC
90 #define SETTINGS_RESET BUTTON_REC
91 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
92 #define SETTINGS_RESET BUTTON_A
93 #endif
95 #if CONFIG_TUNER
96 #include "radio.h"
97 #endif
98 #if (CONFIG_STORAGE & STORAGE_MMC)
99 #include "ata_mmc.h"
100 #endif
102 #ifdef HAVE_REMOTE_LCD
103 #include "lcd-remote.h"
104 #endif
106 #if CONFIG_USBOTG == USBOTG_ISP1362
107 #include "isp1362.h"
108 #endif
110 #if CONFIG_USBOTG == USBOTG_M5636
111 #include "m5636.h"
112 #endif
114 #ifdef SIMULATOR
115 #include "sim_tasks.h"
116 #include "system-sdl.h"
117 #endif
119 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
121 const char appsversion[]=APPSVERSION;
123 static void init(void);
125 #ifdef SIMULATOR
126 void app_main(void)
127 #else
128 static void app_main(void)
129 #endif
131 int i;
132 init();
133 FOR_NB_SCREENS(i)
135 screens[i].clear_display();
136 screens[i].update();
138 #ifdef HAVE_LCD_BITMAP
139 list_init();
140 #endif
141 tree_gui_init();
142 gui_syncstatusbar_init(&statusbars);
143 viewportmanager_init();
144 #ifdef HAVE_USBSTACK
145 /* All threads should be created and public queues registered by now */
146 usb_start_monitoring();
147 #endif
149 #ifdef AUTOROCK
151 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
153 if(file_exists(filename)) /* no complaint if it doesn't exist */
155 plugin_load((char*)filename, NULL); /* start if it does */
158 #endif /* #ifdef AUTOROCK */
160 root_menu();
163 static int init_dircache(bool preinit)
165 #ifdef HAVE_DIRCACHE
166 int result = 0;
167 bool clear = false;
169 if (preinit)
170 dircache_init();
172 if (!global_settings.dircache)
173 return 0;
175 # ifdef HAVE_EEPROM_SETTINGS
176 if (firmware_settings.initialized && firmware_settings.disk_clean
177 && preinit)
179 result = dircache_load();
181 if (result < 0)
183 firmware_settings.disk_clean = false;
184 if (global_status.dircache_size <= 0)
186 /* This will be in default language, settings are not
187 applied yet. Not really any easy way to fix that. */
188 splash(0, str(LANG_SCANNING_DISK));
189 clear = true;
192 dircache_build(global_status.dircache_size);
195 else
196 # endif
198 if (preinit)
199 return -1;
201 if (!dircache_is_enabled()
202 && !dircache_is_initializing())
204 if (global_status.dircache_size <= 0)
206 splash(0, str(LANG_SCANNING_DISK));
207 clear = true;
209 result = dircache_build(global_status.dircache_size);
212 if (result < 0)
214 /* Initialization of dircache failed. Manual action is
215 * necessary to enable dircache again.
217 splashf(0, "Dircache failed, disabled. Result: %d", result);
218 global_settings.dircache = false;
222 if (clear)
224 backlight_on();
225 show_logo();
226 global_status.dircache_size = dircache_get_cache_size();
227 status_save();
230 return result;
231 #else
232 (void)preinit;
233 return 0;
234 #endif
237 #ifdef HAVE_TAGCACHE
238 static void init_tagcache(void)
240 bool clear = false;
242 tagcache_init();
244 while (!tagcache_is_initialized())
246 #ifdef HAVE_LCD_CHARCELLS
247 char buf[32];
248 #endif
249 int ret = tagcache_get_commit_step();
251 if (ret > 0)
253 #if CONFIG_CODEC == SWCODEC
254 /* hwcodec can't use voice here, as the database commit
255 * uses the audio buffer. */
256 static long talked_tick = 0;
257 if(global_settings.talk_menu
258 && (talked_tick == 0
259 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
261 talked_tick = current_tick;
262 talk_id(LANG_TAGCACHE_INIT, false);
263 talk_number(ret, true);
264 talk_id(VOICE_OF, true);
265 talk_number(tagcache_get_max_commit_step(), true);
267 #endif
268 #ifdef HAVE_LCD_BITMAP
269 splashf(0, "%s [%d/%d]",
270 str(LANG_TAGCACHE_INIT), ret,
271 tagcache_get_max_commit_step());
272 #else
273 lcd_double_height(false);
274 snprintf(buf, sizeof(buf), " DB [%d/%d]", ret,
275 tagcache_get_max_commit_step());
276 lcd_puts(0, 1, buf);
277 lcd_update();
278 #endif
279 clear = true;
281 sleep(HZ/4);
283 tagtree_init();
285 if (clear)
287 backlight_on();
288 show_logo();
291 #endif
293 #ifdef SIMULATOR
295 static void init(void)
297 kernel_init();
298 buffer_init();
299 enable_irq();
300 lcd_init();
301 #ifdef HAVE_REMOTE_LCD
302 lcd_remote_init();
303 #endif
304 font_init();
305 show_logo();
306 button_init();
307 backlight_init();
308 sim_tasks_init();
309 lang_init();
310 #ifdef DEBUG
311 debug_init();
312 #endif
313 storage_init();
314 settings_reset();
315 settings_load(SETTINGS_ALL);
316 gui_sync_wps_init();
317 settings_apply(true);
318 init_dircache(true);
319 init_dircache(false);
320 #ifdef HAVE_TAGCACHE
321 init_tagcache();
322 #endif
323 sleep(HZ/2);
324 tree_mem_init();
325 filetype_init();
326 playlist_init();
328 #if CONFIG_CODEC != SWCODEC
329 mp3_init( global_settings.volume,
330 global_settings.bass,
331 global_settings.treble,
332 global_settings.balance,
333 global_settings.loudness,
334 global_settings.avc,
335 global_settings.channel_config,
336 global_settings.stereo_width,
337 global_settings.mdb_strength,
338 global_settings.mdb_harmonics,
339 global_settings.mdb_center,
340 global_settings.mdb_shape,
341 global_settings.mdb_enable,
342 global_settings.superbass);
344 /* audio_init must to know the size of voice buffer so init voice first */
345 talk_init();
346 #endif /* CONFIG_CODEC != SWCODEC */
348 scrobbler_init();
349 #if CONFIG_CODEC == SWCODEC
350 tdspeed_init();
351 #endif /* CONFIG_CODEC == SWCODEC */
353 audio_init();
354 button_clear_queue(); /* Empty the keyboard buffer */
357 #else
359 static void init(void)
361 int rc;
362 bool mounted = false;
363 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
364 /* if nobody initialized ATA before, I consider this a cold start */
365 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
366 #endif
368 system_init();
369 kernel_init();
371 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
372 set_cpu_frequency(CPUFREQ_NORMAL);
373 #ifdef CPU_COLDFIRE
374 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
375 #endif
376 cpu_boost(true);
377 #endif
379 buffer_init();
381 settings_reset();
383 i2c_init();
385 power_init();
387 enable_irq();
388 #ifdef CPU_ARM
389 enable_fiq();
390 #endif
391 lcd_init();
392 #ifdef HAVE_REMOTE_LCD
393 lcd_remote_init();
394 #endif
395 font_init();
397 show_logo();
398 lang_init();
400 #ifdef DEBUG
401 debug_init();
402 #else
403 #ifdef HAVE_SERIAL
404 serial_setup();
405 #endif
406 #endif
408 #if CONFIG_RTC
409 rtc_init();
410 #endif
411 #ifdef HAVE_RTC_RAM
412 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
413 #endif
415 adc_init();
417 usb_init();
418 #if CONFIG_USBOTG == USBOTG_ISP1362
419 isp1362_init();
420 #elif CONFIG_USBOTG == USBOTG_M5636
421 m5636_init();
422 #endif
424 backlight_init();
426 button_init();
428 powermgmt_init();
430 #if CONFIG_TUNER
431 radio_init();
432 #endif
434 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
435 /* charger_inserted() can't be used here because power_thread()
436 hasn't checked power_input_status() yet */
437 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
438 && !global_settings.car_adapter_mode
439 #ifdef ATA_POWER_PLAYERSTYLE
440 && !ide_powered() /* relies on probing result from bootloader */
441 #endif
444 rc = charging_screen(); /* display a "charging" screen */
445 if (rc == 1) /* charger removed */
446 power_off();
447 /* "On" pressed or USB connected: proceed */
448 show_logo(); /* again, to provide better visual feedback */
450 #endif
452 rc = storage_init();
453 if(rc)
455 #ifdef HAVE_LCD_BITMAP
456 char str[32];
457 lcd_clear_display();
458 snprintf(str, 31, "ATA error: %d", rc);
459 lcd_puts(0, 1, str);
460 lcd_puts(0, 3, "Press ON to debug");
461 lcd_update();
462 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
463 dbg_ports();
464 #endif
465 panicf("ata: %d", rc);
468 #ifdef HAVE_EEPROM_SETTINGS
469 eeprom_settings_init();
470 #endif
472 #ifndef HAVE_USBSTACK
473 usb_start_monitoring();
474 while (usb_detect() == USB_INSERTED)
476 #ifdef HAVE_EEPROM_SETTINGS
477 firmware_settings.disk_clean = false;
478 #endif
479 /* enter USB mode early, before trying to mount */
480 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
481 #if (CONFIG_STORAGE & STORAGE_MMC)
482 if (!mmc_touched() ||
483 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
484 #endif
486 usb_screen();
487 mounted = true; /* mounting done @ end of USB mode */
489 #ifdef HAVE_USB_POWER
490 if (usb_powered()) /* avoid deadlock */
491 break;
492 #endif
494 #endif
496 if (!mounted)
498 rc = disk_mount_all();
499 if (rc<=0)
501 lcd_clear_display();
502 lcd_puts(0, 0, "No partition");
503 lcd_puts(0, 1, "found.");
504 #ifdef HAVE_LCD_BITMAP
505 lcd_puts(0, 2, "Insert USB cable");
506 lcd_puts(0, 3, "and fix it.");
507 #endif
508 lcd_update();
510 while(button_get(true) != SYS_USB_CONNECTED) {};
511 usb_screen();
512 system_reboot();
516 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
517 (CONFIG_KEYPAD == IRIVER_H10_PAD)
518 #ifdef SETTINGS_RESET
519 /* Reset settings if holding the reset button. (Rec on Archos,
520 A on Gigabeat) */
521 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
522 #else
523 /* Reset settings if the hold button is turned on */
524 if (button_hold())
525 #endif
527 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
528 settings_reset();
530 else
531 #endif
532 settings_load(SETTINGS_ALL);
534 if (init_dircache(true) < 0)
536 #ifdef HAVE_TAGCACHE
537 remove(TAGCACHE_STATEFILE);
538 #endif
541 gui_sync_wps_init();
542 settings_apply(true);
543 init_dircache(false);
544 #ifdef HAVE_TAGCACHE
545 init_tagcache();
546 #endif
548 #ifdef HAVE_EEPROM_SETTINGS
549 if (firmware_settings.initialized)
551 /* In case we crash. */
552 firmware_settings.disk_clean = false;
553 eeprom_settings_store();
555 #endif
556 status_init();
557 playlist_init();
558 tree_mem_init();
559 filetype_init();
560 scrobbler_init();
561 #if CONFIG_CODEC == SWCODEC
562 tdspeed_init();
563 #endif /* CONFIG_CODEC == SWCODEC */
565 #if CONFIG_CODEC != SWCODEC
566 /* No buffer allocation (see buffer.c) may take place after the call to
567 audio_init() since the mpeg thread takes the rest of the buffer space */
568 mp3_init( global_settings.volume,
569 global_settings.bass,
570 global_settings.treble,
571 global_settings.balance,
572 global_settings.loudness,
573 global_settings.avc,
574 global_settings.channel_config,
575 global_settings.stereo_width,
576 global_settings.mdb_strength,
577 global_settings.mdb_harmonics,
578 global_settings.mdb_center,
579 global_settings.mdb_shape,
580 global_settings.mdb_enable,
581 global_settings.superbass);
583 /* audio_init must to know the size of voice buffer so init voice first */
584 talk_init();
585 #endif /* CONFIG_CODEC != SWCODEC */
587 audio_init();
589 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
590 pcm_rec_init();
591 #endif
593 /* runtime database has to be initialized after audio_init() */
594 cpu_boost(false);
596 #if CONFIG_CHARGING
597 car_adapter_mode_init();
598 #endif
599 #ifdef IPOD_ACCESSORY_PROTOCOL
600 iap_setup(global_settings.serial_bitrate);
601 #endif
602 #ifdef HAVE_ACCESSORY_SUPPLY
603 accessory_supply_set(global_settings.accessory_supply);
604 #endif
607 #ifdef CPU_PP
608 void cop_main(void)
610 /* This is the entry point for the coprocessor
611 Anyone not running an upgraded bootloader will never reach this point,
612 so it should not be assumed that the coprocessor be usable even on
613 platforms which support it.
615 A kernel thread is initially setup on the coprocessor and immediately
616 destroyed for purposes of continuity. The cop sits idle until at least
617 one thread exists on it. */
619 /* 3G doesn't have Rolo or dual core support yet */
620 #if NUM_CORES > 1
621 system_init();
622 kernel_init();
623 /* This should never be reached */
624 #endif
625 while(1) {
626 sleep_core(COP);
629 #endif /* CPU_PP */
631 int main(void)
633 app_main();
635 while(1) {
636 #if (CONFIG_LED == LED_REAL)
637 led(true); sleep(HZ/10);
638 led(false); sleep(HZ/10);
639 #endif
641 return 0;
643 #endif