blob: fb27a3b904f94f5102de6fc8a1be3b64c1c606cc [file] [log] [blame]
Björn Stenberg1ac46002002-05-24 12:22:14 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdbool.h>
Linus Nielsen Feltzingc633ceb2002-06-07 14:41:26 +000020#include "config.h"
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +000021#include "debug.h"
22#include "panic.h"
23#include "id3.h"
24#include "mpeg.h"
Björn Stenbergaba3d782002-07-16 12:22:31 +000025#include "ata.h"
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +000026#include "string.h"
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +000027#ifndef SIMULATOR
Björn Stenberg1ac46002002-05-24 12:22:14 +000028#include "i2c.h"
29#include "mas.h"
30#include "dac.h"
Björn Stenberg1ac46002002-05-24 12:22:14 +000031#include "system.h"
Björn Stenberg1ac46002002-05-24 12:22:14 +000032#include "kernel.h"
33#include "thread.h"
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +000034#include "usb.h"
Björn Stenberg1ac46002002-05-24 12:22:14 +000035#include "file.h"
Linus Nielsen Feltzing8e4a0e02002-11-10 18:24:40 +000036#include "hwcompat.h"
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +000037#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +000038
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +000039extern void bitswap(unsigned char *data, int length);
Linus Nielsen Feltzingbfc8d0a2002-08-20 14:22:11 +000040
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000041#ifdef HAVE_MAS3587F
42static void init_recording(void);
43static void init_playback(void);
44static void start_recording(void);
Linus Nielsen Feltzing2c0b72f2002-11-25 00:02:54 +000045static void stop_recording(void);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000046#endif
47
Linus Nielsen Feltzing5c6ecc82002-10-15 07:28:57 +000048#ifndef SIMULATOR
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +000049static int get_unplayed_space(void);
Linus Nielsen Feltzingd29248d2002-12-05 14:11:48 +000050static int get_playable_space(void);
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +000051static int get_unswapped_space(void);
Linus Nielsen Feltzing5c6ecc82002-10-15 07:28:57 +000052#endif
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +000053
Björn Stenberg1ac46002002-05-24 12:22:14 +000054#define MPEG_PLAY 1
55#define MPEG_STOP 2
56#define MPEG_PAUSE 3
57#define MPEG_RESUME 4
Björn Stenberga61617f2002-06-26 21:27:17 +000058#define MPEG_NEXT 5
59#define MPEG_PREV 6
Björn Stenberg05704972002-08-14 19:23:34 +000060#define MPEG_FF_REWIND 7
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +000061#define MPEG_FLUSH_RELOAD 8
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000062#define MPEG_RECORD 9
63#define MPEG_INIT_RECORDING 10
64#define MPEG_INIT_PLAYBACK 11
Björn Stenberg1ac46002002-05-24 12:22:14 +000065#define MPEG_NEED_DATA 100
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +000066#define MPEG_TRACK_CHANGE 101
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000067#define MPEG_SAVE_DATA 102
68#define MPEG_STOP_DONE 103
69
Björn Stenbergc3fd67c2002-12-18 14:57:45 +000070#ifdef HAVE_MAS3587F
71static enum
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000072{
73 MPEG_DECODER,
74 MPEG_ENCODER
75} mpeg_mode;
Björn Stenbergc3fd67c2002-12-18 14:57:45 +000076#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +000077
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +000078extern char* playlist_peek(int steps);
79extern int playlist_next(int steps);
Linus Nielsen Feltzing56e5d1a2002-10-09 13:47:38 +000080extern int playlist_amount(void);
Björn Stenberg6224cdb2002-08-16 14:41:47 +000081extern void update_file_pos( int id, int pos );
Daniel Stenberg6229aa22002-06-10 06:04:31 +000082
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +000083static char *units[] =
84{
85 "%", /* Volume */
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +000086 "dB", /* Bass */
Linus Nielsen Feltzinge0d88a12002-07-22 16:38:02 +000087 "dB", /* Treble */
Linus Nielsen Feltzingb3bda032002-08-14 21:30:06 +000088 "%", /* Balance */
Linus Nielsen Feltzinge0d88a12002-07-22 16:38:02 +000089 "dB", /* Loudness */
Linus Nielsen Feltzingb1098982002-09-09 15:13:33 +000090 "%", /* Bass boost */
91 "", /* AVC */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +000092 "", /* Channels */
93 "dB", /* Left gain */
94 "dB", /* Right gain */
95 "dB", /* Mic gain */
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +000096};
97
Linus Nielsen Feltzingfd42ceb2002-06-28 12:39:47 +000098static int numdecimals[] =
99{
Linus Nielsen Feltzing5c0ba522002-06-28 12:47:42 +0000100 0, /* Volume */
101 0, /* Bass */
Linus Nielsen Feltzinge0d88a12002-07-22 16:38:02 +0000102 0, /* Treble */
103 0, /* Balance */
104 0, /* Loudness */
Linus Nielsen Feltzingb1098982002-09-09 15:13:33 +0000105 0, /* Bass boost */
106 0, /* AVC */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000107 0, /* Channels */
108 1, /* Left gain */
109 1, /* Right gain */
110 1, /* Mic gain */
Linus Nielsen Feltzingfd42ceb2002-06-28 12:39:47 +0000111};
112
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +0000113static int minval[] =
114{
115 0, /* Volume */
116 0, /* Bass */
Linus Nielsen Feltzinge0d88a12002-07-22 16:38:02 +0000117 0, /* Treble */
Linus Nielsen Feltzingb3bda032002-08-14 21:30:06 +0000118 -50, /* Balance */
Linus Nielsen Feltzinge0d88a12002-07-22 16:38:02 +0000119 0, /* Loudness */
Linus Nielsen Feltzingb1098982002-09-09 15:13:33 +0000120 0, /* Bass boost */
Robert Hak04782362002-10-03 09:40:19 +0000121 -1, /* AVC */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000122 0, /* Channels */
123 0, /* Left gain */
124 0, /* Right gain */
125 0, /* Mic gain */
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +0000126};
127
128static int maxval[] =
129{
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000130 100, /* Volume */
Linus Nielsen Feltzingf1e9de52002-07-29 09:34:44 +0000131#ifdef HAVE_MAS3587F
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000132 24, /* Bass */
133 24, /* Treble */
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000134#else
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000135 30, /* Bass */
136 30, /* Treble */
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000137#endif
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000138 50, /* Balance */
139 17, /* Loudness */
140 10, /* Bass boost */
141 3, /* AVC */
142 3, /* Channels */
143 15, /* Left gain */
144 15, /* Right gain */
145 15, /* Mic gain */
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +0000146};
147
Linus Nielsen Feltzinga3a51ec2002-06-28 11:54:47 +0000148static int defaultval[] =
149{
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000150 70, /* Volume */
Linus Nielsen Feltzingf1e9de52002-07-29 09:34:44 +0000151#ifdef HAVE_MAS3587F
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000152 12+6, /* Bass */
153 12+6, /* Treble */
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000154#else
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000155 15+7, /* Bass */
156 15+7, /* Treble */
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000157#endif
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000158 0, /* Balance */
159 0, /* Loudness */
160 0, /* Bass boost */
161 0, /* AVC */
162 0, /* Channels */
163 8, /* Left gain */
164 2, /* Right gain */
165 2, /* Mic gain */
Linus Nielsen Feltzinga3a51ec2002-06-28 11:54:47 +0000166};
167
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +0000168char *mpeg_sound_unit(int setting)
169{
170 return units[setting];
171}
172
Linus Nielsen Feltzingfd42ceb2002-06-28 12:39:47 +0000173int mpeg_sound_numdecimals(int setting)
174{
175 return numdecimals[setting];
176}
177
Linus Nielsen Feltzing667fb7c2002-06-28 11:48:53 +0000178int mpeg_sound_min(int setting)
179{
180 return minval[setting];
181}
182
183int mpeg_sound_max(int setting)
184{
185 return maxval[setting];
186}
187
Linus Nielsen Feltzinga3a51ec2002-06-28 11:54:47 +0000188int mpeg_sound_default(int setting)
189{
190 return defaultval[setting];
191}
192
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +0000193/* list of tracks in memory */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000194#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
195#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
196
197struct id3tag
198{
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +0000199 struct mp3entry id3;
200 int mempos;
Björn Stenbergebb14ca2002-08-13 23:13:01 +0000201 bool used;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000202};
203
204static struct id3tag *id3tags[MAX_ID3_TAGS];
Björn Stenbergebb14ca2002-08-13 23:13:01 +0000205static struct id3tag _id3tags[MAX_ID3_TAGS];
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000206
Linus Nielsen Feltzinge5792d62002-07-25 23:12:41 +0000207static unsigned int current_track_counter = 0;
208static unsigned int last_track_counter = 0;
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +0000209
210#ifndef SIMULATOR
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000211
Linus Nielsen Feltzingcd517cc2002-10-03 12:07:17 +0000212static bool mpeg_is_initialized = false;
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000213
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000214static int tag_read_idx = 0;
215static int tag_write_idx = 0;
216
217static int num_tracks_in_memory(void)
218{
219 return (tag_write_idx - tag_read_idx) & MAX_ID3_TAGS_MASK;
220}
221#endif
222
223#ifndef SIMULATOR
224static void debug_tags(void)
225{
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000226#ifdef DEBUG_TAGS
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000227 int i;
228
229 for(i = 0;i < MAX_ID3_TAGS;i++)
230 {
231 DEBUGF("id3tags[%d]: %08x", i, id3tags[i]);
232 if(id3tags[i])
233 DEBUGF(" - %s", id3tags[i]->id3.path);
234 DEBUGF("\n");
235 }
236 DEBUGF("read: %d, write :%d\n", tag_read_idx, tag_write_idx);
237 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
238#endif
239}
240
241static bool append_tag(struct id3tag *tag)
242{
243 if(num_tracks_in_memory() < MAX_ID3_TAGS - 1)
244 {
245 id3tags[tag_write_idx] = tag;
246 tag_write_idx = (tag_write_idx+1) & MAX_ID3_TAGS_MASK;
247 debug_tags();
248 return true;
249 }
250 else
251 {
252 DEBUGF("Tag memory is full\n");
253 return false;
254 }
255}
256
257static void remove_current_tag(void)
258{
259 int oldidx = tag_read_idx;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000260
261 if(num_tracks_in_memory() > 0)
262 {
263 /* First move the index, so nobody tries to access the tag */
264 tag_read_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
265
266 /* Now delete it */
Björn Stenbergebb14ca2002-08-13 23:13:01 +0000267 id3tags[oldidx]->used = false;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000268 id3tags[oldidx] = NULL;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000269 debug_tags();
270 }
271}
272
Björn Stenberg05704972002-08-14 19:23:34 +0000273static void remove_all_non_current_tags(void)
274{
275 int i = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
276
277 while (i != tag_write_idx)
278 {
279 id3tags[i]->used = false;
280 id3tags[i] = NULL;
281
282 i = (i+1) & MAX_ID3_TAGS_MASK;
283 }
284
285 tag_write_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
286 debug_tags();
287}
288
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000289static void remove_all_tags(void)
290{
291 int i;
292
293 for(i = 0;i < MAX_ID3_TAGS;i++)
294 remove_current_tag();
295 debug_tags();
296}
297#endif
298
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000299static void set_elapsed(struct mp3entry* id3)
300{
301 if ( id3->vbr ) {
302 if ( id3->vbrflags & VBR_TOC_FLAG ) {
303 /* calculate elapsed time using TOC */
Hardeep Sidhu441f48f2002-08-27 07:19:25 +0000304 int i;
305 unsigned int remainder, plen, relpos, nextpos;
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000306
307 /* find wich percent we're at */
308 for (i=0; i<100; i++ )
Hardeep Sidhu441f48f2002-08-27 07:19:25 +0000309 {
310 if ( id3->offset < (int)(id3->toc[i] * (id3->filesize / 256)) )
311 {
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000312 break;
Hardeep Sidhu441f48f2002-08-27 07:19:25 +0000313 }
314 }
315
316 i--;
317 if (i < 0)
318 i = 0;
319
320 relpos = id3->toc[i];
321
322 if (i < 99)
323 {
324 nextpos = id3->toc[i+1];
325 }
326 else
327 {
328 nextpos = 256;
329 }
330
331 remainder = id3->offset - (relpos * (id3->filesize / 256));
332
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000333 /* set time for this percent */
Hardeep Sidhu441f48f2002-08-27 07:19:25 +0000334 id3->elapsed = i * id3->length / 100;
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000335
336 /* calculate remainder time */
Hardeep Sidhu441f48f2002-08-27 07:19:25 +0000337 plen = (nextpos - relpos) * (id3->filesize / 256);
Hardeep Sidhu98cb6362002-08-30 07:07:57 +0000338 id3->elapsed += (((remainder * 100) / plen) * id3->length) / 10000;
Björn Stenberg3a9e7b52002-08-20 20:38:50 +0000339 }
340 else {
341 /* no TOC exists. set a rough estimate using average bitrate */
342 int tpk = (id3->filesize / 1024) / id3->length;
343 id3->elapsed = id3->offset * tpk / 1024;
344 }
345 }
346 else
347 /* constant bitrate == simple frame calculation */
348 id3->elapsed = id3->offset / id3->bpf * id3->tpf;
349}
350
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000351static bool paused; /* playback is paused */
Björn Stenberg66b7ade2002-08-08 16:44:20 +0000352#ifdef SIMULATOR
Linus Nielsen Feltzing97bead32002-08-28 10:54:01 +0000353static bool is_playing = false;
Björn Stenberg66b7ade2002-08-08 16:44:20 +0000354static bool playing = false;
Björn Stenberg66b7ade2002-08-08 16:44:20 +0000355#else
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +0000356static int last_dma_tick = 0;
357
Linus Nielsen Feltzingf026f882002-07-29 09:59:49 +0000358static unsigned long mas_version_code;
359
Linus Nielsen Feltzing77d9c7c2002-11-20 22:23:20 +0000360#ifdef HAVE_MAS3507D
361
Björn Stenberg1ac46002002-05-24 12:22:14 +0000362static unsigned int bass_table[] =
363{
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000364 0x9e400, /* -15dB */
365 0xa2800, /* -14dB */
366 0xa7400, /* -13dB */
367 0xac400, /* -12dB */
368 0xb1800, /* -11dB */
369 0xb7400, /* -10dB */
370 0xbd400, /* -9dB */
371 0xc3c00, /* -8dB */
372 0xca400, /* -7dB */
373 0xd1800, /* -6dB */
374 0xd8c00, /* -5dB */
375 0xe0400, /* -4dB */
376 0xe8000, /* -3dB */
377 0xefc00, /* -2dB */
378 0xf7c00, /* -1dB */
Björn Stenberg1ac46002002-05-24 12:22:14 +0000379 0,
380 0x800, /* 1dB */
381 0x10000, /* 2dB */
382 0x17c00, /* 3dB */
383 0x1f800, /* 4dB */
384 0x27000, /* 5dB */
385 0x2e400, /* 6dB */
386 0x35800, /* 7dB */
387 0x3c000, /* 8dB */
388 0x42800, /* 9dB */
389 0x48800, /* 10dB */
390 0x4e400, /* 11dB */
391 0x53800, /* 12dB */
392 0x58800, /* 13dB */
393 0x5d400, /* 14dB */
394 0x61800 /* 15dB */
395};
396
397static unsigned int treble_table[] =
398{
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000399 0xb2c00, /* -15dB */
400 0xbb400, /* -14dB */
401 0xc1800, /* -13dB */
402 0xc6c00, /* -12dB */
403 0xcbc00, /* -11dB */
404 0xd0400, /* -10dB */
405 0xd5000, /* -9dB */
406 0xd9800, /* -8dB */
407 0xde000, /* -7dB */
408 0xe2800, /* -6dB */
409 0xe7e00, /* -5dB */
410 0xec000, /* -4dB */
411 0xf0c00, /* -3dB */
412 0xf5c00, /* -2dB */
413 0xfac00, /* -1dB */
Björn Stenberg1ac46002002-05-24 12:22:14 +0000414 0,
415 0x5400, /* 1dB */
416 0xac00, /* 2dB */
417 0x10400, /* 3dB */
418 0x16000, /* 4dB */
419 0x1c000, /* 5dB */
420 0x22400, /* 6dB */
421 0x28400, /* 7dB */
422 0x2ec00, /* 8dB */
423 0x35400, /* 9dB */
424 0x3c000, /* 10dB */
425 0x42c00, /* 11dB */
426 0x49c00, /* 12dB */
427 0x51800, /* 13dB */
428 0x58400, /* 14dB */
429 0x5f800 /* 15dB */
430};
Linus Nielsen Feltzing07b23352002-06-28 15:10:20 +0000431
432static unsigned int prescale_table[] =
433{
434 0x80000, /* 0db */
435 0x8e000, /* 1dB */
436 0x9a400, /* 2dB */
437 0xa5800, /* 3dB */
438 0xaf400, /* 4dB */
439 0xb8000, /* 5dB */
440 0xbfc00, /* 6dB */
441 0xc6c00, /* 7dB */
442 0xcd000, /* 8dB */
443 0xd25c0, /* 9dB */
444 0xd7800, /* 10dB */
445 0xdc000, /* 11dB */
446 0xdfc00, /* 12dB */
447 0xe3400, /* 13dB */
448 0xe6800, /* 14dB */
449 0xe9400 /* 15dB */
450};
Linus Nielsen Feltzingc57dbe72002-06-19 12:08:15 +0000451#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +0000452
Björn Stenberg1ac46002002-05-24 12:22:14 +0000453static struct event_queue mpeg_queue;
Linus Nielsen Feltzing76b40962002-07-15 22:19:49 +0000454static char mpeg_stack[DEFAULT_STACK_SIZE + 0x1000];
455static char mpeg_thread_name[] = "mpeg";
Björn Stenberg1ac46002002-05-24 12:22:14 +0000456
Björn Stenberg3c260772002-05-24 15:27:55 +0000457/* defined in linker script */
458extern unsigned char mp3buf[];
459extern unsigned char mp3end[];
460
461static int mp3buflen;
Björn Stenbergc3fd67c2002-12-18 14:57:45 +0000462static int mp3buf_write;
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +0000463static int mp3buf_swapwrite;
Björn Stenbergc3fd67c2002-12-18 14:57:45 +0000464static int mp3buf_read;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000465
466static int last_dma_chunk_size;
467
468static bool dma_on; /* The DMA is active */
469static bool playing; /* We are playing an MP3 stream */
Linus Nielsen Feltzing958025b2002-07-01 20:11:46 +0000470static bool play_pending; /* We are about to start playing */
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +0000471static bool is_playing; /* We are (attempting to) playing MP3 files */
Björn Stenberg1ac46002002-05-24 12:22:14 +0000472static bool filling; /* We are filling the buffer with data from disk */
Linus Nielsen Feltzing33060d02002-10-09 13:25:03 +0000473static bool dma_underrun; /* True when the DMA has stopped because of
474 slow disk reading (read error, shaking) */
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000475static int low_watermark; /* Dynamic low watermark level */
Linus Nielsen Feltzingb8ff5f82002-12-05 13:09:51 +0000476static int low_watermark_margin; /* Extra time in seconds for watermark */
Linus Nielsen Feltzingbf303de2002-10-15 07:23:18 +0000477static int lowest_watermark_level; /* Debug value to observe the buffer
478 usage */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000479#ifdef HAVE_MAS3587F
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000480static bool is_recording; /* We are recording */
Linus Nielsen Feltzing6a240592002-11-24 11:49:17 +0000481static bool stop_pending;
482static unsigned long record_start_frame; /* Frame number where
483 recording started */
484static bool saving; /* We are saving the buffer to disk */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000485#endif
486
Linus Nielsen Feltzing60ed5ee2002-06-19 06:19:00 +0000487static int mpeg_file;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000488
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000489#ifdef HAVE_MAS3587F
490/* Synchronization variables */
491static bool init_recording_done;
492static bool init_playback_done;
493#endif
494
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000495static void recalculate_watermark(int bitrate)
496{
Linus Nielsen Feltzing672479c2002-12-05 21:56:53 +0000497 int bytes_per_sec = bitrate * 1000 / 8;
498 int time = ata_spinup_time;
499
500 if(time)
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000501 {
Linus Nielsen Feltzingc9feaaf2002-12-05 23:02:36 +0000502 /* No drive spins up faster than 3.5s */
503 if(time < 350)
504 time = 350;
Linus Nielsen Feltzing672479c2002-12-05 21:56:53 +0000505
506 time = time * 3;
507 low_watermark = ((low_watermark_margin * HZ + time) *
508 bytes_per_sec) / HZ;
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000509 }
510 else
511 {
512 low_watermark = MPEG_LOW_WATER;
513 }
514}
515
Linus Nielsen Feltzingb8ff5f82002-12-05 13:09:51 +0000516void mpeg_set_buffer_margin(int seconds)
517{
518 low_watermark_margin = seconds;
519}
520
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +0000521void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
522{
523 dbgdata->mp3buflen = mp3buflen;
524 dbgdata->mp3buf_write = mp3buf_write;
525 dbgdata->mp3buf_swapwrite = mp3buf_swapwrite;
526 dbgdata->mp3buf_read = mp3buf_read;
527
528 dbgdata->last_dma_chunk_size = last_dma_chunk_size;
529
530 dbgdata->dma_on = dma_on;
531 dbgdata->playing = playing;
532 dbgdata->play_pending = play_pending;
533 dbgdata->is_playing = is_playing;
534 dbgdata->filling = filling;
535 dbgdata->dma_underrun = dma_underrun;
536
537 dbgdata->unplayed_space = get_unplayed_space();
Linus Nielsen Feltzingd29248d2002-12-05 14:11:48 +0000538 dbgdata->playable_space = get_playable_space();
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +0000539 dbgdata->unswapped_space = get_unswapped_space();
Linus Nielsen Feltzingbf303de2002-10-15 07:23:18 +0000540
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000541 dbgdata->low_watermark_level = low_watermark;
Linus Nielsen Feltzingbf303de2002-10-15 07:23:18 +0000542 dbgdata->lowest_watermark_level = lowest_watermark_level;
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +0000543}
544
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000545#ifdef HAVE_MAS3507D
Björn Stenberg1ac46002002-05-24 12:22:14 +0000546static void mas_poll_start(int interval_in_ms)
547{
548 unsigned int count;
549
Linus Nielsen Feltzing26e7ec42002-10-09 09:15:28 +0000550 count = (FREQ * interval_in_ms) / 1000 / 8;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000551
552 if(count > 0xffff)
553 {
554 panicf("Error! The MAS poll interval is too long (%d ms)\n",
555 interval_in_ms);
556 return;
557 }
558
559 /* We are using timer 1 */
560
561 TSTR &= ~0x02; /* Stop the timer */
562 TSNC &= ~0x02; /* No synchronization */
563 TMDR &= ~0x02; /* Operate normally */
564
565 TCNT1 = 0; /* Start counting at 0 */
566 GRA1 = count;
567 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
568
Linus Nielsen Feltzingc57dbe72002-06-19 12:08:15 +0000569 /* Enable interrupt on level 5 */
570 IPRC = (IPRC & ~0x000f) | 0x0005;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000571
572 TSR1 &= ~0x02;
573 TIER1 = 0xf9; /* Enable GRA match interrupt */
574
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +0000575 TSTR |= 0x02; /* Start timer 1 */
Björn Stenberg1ac46002002-05-24 12:22:14 +0000576}
Linus Nielsen Feltzinga9461562002-12-06 21:41:46 +0000577#else
578static void postpone_dma_tick(void)
579{
580 unsigned int count;
581
582 count = FREQ / 1000 / 8;
583
584 /* We are using timer 1 */
585
586 TSTR &= ~0x02; /* Stop the timer */
587 TSNC &= ~0x02; /* No synchronization */
588 TMDR &= ~0x02; /* Operate normally */
589
590 TCNT1 = 0; /* Start counting at 0 */
591 GRA1 = count;
592 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
593
594 /* Enable interrupt on level 5 */
595 IPRC = (IPRC & ~0x000f) | 0x0005;
596
597 TSR1 &= ~0x02;
598 TIER1 = 0xf9; /* Enable GRA match interrupt */
599
600 TSTR |= 0x02; /* Start timer 1 */
601}
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000602#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +0000603
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +0000604#ifdef DEBUG
605static void dbg_timer_start(void)
606{
607 /* We are using timer 2 */
608
609 TSTR &= ~0x04; /* Stop the timer */
610 TSNC &= ~0x04; /* No synchronization */
611 TMDR &= ~0x44; /* Operate normally */
612
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +0000613 TCNT2 = 0; /* Start counting at 0 */
614 TCR2 = 0x03; /* Sysclock/8 */
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +0000615
616 TSTR |= 0x04; /* Start timer 2 */
617}
618
619static int dbg_cnt2us(unsigned int cnt)
620{
621 return (cnt * 10000) / (FREQ/800);
622}
623#endif
624
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +0000625static int get_unplayed_space(void)
Björn Stenbergbcbc7822002-08-08 12:02:17 +0000626{
627 int space = mp3buf_write - mp3buf_read;
628 if (space < 0)
Björn Stenberg749d87b2002-08-15 16:48:34 +0000629 space += mp3buflen;
630 return space;
631}
632
Linus Nielsen Feltzingd29248d2002-12-05 14:11:48 +0000633static int get_playable_space(void)
634{
635 int space = mp3buf_swapwrite - mp3buf_read;
636 if (space < 0)
637 space += mp3buflen;
638 return space;
639}
640
Björn Stenberg749d87b2002-08-15 16:48:34 +0000641static int get_unplayed_space_current_song(void)
642{
643 int space;
644
645 if (num_tracks_in_memory() > 1)
646 {
647 int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
648
649 space = id3tags[track_offset]->mempos - mp3buf_read;
650 }
651 else
652 {
653 space = mp3buf_write - mp3buf_read;
654 }
655
656 if (space < 0)
657 space += mp3buflen;
658
Björn Stenbergbcbc7822002-08-08 12:02:17 +0000659 return space;
660}
661
Hardeep Sidhu67f95ec2002-10-03 07:28:28 +0000662static int get_unswapped_space(void)
663{
664 int space = mp3buf_write - mp3buf_swapwrite;
665 if (space < 0)
666 space += mp3buflen;
667 return space;
668}
669
Björn Stenberg1ac46002002-05-24 12:22:14 +0000670static void init_dma(void)
671{
672 SAR3 = (unsigned int) mp3buf + mp3buf_read;
673 DAR3 = 0x5FFFEC3;
674 CHCR3 &= ~0x0002; /* Clear interrupt */
675 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
Björn Stenberg749d87b2002-08-15 16:48:34 +0000676 last_dma_chunk_size = MIN(65536, get_unplayed_space_current_song());
Björn Stenberg1ac46002002-05-24 12:22:14 +0000677 DTCR3 = last_dma_chunk_size & 0xffff;
678 DMAOR = 0x0001; /* Enable DMA */
679 CHCR3 |= 0x0001; /* Enable DMA IRQ */
Linus Nielsen Feltzing33060d02002-10-09 13:25:03 +0000680 dma_underrun = false;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000681}
682
683static void start_dma(void)
684{
685 SCR0 |= 0x80;
686 dma_on = true;
687}
688
689static void stop_dma(void)
690{
691 SCR0 &= 0x7f;
692 dma_on = false;
693}
694
Linus Nielsen Feltzingfde9b572002-11-19 10:29:38 +0000695#ifdef HAVE_MAS3587F
Björn Stenbergc3fd67c2002-12-18 14:57:45 +0000696#ifdef DEBUG
697static long timing_info_index = 0;
698static long timing_info[1024];
699#endif
700static bool inverted_pr;
701static unsigned long num_rec_bytes;
Linus Nielsen Feltzing2c0b72f2002-11-25 00:02:54 +0000702
703void drain_dma_buffer(void)
704{
705 if(inverted_pr)
706 {
707 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))
708 {
709 PADR |= 0x800;
710
711 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
712
713 /* It must take at least 5 cycles before
714 the data is read */
715 asm(" nop\n nop\n nop\n");
716 asm(" nop\n nop\n nop\n");
717 PADR &= ~0x800;
718
719 while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));
720 }
721 }
722 else
723 {
724 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40))
725 {
726 PADR &= ~0x800;
727
728 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
729
730 /* It must take at least 5 cycles before
731 the data is read */
732 asm(" nop\n nop\n nop\n");
733 asm(" nop\n nop\n nop\n");
734
735 PADR |= 0x800;
736
737 while(!(*((volatile unsigned char *)PBDR_ADDR) & 0x80));
738 }
739 }
740}
Linus Nielsen Feltzingfde9b572002-11-19 10:29:38 +0000741#endif
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000742
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000743static void dma_tick (void) __attribute__ ((section (".icode")));
Björn Stenberg1ac46002002-05-24 12:22:14 +0000744static void dma_tick(void)
745{
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000746#ifdef HAVE_MAS3587F
747 if(mpeg_mode == MPEG_DECODER)
Björn Stenberg1ac46002002-05-24 12:22:14 +0000748 {
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000749#endif
750 if(playing && !paused)
Björn Stenberg1ac46002002-05-24 12:22:14 +0000751 {
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000752 /* Start DMA if it is disabled and the DEMAND pin is high */
753 if(!dma_on && (PBDR & 0x4000))
754 {
755 if(!(SCR0 & 0x80))
756 start_dma();
757 }
758 id3tags[tag_read_idx]->id3.elapsed +=
759 (current_tick - last_dma_tick) * 1000 / HZ;
760 last_dma_tick = current_tick;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000761 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000762#ifdef HAVE_MAS3587F
Björn Stenberg1ac46002002-05-24 12:22:14 +0000763 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000764 else
765 {
766 int i;
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000767 int num_bytes;
Linus Nielsen Feltzingd7033892002-11-19 21:07:44 +0000768 if(is_recording && (PBDR & 0x4000))
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000769 {
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000770#ifdef DEBUG
771 timing_info[timing_info_index++] = current_tick;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000772 TCNT2 = 0;
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000773#endif
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000774 /* We read as long as EOD is high, but max 30 bytes.
775 This code is optimized, and should probably be
776 written in assembler instead. */
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000777 if(inverted_pr)
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000778 {
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000779 i = 0;
780 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
781 && i < 30)
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000782 {
Linus Nielsen Feltzing8e4a0e02002-11-10 18:24:40 +0000783 PADR |= 0x800;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000784
785 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000786
787 /* It must take at least 5 cycles before
788 the data is read */
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000789 asm(" nop\n nop\n nop\n");
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000790 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
791
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000792 if(mp3buf_write >= mp3buflen)
793 mp3buf_write = 0;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000794
795 i++;
796
797 PADR &= ~0x800;
798
799 /* No wait for /RTW, cause it's not necessary */
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000800 }
801 }
802 else
803 {
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000804 i = 0;
805 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
806 && i < 30)
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000807 {
Linus Nielsen Feltzing8e4a0e02002-11-10 18:24:40 +0000808 PADR &= ~0x800;
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000809
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000810 while(*((volatile unsigned char *)PBDR_ADDR) & 0x80);
811
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000812 /* It must take at least 5 cycles before
813 the data is read */
Linus Nielsen Feltzing2c0b72f2002-11-25 00:02:54 +0000814 asm(" nop\n nop\n nop\n");
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000815 mp3buf[mp3buf_write++] = *(unsigned char *)0x4000000;
816
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000817 if(mp3buf_write >= mp3buflen)
818 mp3buf_write = 0;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000819
820 i++;
821
822 PADR |= 0x800;
823
824 /* No wait for /RTW, cause it's not necessary */
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000825 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000826 }
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000827#ifdef DEBUG
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000828 timing_info[timing_info_index++] = TCNT2 + (i << 16);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000829 timing_info_index &= 0x3ff;
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000830#endif
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000831
Linus Nielsen Feltzing68719772002-11-21 21:38:58 +0000832 num_rec_bytes += i;
833
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000834 /* Signal to save the data if we are running out of buffer
835 space */
836 num_bytes = mp3buf_write - mp3buf_read;
837 if(num_bytes < 0)
838 num_bytes += mp3buflen;
839
Linus Nielsen Feltzing00b2aad2002-12-12 02:22:01 +0000840 if(mp3buflen - num_bytes < MPEG_LOW_WATER && !saving)
841 {
842 saving = true;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000843 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
Linus Nielsen Feltzing00b2aad2002-12-12 02:22:01 +0000844 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +0000845 }
846 }
847#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +0000848}
849
Björn Stenberg1ac46002002-05-24 12:22:14 +0000850static void reset_mp3_buffer(void)
851{
852 mp3buf_read = 0;
853 mp3buf_write = 0;
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +0000854 mp3buf_swapwrite = 0;
Linus Nielsen Feltzingbf303de2002-10-15 07:23:18 +0000855 lowest_watermark_level = mp3buflen;
Björn Stenberg1ac46002002-05-24 12:22:14 +0000856}
857
858#pragma interrupt
Björn Stenberg3c260772002-05-24 15:27:55 +0000859void DEI3(void)
860{
Björn Stenberg34486b72002-08-19 11:00:29 +0000861 if(playing && !paused)
Björn Stenberg3c260772002-05-24 15:27:55 +0000862 {
Linus Nielsen Feltzinga46a5d32002-08-08 13:29:31 +0000863 int unplayed_space_left;
Björn Stenbergbcbc7822002-08-08 12:02:17 +0000864 int space_until_end_of_buffer;
865 int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
866
Björn Stenberg3c260772002-05-24 15:27:55 +0000867 mp3buf_read += last_dma_chunk_size;
868 if(mp3buf_read >= mp3buflen)
869 mp3buf_read = 0;
870
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000871 /* First, check if we are on a track boundary */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000872 if (num_tracks_in_memory() > 0)
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000873 {
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000874 if (mp3buf_read == id3tags[track_offset]->mempos)
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000875 {
Linus Nielsen Feltzinge4b9dbb2002-07-25 11:51:11 +0000876 queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000877 track_offset = (track_offset+1) & MAX_ID3_TAGS_MASK;
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000878 }
879 }
880
Linus Nielsen Feltzinga46a5d32002-08-08 13:29:31 +0000881 unplayed_space_left = get_unplayed_space();
882
Björn Stenberg3c260772002-05-24 15:27:55 +0000883 space_until_end_of_buffer = mp3buflen - mp3buf_read;
884
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +0000885 if(!filling && unplayed_space_left < low_watermark)
Björn Stenberg3c260772002-05-24 15:27:55 +0000886 {
Linus Nielsen Feltzing3a25aa42002-05-29 12:25:21 +0000887 filling = true;
Björn Stenberg3c260772002-05-24 15:27:55 +0000888 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
889 }
890
891 if(unplayed_space_left)
892 {
893 last_dma_chunk_size = MIN(65536, unplayed_space_left);
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000894 last_dma_chunk_size = MIN(last_dma_chunk_size,
895 space_until_end_of_buffer);
Björn Stenbergbb9aaf52002-06-25 13:26:04 +0000896
Björn Stenberg200d2262002-06-26 12:05:06 +0000897 /* several tracks loaded? */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000898 if (num_tracks_in_memory() > 1)
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000899 {
Björn Stenberg200d2262002-06-26 12:05:06 +0000900 /* will we move across the track boundary? */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000901 if (( mp3buf_read < id3tags[track_offset]->mempos ) &&
Linus Nielsen Feltzinge4b9dbb2002-07-25 11:51:11 +0000902 ((mp3buf_read+last_dma_chunk_size) >
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000903 id3tags[track_offset]->mempos ))
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000904 {
905 /* Make sure that we end exactly on the boundary */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +0000906 last_dma_chunk_size = id3tags[track_offset]->mempos
Linus Nielsen Feltzinge4b9dbb2002-07-25 11:51:11 +0000907 - mp3buf_read;
Björn Stenberg200d2262002-06-26 12:05:06 +0000908 }
Björn Stenbergbb9aaf52002-06-25 13:26:04 +0000909 }
Linus Nielsen Feltzing4e2384e2002-07-25 11:12:54 +0000910
911 DTCR3 = last_dma_chunk_size & 0xffff;
912 SAR3 = (unsigned int)mp3buf + mp3buf_read;
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000913 id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size;
Linus Nielsen Feltzingd29248d2002-12-05 14:11:48 +0000914
915 /* Update the watermark debug level */
916 if(unplayed_space_left < lowest_watermark_level)
917 lowest_watermark_level = unplayed_space_left;
Björn Stenberg3c260772002-05-24 15:27:55 +0000918 }
919 else
920 {
Linus Nielsen Feltzing33060d02002-10-09 13:25:03 +0000921 /* Check if the end of data is because of a hard disk error.
922 If there is an open file handle, we are still playing music.
923 If not, the last file has been loaded, and the file handle is
924 closed. */
925 if(mpeg_file >= 0)
926 {
Linus Nielsen Feltzingd29248d2002-12-05 14:11:48 +0000927 /* Update the watermark debug level */
928 if(unplayed_space_left < lowest_watermark_level)
929 lowest_watermark_level = unplayed_space_left;
930
Linus Nielsen Feltzing33060d02002-10-09 13:25:03 +0000931 DEBUGF("DMA underrun.\n");
932 dma_underrun = true;
933 }
Linus Nielsen Feltzing26e7ec42002-10-09 09:15:28 +0000934 else
935 {
Linus Nielsen Feltzing33060d02002-10-09 13:25:03 +0000936 DEBUGF("No more MP3 data. Stopping.\n");
937
Linus Nielsen Feltzing26e7ec42002-10-09 09:15:28 +0000938 queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);
939 playing = false;
940 is_playing = false;
941 }
942 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
Björn Stenberg3c260772002-05-24 15:27:55 +0000943 }
944 }
945
946 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
947}
948
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000949#ifdef HAVE_MAS3587F
950static void demand_irq_enable(bool on)
951{
952 int oldlevel = set_irq_level(15);
953
954 if(on)
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000955 {
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000956 IPRA = (IPRA & 0xfff0) | 0x000b;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000957 ICR &= ~0x0010; /* IRQ3 level sensitive */
958 }
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000959 else
960 IPRA &= 0xfff0;
961
962 set_irq_level(oldlevel);
963}
964#endif
965
966#pragma interrupt
Linus Nielsen Feltzinga9461562002-12-06 21:41:46 +0000967void IMIA1(void)
968{
969 dma_tick();
970 TSR1 &= ~0x01;
971#ifdef HAVE_MAS3587F
972 /* Disable interrupt */
973 IPRC &= ~0x000f;
974#endif
975}
976
977#pragma interrupt
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000978void IRQ6(void)
979{
980 stop_dma();
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000981}
982
983#ifdef HAVE_MAS3587F
984#pragma interrupt
985void IRQ3(void)
986{
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000987 /* Begin with setting the IRQ to edge sensitive */
988 ICR |= 0x0010;
989
Linus Nielsen Feltzinga9461562002-12-06 21:41:46 +0000990 if(mpeg_mode == MPEG_ENCODER)
991 dma_tick();
992 else
993 postpone_dma_tick();
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +0000994
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +0000995#if 0
996 if(mpeg_mode == MPEG_ENCODER)
997 /* Shut off if recording is stopped */
998 if(!is_recording)
999 demand_irq_enable(false);
1000#endif
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +00001001}
1002#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +00001003
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001004static int add_track_to_tag_list(char *filename)
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001005{
Björn Stenbergebb14ca2002-08-13 23:13:01 +00001006 struct id3tag *t = NULL;
1007 int i;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001008
Björn Stenbergebb14ca2002-08-13 23:13:01 +00001009 /* find a free tag */
1010 for (i=0; i < MAX_ID3_TAGS_MASK; i++ )
1011 if ( !_id3tags[i].used )
1012 t = &_id3tags[i];
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001013 if(t)
1014 {
Björn Stenbergebb14ca2002-08-13 23:13:01 +00001015 /* grab id3 tag of new file and
1016 remember where in memory it starts */
Daniel Stenberg22633d62002-08-22 07:58:18 +00001017 if(mp3info(&(t->id3), filename))
1018 {
1019 DEBUGF("Bad mp3\n");
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001020 return -1;
Daniel Stenberg22633d62002-08-22 07:58:18 +00001021 }
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001022 t->mempos = mp3buf_write;
1023 t->id3.elapsed = 0;
1024 if(!append_tag(t))
1025 {
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001026 DEBUGF("Tag list is full\n");
1027 }
Björn Stenbergebb14ca2002-08-13 23:13:01 +00001028 else
1029 t->used = true;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001030 }
1031 else
1032 {
1033 DEBUGF("No memory available for id3 tag");
1034 }
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001035 return 0;
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001036}
1037
Björn Stenberga61617f2002-06-26 21:27:17 +00001038/* If next_track is true, opens the next track, if false, opens prev track */
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001039static int new_file(int steps)
Björn Stenbergfa8cd2c2002-05-31 12:12:23 +00001040{
Linus Nielsen Feltzing56e5d1a2002-10-09 13:47:38 +00001041 int max_steps = playlist_amount();
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001042 int start = num_tracks_in_memory() - 1;
1043
1044 if (start < 0)
1045 start = 0;
1046
Björn Stenbergf952ba72002-07-18 15:37:41 +00001047 do {
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001048 char *trackname;
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001049
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001050 trackname = playlist_peek( start + steps );
Björn Stenbergf952ba72002-07-18 15:37:41 +00001051 if ( !trackname )
1052 return -1;
1053
1054 DEBUGF("playing %s\n", trackname);
1055
1056 mpeg_file = open(trackname, O_RDONLY);
1057 if(mpeg_file < 0) {
1058 DEBUGF("Couldn't open file: %s\n",trackname);
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +00001059 steps++;
Linus Nielsen Feltzing56e5d1a2002-10-09 13:47:38 +00001060
1061 /* Bail out if no file could be opened */
1062 if(steps > max_steps)
1063 return -1;
Björn Stenbergf952ba72002-07-18 15:37:41 +00001064 }
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001065 else
1066 {
Björn Stenberg34486b72002-08-19 11:00:29 +00001067 int new_tag_idx = tag_write_idx;
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +00001068
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001069 if(add_track_to_tag_list(trackname))
1070 {
1071 /* Bad mp3 file */
1072 steps++;
1073 close(mpeg_file);
1074 mpeg_file = -1;
1075 }
1076 else
1077 {
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +00001078 /* skip past id3v2 tag */
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001079 lseek(mpeg_file,
Linus Nielsen Feltzingc41322c2002-10-27 23:07:26 +00001080 id3tags[new_tag_idx]->id3.first_frame_offset,
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001081 SEEK_SET);
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001082 id3tags[new_tag_idx]->id3.index = steps;
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001083 id3tags[new_tag_idx]->id3.offset = 0;
Linus Nielsen Feltzingce882bb2002-12-05 15:23:46 +00001084
1085 if(id3tags[new_tag_idx]->id3.vbr)
Linus Nielsen Feltzing672479c2002-12-05 21:56:53 +00001086 /* Average bitrate * 1.5 */
Linus Nielsen Feltzingce882bb2002-12-05 15:23:46 +00001087 recalculate_watermark(
1088 (id3tags[new_tag_idx]->id3.bitrate * 3) / 2);
1089 else
1090 recalculate_watermark(
1091 id3tags[new_tag_idx]->id3.bitrate);
1092
Linus Nielsen Feltzing606b0f52002-08-28 11:43:49 +00001093 }
Björn Stenbergf952ba72002-07-18 15:37:41 +00001094 }
1095 } while ( mpeg_file < 0 );
Björn Stenbergfa8cd2c2002-05-31 12:12:23 +00001096
Björn Stenbergfa8cd2c2002-05-31 12:12:23 +00001097 return 0;
1098}
1099
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +00001100static void stop_playing(void)
1101{
1102 /* Stop the current stream */
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +00001103#ifdef HAVE_MAS3587F
1104 demand_irq_enable(false);
1105#endif
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +00001106 playing = false;
1107 filling = false;
1108 if(mpeg_file >= 0)
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001109 close(mpeg_file);
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +00001110 mpeg_file = -1;
1111 stop_dma();
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001112 remove_all_tags();
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +00001113}
1114
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001115static void update_playlist(void)
1116{
1117 int index;
1118
Björn Stenberga6d0abb2002-10-04 08:48:20 +00001119 if (num_tracks_in_memory() > 0)
1120 {
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001121 index = playlist_next(id3tags[tag_read_idx]->id3.index);
1122 id3tags[tag_read_idx]->id3.index = index;
Björn Stenberga6d0abb2002-10-04 08:48:20 +00001123 }
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001124}
1125
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001126static void track_change(void)
1127{
1128 DEBUGF("Track change\n");
1129
1130#ifdef HAVE_MAS3587F
1131 /* Reset the AVC */
1132 mpeg_sound_set(SOUND_AVC, -1);
1133#endif
1134 remove_current_tag();
1135
1136 current_track_counter++;
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001137
1138 update_playlist();
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001139}
1140
Linus Nielsen Feltzingb3bb0762002-09-18 13:51:08 +00001141#ifdef DEBUG
1142void hexdump(unsigned char *buf, int len)
1143{
1144 int i;
1145
1146 for(i = 0;i < len;i++)
1147 {
1148 if(i && (i & 15) == 0)
1149 {
1150 DEBUGF("\n");
1151 }
1152 DEBUGF("%02x ", buf[i]);
1153 }
1154 DEBUGF("\n");
1155}
1156#endif
1157
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001158static void start_playback_if_ready(void)
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001159{
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001160 int playable_space;
1161
1162 playable_space = mp3buf_swapwrite - mp3buf_read;
1163 if(playable_space < 0)
1164 playable_space += mp3buflen;
1165
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001166 /* See if we have started playing yet. If not, do it. */
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001167 if(play_pending || dma_underrun)
1168 {
1169 /* If the filling has stopped, and we still haven't reached
1170 the watermark, the file must be smaller than the
1171 watermark. We must still play it. */
Linus Nielsen Feltzing7fed4a02002-12-05 17:14:35 +00001172 if((playable_space >= MPEG_PLAY_PENDING_THRESHOLD) ||
Linus Nielsen Feltzing83444372002-12-05 11:09:52 +00001173 !filling || dma_underrun)
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001174 {
1175 DEBUGF("P\n");
1176 play_pending = false;
1177 playing = true;
1178
1179 init_dma();
1180 if (!paused)
1181 {
1182 last_dma_tick = current_tick;
1183 start_dma();
Linus Nielsen Feltzing0dcd47e2002-11-19 09:50:19 +00001184#ifdef HAVE_MAS3587F
1185 demand_irq_enable(true);
1186#endif
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001187 }
1188
1189 /* Tell ourselves that we need more data */
1190 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1191 }
1192 }
1193}
1194
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001195static bool swap_one_chunk(void)
1196{
1197 int free_space_left;
1198 int amount_to_swap;
1199
1200 free_space_left = get_unswapped_space();
1201
1202 if(free_space_left == 0 && !play_pending)
1203 return false;
1204
1205 /* Swap in larger chunks when the user is waiting for the playback
Linus Nielsen Feltzingd199e692002-12-05 13:36:08 +00001206 to start, or when there is dangerously little playable data left */
Linus Nielsen Feltzing7fed4a02002-12-05 17:14:35 +00001207 if(play_pending)
1208 amount_to_swap = MIN(MPEG_PLAY_PENDING_SWAPSIZE, free_space_left);
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001209 else
Linus Nielsen Feltzing7fed4a02002-12-05 17:14:35 +00001210 {
1211 if(get_playable_space() < low_watermark)
1212 amount_to_swap = MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE,
1213 free_space_left);
1214 else
1215 amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left);
1216 }
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001217
1218 if(mp3buf_write < mp3buf_swapwrite)
1219 amount_to_swap = MIN(mp3buflen - mp3buf_swapwrite,
1220 amount_to_swap);
1221 else
1222 amount_to_swap = MIN(mp3buf_write - mp3buf_swapwrite,
1223 amount_to_swap);
1224
1225 bitswap(mp3buf + mp3buf_swapwrite, amount_to_swap);
1226
1227 mp3buf_swapwrite += amount_to_swap;
1228 if(mp3buf_swapwrite >= mp3buflen)
1229 {
1230 mp3buf_swapwrite = 0;
1231 }
1232
1233 return true;
1234}
1235
Björn Stenberg1ac46002002-05-24 12:22:14 +00001236static void mpeg_thread(void)
1237{
Björn Stenberg0c2e9f22002-08-21 17:38:56 +00001238 static int pause_tick = 0;
1239 static unsigned int pause_track = 0;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001240 struct event ev;
1241 int len;
1242 int free_space_left;
Linus Nielsen Feltzing54a65f72002-07-21 07:12:39 +00001243 int unplayed_space_left;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001244 int amount_to_read;
Linus Nielsen Feltzing1d21ca92002-08-01 08:16:44 +00001245 int t1, t2;
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001246 int start_offset;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001247#ifdef HAVE_MAS3587F
1248 int amount_to_save;
Linus Nielsen Feltzing1521a1c2002-11-13 23:22:40 +00001249 int writelen;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001250#endif
1251
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +00001252 is_playing = false;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001253 play_pending = false;
1254 playing = false;
Linus Nielsen Feltzing60ed5ee2002-06-19 06:19:00 +00001255 mpeg_file = -1;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001256
1257 while(1)
1258 {
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001259#ifdef HAVE_MAS3587F
1260 if(mpeg_mode == MPEG_DECODER)
1261 {
1262#endif
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001263 yield();
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001264
1265 /* Swap if necessary, and don't block on the queue_wait() */
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001266 if(swap_one_chunk())
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001267 {
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001268 queue_wait_w_tmo(&mpeg_queue, &ev, 0);
1269 }
1270 else
1271 {
Linus Nielsen Feltzing647db262002-10-16 09:26:03 +00001272 DEBUGF("S R:%x W:%x SW:%x\n",
1273 mp3buf_read, mp3buf_write, mp3buf_swapwrite);
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001274 queue_wait(&mpeg_queue, &ev);
1275 }
Linus Nielsen Feltzingc5e29932002-10-28 00:00:07 +00001276
1277 start_playback_if_ready();
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001278
Björn Stenberg1ac46002002-05-24 12:22:14 +00001279 switch(ev.id)
1280 {
1281 case MPEG_PLAY:
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001282 DEBUGF("MPEG_PLAY\n");
Björn Stenberg1ac46002002-05-24 12:22:14 +00001283 /* Stop the current stream */
1284 play_pending = false;
1285 playing = false;
1286 stop_dma();
1287
1288 reset_mp3_buffer();
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001289 remove_all_tags();
Björn Stenberg1ac46002002-05-24 12:22:14 +00001290
Linus Nielsen Feltzing8f8ab272002-06-19 15:17:40 +00001291 if(mpeg_file >= 0)
1292 close(mpeg_file);
Linus Nielsen Feltzing60ed5ee2002-06-19 06:19:00 +00001293
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001294 if ( new_file(0) == -1 )
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +00001295 {
1296 is_playing = false;
1297 break;
1298 }
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001299
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001300 start_offset = (int)ev.data;
Björn Stenberg3a9e7b52002-08-20 20:38:50 +00001301
1302 /* mid-song resume? */
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001303 if (start_offset) {
Björn Stenberg3a9e7b52002-08-20 20:38:50 +00001304 struct mp3entry* id3 = &id3tags[tag_read_idx]->id3;
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001305 lseek(mpeg_file, start_offset, SEEK_SET);
Björn Stenberg3a9e7b52002-08-20 20:38:50 +00001306 id3->offset = start_offset;
1307 set_elapsed(id3);
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001308 }
1309 else {
Linus Nielsen Feltzing03c13a12002-10-08 07:43:52 +00001310 /* skip past id3v2 tag */
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001311 lseek(mpeg_file,
Linus Nielsen Feltzingc41322c2002-10-27 23:07:26 +00001312 id3tags[tag_read_idx]->id3.first_frame_offset,
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001313 SEEK_SET);
1314
1315 }
Björn Stenbergbb9aaf52002-06-25 13:26:04 +00001316
Björn Stenberg1ac46002002-05-24 12:22:14 +00001317 /* Make it read more data */
1318 filling = true;
1319 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1320
1321 /* Tell the file loading code that we want to start playing
1322 as soon as we have some data */
1323 play_pending = true;
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001324 paused = false;
Linus Nielsen Feltzinge5792d62002-07-25 23:12:41 +00001325
1326 current_track_counter++;
Hardeep Sidhuaa287bb2002-09-17 07:04:43 +00001327 update_playlist();
Björn Stenberg1ac46002002-05-24 12:22:14 +00001328 break;
1329
1330 case MPEG_STOP:
Björn Stenberg3c260772002-05-24 15:27:55 +00001331 DEBUGF("MPEG_STOP\n");
Linus Nielsen Feltzingccfef042002-08-28 10:21:32 +00001332 is_playing = false;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001333 paused = false;
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001334 stop_playing();
Björn Stenberg1ac46002002-05-24 12:22:14 +00001335 break;
1336
1337 case MPEG_PAUSE:
Björn Stenberg3c260772002-05-24 15:27:55 +00001338 DEBUGF("MPEG_PAUSE\n");
Björn Stenberg1ac46002002-05-24 12:22:14 +00001339 /* Stop the current stream */
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001340 paused = true;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001341 playing = false;
Linus Nielsen Feltzingd2018eb2002-07-25 22:09:12 +00001342 pause_tick = current_tick;
Björn Stenberg0c2e9f22002-08-21 17:38:56 +00001343 pause_track = current_track_counter;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001344 stop_dma();
1345 break;
1346
1347 case MPEG_RESUME:
Björn Stenberg3c260772002-05-24 15:27:55 +00001348 DEBUGF("MPEG_RESUME\n");
Linus Nielsen Feltzingd2018eb2002-07-25 22:09:12 +00001349 /* Continue the current stream */
Björn Stenberg34486b72002-08-19 11:00:29 +00001350 paused = false;
1351 if (!play_pending)
1352 {
Björn Stenberg0c2e9f22002-08-21 17:38:56 +00001353 playing = true;
1354 if ( current_track_counter == pause_track )
1355 last_dma_tick += current_tick - pause_tick;
1356 else
1357 last_dma_tick = current_tick;
1358 pause_tick = 0;
1359 start_dma();
Björn Stenberg34486b72002-08-19 11:00:29 +00001360 }
Björn Stenberg1ac46002002-05-24 12:22:14 +00001361 break;
1362
Björn Stenberga61617f2002-06-26 21:27:17 +00001363 case MPEG_NEXT:
1364 DEBUGF("MPEG_NEXT\n");
Björn Stenberga6d0abb2002-10-04 08:48:20 +00001365 /* is next track in ram? */
1366 if ( num_tracks_in_memory() > 1 ) {
1367 int unplayed_space_left, unswapped_space_left;
1368
Björn Stenberga61617f2002-06-26 21:27:17 +00001369 /* stop the current stream */
1370 play_pending = false;
1371 playing = false;
1372 stop_dma();
1373
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001374 track_change();
1375 mp3buf_read = id3tags[tag_read_idx]->mempos;
Björn Stenberg445f17e2002-08-07 22:44:43 +00001376 init_dma();
Linus Nielsen Feltzingfe8a7e72002-08-08 14:51:58 +00001377 last_dma_tick = current_tick;
Björn Stenberg235d9d22002-08-08 14:01:40 +00001378
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001379 unplayed_space_left = get_unplayed_space();
Hardeep Sidhu67f95ec2002-10-03 07:28:28 +00001380 unswapped_space_left = get_unswapped_space();
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001381
Björn Stenberg235d9d22002-08-08 14:01:40 +00001382 /* should we start reading more data? */
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001383 if(!filling && (unplayed_space_left < low_watermark)) {
Björn Stenberg235d9d22002-08-08 14:01:40 +00001384 filling = true;
1385 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
Linus Nielsen Feltzingfe8a7e72002-08-08 14:51:58 +00001386 play_pending = true;
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001387 } else if(unswapped_space_left &&
1388 unswapped_space_left > unplayed_space_left) {
1389 /* Stop swapping the data from the previous file */
1390 mp3buf_swapwrite = mp3buf_read;
1391 play_pending = true;
Linus Nielsen Feltzingfe8a7e72002-08-08 14:51:58 +00001392 } else {
1393 playing = true;
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001394 if (!paused)
1395 start_dma();
Björn Stenberg235d9d22002-08-08 14:01:40 +00001396 }
Björn Stenberg445f17e2002-08-07 22:44:43 +00001397 }
1398 else {
Björn Stenberga6d0abb2002-10-04 08:48:20 +00001399 if (!playlist_peek(1))
1400 break;
1401
1402 /* stop the current stream */
1403 play_pending = false;
1404 playing = false;
1405 stop_dma();
1406
Björn Stenberg445f17e2002-08-07 22:44:43 +00001407 reset_mp3_buffer();
1408 remove_all_tags();
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001409
Björn Stenberg445f17e2002-08-07 22:44:43 +00001410 /* Open the next file */
1411 if (mpeg_file >= 0)
1412 close(mpeg_file);
1413
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001414 if (new_file(1) < 0) {
Björn Stenberg445f17e2002-08-07 22:44:43 +00001415 DEBUGF("No more files to play\n");
1416 filling = false;
1417 } else {
1418 /* Make it read more data */
1419 filling = true;
1420 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1421
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001422 /* Tell the file loading code that we want
1423 to start playing as soon as we have some data */
Björn Stenberg445f17e2002-08-07 22:44:43 +00001424 play_pending = true;
Linus Nielsen Feltzingab042e62002-07-27 00:31:38 +00001425
Björn Stenberg445f17e2002-08-07 22:44:43 +00001426 current_track_counter++;
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001427 update_playlist();
Björn Stenberg445f17e2002-08-07 22:44:43 +00001428 }
Björn Stenberga61617f2002-06-26 21:27:17 +00001429 }
1430 break;
1431
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001432 case MPEG_PREV: {
1433 int numtracks = num_tracks_in_memory();
Björn Stenberga61617f2002-06-26 21:27:17 +00001434 DEBUGF("MPEG_PREV\n");
Björn Stenberga6d0abb2002-10-04 08:48:20 +00001435 if (!playlist_peek(-1))
1436 break;
Björn Stenberga61617f2002-06-26 21:27:17 +00001437 /* stop the current stream */
1438 play_pending = false;
1439 playing = false;
1440 stop_dma();
1441
1442 reset_mp3_buffer();
Linus Nielsen Feltzingab042e62002-07-27 00:31:38 +00001443 remove_all_tags();
1444
Björn Stenberga61617f2002-06-26 21:27:17 +00001445 /* Open the next file */
1446 if (mpeg_file >= 0)
1447 close(mpeg_file);
Linus Nielsen Feltzingab042e62002-07-27 00:31:38 +00001448
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001449 if (new_file(-numtracks) < 0) {
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001450 DEBUGF("No more files to play\n");
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001451 filling = false;
Björn Stenberga61617f2002-06-26 21:27:17 +00001452 } else {
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001453 /* Make it read more data */
1454 filling = true;
1455 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
Björn Stenberga61617f2002-06-26 21:27:17 +00001456
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001457 /* Tell the file loading code that we want to
1458 start playing as soon as we have some data */
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001459 play_pending = true;
Linus Nielsen Feltzinge5792d62002-07-25 23:12:41 +00001460
1461 current_track_counter++;
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001462 update_playlist();
Björn Stenberga61617f2002-06-26 21:27:17 +00001463 }
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001464 break;
1465 }
Björn Stenberga61617f2002-06-26 21:27:17 +00001466
Björn Stenberg05704972002-08-14 19:23:34 +00001467 case MPEG_FF_REWIND: {
Hardeep Sidhu98cb6362002-08-30 07:07:57 +00001468 struct mp3entry *id3 = mpeg_current_track();
1469 unsigned int oldtime = id3->elapsed;
1470 unsigned int newtime = oldtime + (int)ev.data;
Björn Stenberg05704972002-08-14 19:23:34 +00001471 int curpos, newpos, diffpos;
1472 DEBUGF("MPEG_FF_REWIND\n");
1473
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001474 id3->elapsed = newtime;
1475
Hardeep Sidhuaa287bb2002-09-17 07:04:43 +00001476 if (id3->vbr)
Björn Stenberg05704972002-08-14 19:23:34 +00001477 {
Hardeep Sidhuaa287bb2002-09-17 07:04:43 +00001478 if (id3->vbrflags & VBR_TOC_FLAG)
1479 {
1480 /* Use the TOC to find the new position */
1481 unsigned int percent, remainder;
1482 int curtoc, nexttoc, plen;
1483
1484 percent = (newtime*100)/id3->length;
1485 if (percent > 99)
1486 percent = 99;
1487
1488 curtoc = id3->toc[percent];
1489
1490 if (percent < 99)
1491 nexttoc = id3->toc[percent+1];
1492 else
1493 nexttoc = 256;
1494
1495 newpos = (id3->filesize/256)*curtoc;
1496
1497 /* Use the remainder to get a more accurate position */
1498 remainder = (newtime*100)%id3->length;
1499 remainder = (remainder*100)/id3->length;
1500 plen = (nexttoc - curtoc)*(id3->filesize/256);
1501 newpos += (plen/100)*remainder;
1502 }
Björn Stenberg05704972002-08-14 19:23:34 +00001503 else
Hardeep Sidhuaa287bb2002-09-17 07:04:43 +00001504 {
1505 /* No TOC exists, estimate the new position */
1506 newpos = (id3->filesize/id3->length)*newtime;
1507 }
Björn Stenberg05704972002-08-14 19:23:34 +00001508 }
1509 else if (id3->bpf && id3->tpf)
Hardeep Sidhu98cb6362002-08-30 07:07:57 +00001510 newpos = (newtime/id3->tpf)*id3->bpf;
Björn Stenberg05704972002-08-14 19:23:34 +00001511 else
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001512 {
Björn Stenberg05704972002-08-14 19:23:34 +00001513 /* Not enough information to FF/Rewind */
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001514 id3->elapsed = oldtime;
Björn Stenberg05704972002-08-14 19:23:34 +00001515 break;
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001516 }
Björn Stenberg05704972002-08-14 19:23:34 +00001517
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001518 if (newpos >= (int)(id3->filesize - id3->id3v1len))
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001519 {
1520 /* Don't seek right to the end of the file so that we can
1521 transition properly to the next song */
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001522 newpos = id3->filesize - id3->id3v1len - 1;
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001523 }
1524 else if (newpos < (int)id3->id3v2len)
1525 {
1526 /* skip past id3v2 tag */
1527 newpos = id3->id3v2len;
1528 }
Hardeep Sidhu754651e2002-08-22 23:01:25 +00001529
Hardeep Sidhuc5385932002-10-04 16:39:02 +00001530 if (mpeg_file >= 0)
1531 curpos = lseek(mpeg_file, 0, SEEK_CUR);
1532 else
1533 curpos = id3->filesize;
Björn Stenberg05704972002-08-14 19:23:34 +00001534
1535 if (num_tracks_in_memory() > 1)
1536 {
1537 /* We have started loading other tracks that need to be
1538 accounted for */
1539 int i = tag_read_idx;
1540 int j = tag_write_idx - 1;
1541
1542 if (j < 0)
1543 j = MAX_ID3_TAGS - 1;
1544
1545 while (i != j)
1546 {
1547 curpos += id3tags[i]->id3.filesize;
1548 i = (i+1) & MAX_ID3_TAGS_MASK;
1549 }
1550 }
1551
1552 diffpos = curpos - newpos;
1553
Hardeep Sidhuf9914b72002-08-26 03:30:31 +00001554 if(!filling && diffpos >= 0 && diffpos < mp3buflen)
Björn Stenberg05704972002-08-14 19:23:34 +00001555 {
Hardeep Sidhu67f95ec2002-10-03 07:28:28 +00001556 int unplayed_space_left, unswapped_space_left;
1557
Björn Stenberg05704972002-08-14 19:23:34 +00001558 /* We are changing to a position that's already in
1559 memory */
1560 mp3buf_read = mp3buf_write - diffpos;
1561 if (mp3buf_read < 0)
1562 {
1563 mp3buf_read += mp3buflen;
1564 }
1565
Hardeep Sidhu67f95ec2002-10-03 07:28:28 +00001566 unplayed_space_left = get_unplayed_space();
1567 unswapped_space_left = get_unswapped_space();
1568
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001569 if (mpeg_file>=0 && unplayed_space_left < low_watermark)
Hardeep Sidhuc6744152002-08-25 05:11:25 +00001570 {
1571 /* We need to load more data before starting */
1572 filling = true;
1573 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1574 play_pending = true;
1575 }
Hardeep Sidhu67f95ec2002-10-03 07:28:28 +00001576 else if (unswapped_space_left > unplayed_space_left)
1577 {
1578 mp3buf_swapwrite = mp3buf_read;
1579 play_pending = true;
1580 }
Hardeep Sidhuc6744152002-08-25 05:11:25 +00001581 else
1582 {
1583 /* resume will start at new position */
1584 init_dma();
1585 }
Björn Stenberg05704972002-08-14 19:23:34 +00001586 }
1587 else
1588 {
1589 /* Move to the new position in the file and start
1590 loading data */
1591 reset_mp3_buffer();
1592
1593 if (num_tracks_in_memory() > 1)
1594 {
1595 /* We have to reload the current track */
1596 close(mpeg_file);
1597 remove_all_non_current_tags();
Hardeep Sidhuc5385932002-10-04 16:39:02 +00001598 mpeg_file = -1;
1599 }
Björn Stenberg05704972002-08-14 19:23:34 +00001600
Hardeep Sidhuc5385932002-10-04 16:39:02 +00001601 if (mpeg_file < 0)
1602 {
Björn Stenberg05704972002-08-14 19:23:34 +00001603 mpeg_file = open(id3->path, O_RDONLY);
1604 if (mpeg_file < 0)
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001605 {
1606 id3->elapsed = oldtime;
Björn Stenberg05704972002-08-14 19:23:34 +00001607 break;
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001608 }
Björn Stenberg05704972002-08-14 19:23:34 +00001609 }
1610
1611 if(-1 == lseek(mpeg_file, newpos, SEEK_SET))
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001612 {
1613 id3->elapsed = oldtime;
Björn Stenberg05704972002-08-14 19:23:34 +00001614 break;
Hardeep Sidhu441f48f2002-08-27 07:19:25 +00001615 }
Björn Stenberg05704972002-08-14 19:23:34 +00001616
1617 filling = true;
1618 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1619
1620 /* Tell the file loading code that we want to start playing
1621 as soon as we have some data */
1622 play_pending = true;
1623 }
1624
Björn Stenberg34486b72002-08-19 11:00:29 +00001625 id3->offset = newpos;
Björn Stenberg05704972002-08-14 19:23:34 +00001626
1627 break;
1628 }
1629
Hardeep Sidhu62bec9e2002-09-10 08:50:40 +00001630 case MPEG_FLUSH_RELOAD: {
1631 int numtracks = num_tracks_in_memory();
1632 bool reload_track = false;
1633
1634 if (numtracks > 1)
1635 {
1636 /* Reload songs */
1637 int next = (tag_read_idx+1) & MAX_ID3_TAGS_MASK;
1638
1639 /* Reset the buffer */
1640 mp3buf_write = mp3buf_swapwrite = id3tags[next]->mempos;
1641
1642 close(mpeg_file);
1643 remove_all_non_current_tags();
1644 mpeg_file = -1;
1645 reload_track = true;
1646 }
1647 else if (numtracks == 1 && mpeg_file < 0)
1648 {
1649 reload_track = true;
1650 }
1651
1652 if(reload_track && new_file(1) >= 0)
1653 {
1654 /* Tell ourselves that we want more data */
1655 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1656 filling = true;
1657 }
1658
1659 break;
1660 }
1661
Björn Stenberg1ac46002002-05-24 12:22:14 +00001662 case MPEG_NEED_DATA:
1663 free_space_left = mp3buf_read - mp3buf_write;
1664
1665 /* We interpret 0 as "empty buffer" */
1666 if(free_space_left <= 0)
Björn Stenberg3c260772002-05-24 15:27:55 +00001667 free_space_left = mp3buflen + free_space_left;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001668
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001669 unplayed_space_left = mp3buflen - free_space_left;
Linus Nielsen Feltzing54a65f72002-07-21 07:12:39 +00001670
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001671 /* Make sure that we don't fill the entire buffer */
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001672 free_space_left -= MPEG_HIGH_WATER;
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001673
Björn Stenbergc4b28502002-07-16 12:18:17 +00001674 /* do we have any more buffer space to fill? */
Linus Nielsen Feltzing0b895072002-07-19 19:07:13 +00001675 if(free_space_left <= MPEG_HIGH_WATER)
Björn Stenberg1ac46002002-05-24 12:22:14 +00001676 {
1677 DEBUGF("0\n");
1678 filling = false;
Björn Stenbergc4b28502002-07-16 12:18:17 +00001679 ata_sleep();
1680 break;
Björn Stenberg1ac46002002-05-24 12:22:14 +00001681 }
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001682
Linus Nielsen Feltzingb605b2e2002-07-31 06:33:48 +00001683 /* Read small chunks while we are below the low water mark */
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001684 if(unplayed_space_left < low_watermark)
Linus Nielsen Feltzingb605b2e2002-07-31 06:33:48 +00001685 amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE,
1686 free_space_left);
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001687 else
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001688 amount_to_read = free_space_left;
Linus Nielsen Feltzingb605b2e2002-07-31 06:33:48 +00001689
1690 /* Don't read more than until the end of the buffer */
Björn Stenberg3c260772002-05-24 15:27:55 +00001691 amount_to_read = MIN(mp3buflen - mp3buf_write, amount_to_read);
Linus Nielsen Feltzing402502f2002-10-14 14:13:13 +00001692
1693 /* Read as much mpeg data as we can fit in the buffer */
Linus Nielsen Feltzing3a25aa42002-05-29 12:25:21 +00001694 if(mpeg_file >= 0)
Björn Stenberg1ac46002002-05-24 12:22:14 +00001695 {
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001696 DEBUGF("R\n");
Linus Nielsen Feltzing1d21ca92002-08-01 08:16:44 +00001697 t1 = current_tick;
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001698 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read);
Linus Nielsen Feltzingce882bb2002-12-05 15:23:46 +00001699#if 0
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001700 if(id3tags[tag_read_idx]->id3.vbr)
Linus Nielsen Feltzingf4233e42002-12-05 12:38:59 +00001701 /* Average bitrate * 1.5 */
1702 recalculate_watermark(
1703 (id3tags[tag_read_idx]->id3.bitrate * 3) / 2);
Linus Nielsen Feltzing2df262c2002-12-05 12:18:22 +00001704 else
1705 recalculate_watermark(
1706 id3tags[tag_read_idx]->id3.bitrate);
Linus Nielsen Feltzingce882bb2002-12-05 15:23:46 +00001707#endif
Linus Nielsen Feltzingc7e36752002-06-05 14:34:05 +00001708 if(len > 0)
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001709 {
Linus Nielsen Feltzing1d21ca92002-08-01 08:16:44 +00001710 t2 = current_tick;
1711 DEBUGF("time: %d\n", t2 - t1);
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001712 DEBUGF("R: %x\n", len);
Linus Nielsen Feltzinga124e872002-06-19 12:44:32 +00001713
Linus Nielsen Feltzing80b285c2002-07-23 15:10:31 +00001714 /* Make sure that the write pointer is at a word
1715 boundary when we reach the end of the file */
Björn Stenberg1ec91da2002-08-14 10:30:18 +00001716 if (len < amount_to_read) {
Linus Nielsen Feltzing2bd519d2002-09-16 13:31:17 +00001717 /* Skip id3v1 tag */
Linus Nielsen Feltzingb3bb0762002-09-18 13:51:08 +00001718 DEBUGF("Skipping ID3v1 tag\n");
Björn Stenberg1ec91da2002-08-14 10:30:18 +00001719 len -= id3tags[tag_read_idx]->id3.id3v1len;
Linus Nielsen Feltzingb3bb0762002-09-18 13:51:08 +00001720 /* The very rare case when the buffer wrapped
1721 inside the tag must be taken care of */
Linus Nielsen Feltzing2bd519d2002-09-16 13:31:17 +00001722 if(len < 0)
1723 len = 0;
Linus Nielsen Feltzing6ce6d462002-10-08 08:02:58 +00001724 }
Linus Nielsen Feltzingb3bb0762002-09-18 13:51:08 +00001725
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001726 mp3buf_write += len;
Linus Nielsen Feltzingb3bb0762002-09-18 13:51:08 +00001727
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001728 if(mp3buf_write >= mp3buflen)
1729 {
1730 mp3buf_write = 0;
1731 DEBUGF("W\n");
1732 }
Björn Stenberg1ac46002002-05-24 12:22:14 +00001733
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001734 /* Tell ourselves that we want more data */
1735 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
Björn Stenberg1ac46002002-05-24 12:22:14 +00001736 }
1737 else
1738 {
Linus Nielsen Feltzingc7e36752002-06-05 14:34:05 +00001739 if(len < 0)
1740 {
1741 DEBUGF("MPEG read error\n");
1742 }
1743
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001744 close(mpeg_file);
Linus Nielsen Feltzing3a25aa42002-05-29 12:25:21 +00001745 mpeg_file = -1;
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001746
Björn Stenberga61617f2002-06-26 21:27:17 +00001747 if(new_file(1) < 0)
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001748 {
1749 /* No more data to play */
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001750 DEBUGF("No more files to play\n");
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001751 filling = false;
1752 }
1753 else
1754 {
1755 /* Tell ourselves that we want more data */
1756 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1757 }
Linus Nielsen Feltzingf779e262002-05-29 10:26:06 +00001758 }
Björn Stenberg1ac46002002-05-24 12:22:14 +00001759 }
1760 break;
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001761
Linus Nielsen Feltzinge4b9dbb2002-07-25 11:51:11 +00001762 case MPEG_TRACK_CHANGE:
Björn Stenbergbcbc7822002-08-08 12:02:17 +00001763 track_change();
Linus Nielsen Feltzinge4b9dbb2002-07-25 11:51:11 +00001764 break;
1765
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001766 case SYS_USB_CONNECTED:
1767 stop_playing();
Björn Stenbergcd225732002-08-11 09:17:47 +00001768#ifndef SIMULATOR
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001769
1770 /* Tell the USB thread that we are safe */
1771 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1772 usb_acknowledge(SYS_USB_CONNECTED_ACK);
Linus Nielsen Feltzing392f3852002-06-29 23:01:10 +00001773
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001774 /* Wait until the USB cable is extracted again */
1775 usb_wait_for_disconnect(&mpeg_queue);
Björn Stenbergcd225732002-08-11 09:17:47 +00001776#endif
Linus Nielsen Feltzing4e46ac72002-07-18 21:02:55 +00001777 break;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001778
1779#ifdef HAVE_MAS3587F
1780 case MPEG_INIT_RECORDING:
1781 init_recording();
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001782 init_recording_done = true;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001783 break;
1784#endif
1785 }
1786#ifdef HAVE_MAS3587F
Björn Stenberg1ac46002002-05-24 12:22:14 +00001787 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001788 else
1789 {
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001790 yield();
1791 if(!queue_empty(&mpeg_queue))
1792 {
1793 queue_wait(&mpeg_queue, &ev);
1794 switch(ev.id)
1795 {
1796 case MPEG_RECORD:
1797 DEBUGF("Recording...\n");
Linus Nielsen Feltzing5e15aee2002-11-20 11:47:32 +00001798 reset_mp3_buffer();
1799 start_recording();
1800 demand_irq_enable(true);
Linus Nielsen Feltzing6100dd02002-11-20 00:02:52 +00001801 mpeg_file = open((char *)ev.data,
Linus Nielsen Feltzingf844ab22002-11-11 22:43:41 +00001802 O_WRONLY | O_TRUNC | O_CREAT);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001803 if(mpeg_file < 0)
1804 panicf("recfile: %d", mpeg_file);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001805 break;
1806
1807 case MPEG_STOP:
1808 DEBUGF("MPEG_STOP\n");
Linus Nielsen Feltzing6a240592002-11-24 11:49:17 +00001809 demand_irq_enable(false);
Linus Nielsen Feltzing2c0b72f2002-11-25 00:02:54 +00001810 stop_recording();
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001811
1812 /* Save the remaining data in the buffer */
1813 stop_pending = true;
1814 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1815 break;
Linus Nielsen Feltzing1e524ab2002-11-11 13:24:41 +00001816
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001817 case MPEG_STOP_DONE:
1818 DEBUGF("MPEG_STOP_DONE\n");
1819
1820 if(mpeg_file >= 0)
1821 close(mpeg_file);
Linus Nielsen Feltzing77d9c7c2002-11-20 22:23:20 +00001822 mpeg_file = -1;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001823
Linus Nielsen Feltzing6a240592002-11-24 11:49:17 +00001824#ifdef DEBUG1
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001825 {
Linus Nielsen Feltzingd7033892002-11-19 21:07:44 +00001826 int i;
1827 for(i = 0;i < 512;i++)
1828 {
1829 DEBUGF("%d - %d us (%d bytes)\n",
1830 timing_info[i*2],
1831 (timing_info[i*2+1] & 0xffff) *
1832 10000 / 13824,
1833 timing_info[i*2+1] >> 16);
1834 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001835 }
Linus Nielsen Feltzingd7033892002-11-19 21:07:44 +00001836#endif
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001837 break;
1838
1839 case MPEG_SAVE_DATA:
1840 amount_to_save = mp3buf_write - mp3buf_read;
1841
1842 /* If the result is negative, the write index has
1843 wrapped */
1844 if(amount_to_save < 0)
1845 {
Linus Nielsen Feltzing1521a1c2002-11-13 23:22:40 +00001846 amount_to_save += mp3buflen;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001847 }
Linus Nielsen Feltzing5e15aee2002-11-20 11:47:32 +00001848
1849 DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write);
1850 DEBUGF("ats: %x\n", amount_to_save);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001851 /* Save data only if the buffer is getting full,
1852 or if we should stop recording */
1853 if(amount_to_save)
1854 {
1855 if(mp3buflen - amount_to_save < MPEG_LOW_WATER ||
1856 stop_pending)
1857 {
Linus Nielsen Feltzing5e15aee2002-11-20 11:47:32 +00001858 int rc;
Linus Nielsen Feltzing6a240592002-11-24 11:49:17 +00001859
Linus Nielsen Feltzing1521a1c2002-11-13 23:22:40 +00001860 /* Only save up to the end of the buffer */
1861 writelen = MIN(amount_to_save,
1862 mp3buflen - mp3buf_read);
Linus Nielsen Feltzing5e15aee2002-11-20 11:47:32 +00001863
1864 DEBUGF("wrl: %x\n", writelen);
1865 rc = write(mpeg_file, mp3buf + mp3buf_read,
1866 writelen);
1867 DEBUGF("rc: %x\n", rc);
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001868
1869 mp3buf_read += amount_to_save;
1870 if(mp3buf_read >= mp3buflen)
1871 mp3buf_read = 0;
1872
1873 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1874 }
Linus Nielsen Feltzing6a240592002-11-24 11:49:17 +00001875 else
1876 {
1877 saving = false;
1878 }
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001879 }
1880 else
1881 {
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001882 /* We have saved all data,
1883 time to stop for real */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001884 if(stop_pending)
1885 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
Linus Nielsen Feltzing4432d372002-11-24 22:50:54 +00001886 saving = false;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001887 }
1888 break;
1889
1890 case MPEG_INIT_PLAYBACK:
1891 init_playback();
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001892 init_playback_done = true;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001893 break;
1894 }
1895 }
1896 }
1897#endif
Björn Stenberg1ac46002002-05-24 12:22:14 +00001898 }
1899}
1900
1901static void setup_sci0(void)
1902{
1903 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0 */
1904 PBCR1 = (PBCR1 & 0x0cff) | 0x1200;
1905
1906 /* Set PB12 to output */
1907 PBIOR |= 0x1000;
1908
1909 /* Disable serial port */
1910 SCR0 = 0x00;
1911
1912 /* Synchronous, no prescale */
1913 SMR0 = 0x80;
1914
1915 /* Set baudrate 1Mbit/s */
1916 BRR0 = 0x03;
1917
1918 /* use SCK as serial clock output */
1919 SCR0 = 0x01;
1920
1921 /* Clear FER and PER */
1922 SSR0 &= 0xe7;
1923
1924 /* Set interrupt ITU2 and SCI0 priority to 0 */
1925 IPRD &= 0x0ff0;
1926
Björn Stenberg1ac46002002-05-24 12:22:14 +00001927 /* set PB15 and PB14 to inputs */
1928 PBIOR &= 0x7fff;
1929 PBIOR &= 0xbfff;
1930
Björn Stenberg1ac46002002-05-24 12:22:14 +00001931 /* Enable End of DMA interrupt at prio 8 */
1932 IPRC = (IPRC & 0xf0ff) | 0x0800;
1933
1934 /* Enable Tx (only!) */
1935 SCR0 |= 0x20;
1936}
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +00001937#endif /* SIMULATOR */
Björn Stenberg1ac46002002-05-24 12:22:14 +00001938
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001939#ifdef SIMULATOR
1940static struct mp3entry taginfo;
1941#endif
1942
Björn Stenberg6224cdb2002-08-16 14:41:47 +00001943struct mp3entry* mpeg_current_track()
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +00001944{
Linus Nielsen Feltzing42faf562002-07-26 14:32:24 +00001945#ifdef SIMULATOR
1946 return &taginfo;
1947#else
1948 if(num_tracks_in_memory())
1949 return &(id3tags[tag_read_idx]->id3);
1950 else
1951 return NULL;
1952#endif
Linus Nielsen Feltzingcb30e542002-06-30 14:36:58 +00001953}
Björn Stenberg3c260772002-05-24 15:27:55 +00001954
Linus Nielsen Feltzinge5792d62002-07-25 23:12:41 +00001955bool mpeg_has_changed_track(void)
1956{
1957 if(last_track_counter != current_track_counter)
1958 {
1959 last_track_counter = current_track_counter;
1960 return true;
1961 }
1962 return false;
1963}
1964
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001965#ifdef HAVE_MAS3587F
1966void mpeg_init_recording(void)
1967{
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001968 init_recording_done = false;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001969 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL);
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001970
1971 while(!init_recording_done)
1972 yield();
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001973}
1974
1975void mpeg_init_playback(void)
1976{
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001977 init_playback_done = false;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001978 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL);
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001979
1980 while(!init_playback_done)
1981 yield();
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001982}
1983
1984static void init_recording(void)
1985{
1986 unsigned long val;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001987 int rc;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001988
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001989 stop_playing();
Linus Nielsen Feltzing62c3ba82002-12-05 00:28:28 +00001990 is_playing = false;
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00001991 paused = false;
1992
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001993 reset_mp3_buffer();
1994 remove_all_tags();
1995
1996 if(mpeg_file >= 0)
1997 close(mpeg_file);
Linus Nielsen Feltzing77d9c7c2002-11-20 22:23:20 +00001998 mpeg_file = -1;
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00001999
2000 /* Init the recording variables */
Linus Nielsen Feltzing893095d2002-11-10 16:37:26 +00002001 is_recording = false;
2002
Linus Nielsen Feltzingc833a812002-11-24 00:23:49 +00002003 mas_reset();
2004
2005 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2006 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
2007 if(rc < 0)
2008 panicf(