summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2002-07-18 21:02:55 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2002-07-18 21:02:55 +0000
commit4e46ac78ae5c511db6935b34560a7a2ec8f26b24 (patch)
treec6b8a18502cc9a9797f3d7f8008f9e304ce5f20e
parentf952ba7548772b91bacb9dc44fd740739745e67d (diff)
downloadrockbox-4e46ac78ae5c511db6935b34560a7a2ec8f26b24.tar.gz
rockbox-4e46ac78ae5c511db6935b34560a7a2ec8f26b24.zip
At last, really short load times
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1385 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/mpeg.c131
1 files changed, 87 insertions, 44 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index eb065d5a51..f2cdcf6fa9 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -34,13 +34,12 @@
34#include "file.h" 34#include "file.h"
35#endif 35#endif
36 36
37#define MPEG_CHUNKSIZE 0x20000 37#define MPEG_FIRST_CHUNKSIZE 0x20000
38#ifdef ARCHOS_RECORDER 38#define MPEG_CHUNKSIZE 0x180000
39/* recorder is slower and needs more load time */ 39#define MPEG_FIRST_SWAP_CHUNKSIZE 0x20000
40#define MPEG_LOW_WATER 0x40000 40#define MPEG_SWAP_CHUNKSIZE 0x8000
41#else 41#define MPEG_HIGHWATER 0x10000
42#define MPEG_LOW_WATER 0x30000 42#define MPEG_LOW_WATER 0x30000
43#endif
44 43
45#define MPEG_PLAY 1 44#define MPEG_PLAY 1
46#define MPEG_STOP 2 45#define MPEG_STOP 2
@@ -49,6 +48,7 @@
49#define MPEG_NEXT 5 48#define MPEG_NEXT 5
50#define MPEG_PREV 6 49#define MPEG_PREV 6
51#define MPEG_NEED_DATA 100 50#define MPEG_NEED_DATA 100
51#define MPEG_SWAP_DATA 101
52 52
53extern char* peek_next_track(int type); 53extern char* peek_next_track(int type);
54extern char* peek_prev_track(int type); 54extern char* peek_prev_track(int type);
@@ -274,6 +274,7 @@ extern unsigned char mp3end[];
274 274
275static int mp3buflen; 275static int mp3buflen;
276static int mp3buf_write; 276static int mp3buf_write;
277static int mp3buf_swapwrite;
277static int mp3buf_read; 278static int mp3buf_read;
278 279
279static int last_dma_chunk_size; 280static int last_dma_chunk_size;
@@ -355,14 +356,14 @@ static void dma_tick(void)
355{ 356{
356 if(playing) 357 if(playing)
357 { 358 {
358 /* Start DMA if it is disabled and the DEMAND pin is high */ 359 /* Start DMA if it is disabled and the DEMAND pin is high */
359 if(!dma_on && (PBDR & 0x4000)) 360 if(!dma_on && (PBDR & 0x4000))
360 { 361 {
361 if(!(SCR0 & 0x80)) 362 if(!(SCR0 & 0x80))
362 start_dma(); 363 start_dma();
363 } 364 }
364 id3tags[0].id3.elapsed += (current_tick - last_dma_tick) * 1000 / HZ; 365 id3tags[0].id3.elapsed += (current_tick - last_dma_tick) * 1000 / HZ;
365 last_dma_tick = current_tick; 366 last_dma_tick = current_tick;
366 } 367 }
367} 368}
368 369
@@ -379,6 +380,7 @@ static void reset_mp3_buffer(void)
379{ 380{
380 mp3buf_read = 0; 381 mp3buf_read = 0;
381 mp3buf_write = 0; 382 mp3buf_write = 0;
383 mp3buf_swapwrite = 0;
382} 384}
383 385
384#pragma interrupt 386#pragma interrupt
@@ -436,7 +438,7 @@ void DEI3(void)
436 { 438 {
437 DEBUGF("No more MP3 data. Stopping.\n"); 439 DEBUGF("No more MP3 data. Stopping.\n");
438 CHCR3 = 0; /* Stop DMA interrupt */ 440 CHCR3 = 0; /* Stop DMA interrupt */
439 playing = false; 441 playing = false;
440 } 442 }
441 } 443 }
442 444
@@ -486,7 +488,7 @@ static void stop_playing(void)
486 playing = false; 488 playing = false;
487 filling = false; 489 filling = false;
488 if(mpeg_file >= 0) 490 if(mpeg_file >= 0)
489 close(mpeg_file); 491 close(mpeg_file);
490 mpeg_file = -1; 492 mpeg_file = -1;
491 stop_dma(); 493 stop_dma();
492} 494}
@@ -497,6 +499,7 @@ static void mpeg_thread(void)
497 int len; 499 int len;
498 int free_space_left; 500 int free_space_left;
499 int amount_to_read; 501 int amount_to_read;
502 int amount_to_swap;
500 503
501 play_pending = false; 504 play_pending = false;
502 playing = false; 505 playing = false;
@@ -505,6 +508,7 @@ static void mpeg_thread(void)
505 while(1) 508 while(1)
506 { 509 {
507 DEBUGF("S\n"); 510 DEBUGF("S\n");
511 yield();
508 queue_wait(&mpeg_queue, &ev); 512 queue_wait(&mpeg_queue, &ev);
509 switch(ev.id) 513 switch(ev.id)
510 { 514 {
@@ -545,7 +549,7 @@ static void mpeg_thread(void)
545 549
546 case MPEG_STOP: 550 case MPEG_STOP:
547 DEBUGF("MPEG_STOP\n"); 551 DEBUGF("MPEG_STOP\n");
548 stop_playing(); 552 stop_playing();
549 break; 553 break;
550 554
551 case MPEG_PAUSE: 555 case MPEG_PAUSE:
@@ -614,6 +618,50 @@ static void mpeg_thread(void)
614 } 618 }
615 break; 619 break;
616 620
621 case MPEG_SWAP_DATA:
622 free_space_left = mp3buf_write - mp3buf_swapwrite;
623
624 if(free_space_left == 0)
625 break;
626
627 if(free_space_left < 0)
628 free_space_left = mp3buflen + free_space_left;
629
630 if(play_pending)
631 amount_to_swap = MIN(MPEG_FIRST_SWAP_CHUNKSIZE,
632 free_space_left);
633 else
634 amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left);
635 amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite,
636 amount_to_swap);
637
638 DEBUGF("B %x\n", amount_to_swap);
639 bitswap((unsigned short *)(mp3buf + mp3buf_swapwrite),
640 (amount_to_swap+1)/2);
641
642 mp3buf_swapwrite += amount_to_swap;
643 if(mp3buf_swapwrite >= mp3buflen)
644 {
645 mp3buf_swapwrite = 0;
646 DEBUGF("BW\n");
647 }
648
649 /* Tell ourselves that we must swap more data */
650 queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0);
651
652 /* And while we're at it, see if we have started
653 playing yet. If not, do it. */
654 if(play_pending)
655 {
656 play_pending = false;
657 playing = true;
658
659 last_dma_tick = current_tick;
660 init_dma();
661 start_dma();
662 }
663 break;
664
617 case MPEG_NEED_DATA: 665 case MPEG_NEED_DATA:
618 free_space_left = mp3buf_read - mp3buf_write; 666 free_space_left = mp3buf_read - mp3buf_write;
619 667
@@ -621,16 +669,26 @@ static void mpeg_thread(void)
621 if(free_space_left <= 0) 669 if(free_space_left <= 0)
622 free_space_left = mp3buflen + free_space_left; 670 free_space_left = mp3buflen + free_space_left;
623 671
672 /* Make sure that we don't fill the entire buffer */
673 free_space_left -= 2;
674
624 /* do we have any more buffer space to fill? */ 675 /* do we have any more buffer space to fill? */
625 if(free_space_left <= MPEG_CHUNKSIZE) 676 if(free_space_left <= MPEG_HIGHWATER)
626 { 677 {
627 DEBUGF("0\n"); 678 DEBUGF("0\n");
628 filling = false; 679 filling = false;
629 ata_sleep(); 680 ata_sleep();
630 break; 681 break;
631 } 682 }
632 683
633 amount_to_read = MIN(MPEG_CHUNKSIZE, free_space_left); 684 if(play_pending)
685 {
686 amount_to_read = MIN(MPEG_FIRST_CHUNKSIZE, free_space_left);
687 }
688 else
689 {
690 amount_to_read = MIN(MPEG_CHUNKSIZE, free_space_left);
691 }
634 amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read); 692 amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read);
635 693
636 /* Read in a few seconds worth of MP3 data. We don't want to 694 /* Read in a few seconds worth of MP3 data. We don't want to
@@ -643,11 +701,9 @@ static void mpeg_thread(void)
643 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); 701 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read);
644 if(len > 0) 702 if(len > 0)
645 { 703 {
646 DEBUGF("B\n"); 704 /* Tell ourselves that we need to swap some data */
705 queue_post(&mpeg_queue, MPEG_SWAP_DATA, 0);
647 706
648 bitswap((unsigned short *)(mp3buf + mp3buf_write),
649 (len+1)/2);
650
651 mp3buf_write += len; 707 mp3buf_write += len;
652 if(mp3buf_write >= mp3buflen) 708 if(mp3buf_write >= mp3buflen)
653 { 709 {
@@ -657,18 +713,6 @@ static void mpeg_thread(void)
657 713
658 /* Tell ourselves that we want more data */ 714 /* Tell ourselves that we want more data */
659 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 715 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
660
661 /* And while we're at it, see if we have started
662 playing yet. If not, do it. */
663 if(play_pending)
664 {
665 play_pending = false;
666 playing = true;
667
668 last_dma_tick = current_tick;
669 init_dma();
670 start_dma();
671 }
672 } 716 }
673 else 717 else
674 { 718 {
@@ -696,20 +740,19 @@ static void mpeg_thread(void)
696 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 740 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
697 } 741 }
698 } 742 }
699 yield(); /* To be safe */
700 } 743 }
701 break; 744 break;
702 745
703 case SYS_USB_CONNECTED: 746 case SYS_USB_CONNECTED:
704 stop_playing(); 747 stop_playing();
705 748
706 /* Tell the USB thread that we are safe */ 749 /* Tell the USB thread that we are safe */
707 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n"); 750 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
708 usb_acknowledge(SYS_USB_CONNECTED_ACK); 751 usb_acknowledge(SYS_USB_CONNECTED_ACK);
709 752
710 /* Wait until the USB cable is extracted again */ 753 /* Wait until the USB cable is extracted again */
711 usb_wait_for_disconnect(&mpeg_queue); 754 usb_wait_for_disconnect(&mpeg_queue);
712 break; 755 break;
713 } 756 }
714 } 757 }
715} 758}
@@ -996,7 +1039,7 @@ void mpeg_init(int volume, int bass, int treble)
996 1039
997 queue_init(&mpeg_queue); 1040 queue_init(&mpeg_queue);
998 create_thread(mpeg_thread, mpeg_stack, 1041 create_thread(mpeg_thread, mpeg_stack,
999 sizeof(mpeg_stack), mpeg_thread_name); 1042 sizeof(mpeg_stack), mpeg_thread_name);
1000 mas_poll_start(2); 1043 mas_poll_start(2);
1001 1044
1002#ifndef ARCHOS_RECORDER 1045#ifndef ARCHOS_RECORDER