summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/mpeg.h7
-rw-r--r--firmware/mpeg.c582
2 files changed, 405 insertions, 184 deletions
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index 63eecf51db..bbace28ecd 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -32,6 +32,8 @@
32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000 32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000
33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000 33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000
34 34
35#define MPEG_MAX_PRERECORD_SECONDS 30
36
35/* For ID3 info and VBR header */ 37/* For ID3 info and VBR header */
36#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500) 38#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500)
37 39
@@ -89,7 +91,7 @@ void mpeg_record(char *filename);
89void mpeg_new_file(char *filename); 91void mpeg_new_file(char *filename);
90void mpeg_set_recording_options(int frequency, int quality, 92void mpeg_set_recording_options(int frequency, int quality,
91 int source, int channel_mode, 93 int source, int channel_mode,
92 bool editable); 94 bool editable, int prerecord_time);
93void mpeg_set_recording_gain(int left, int right, bool use_mic); 95void mpeg_set_recording_gain(int left, int right, bool use_mic);
94unsigned long mpeg_recorded_time(void); 96unsigned long mpeg_recorded_time(void);
95unsigned long mpeg_num_recorded_bytes(void); 97unsigned long mpeg_num_recorded_bytes(void);
@@ -123,7 +125,8 @@ void mpeg_error_clear(void);
123#define MPEG_STATUS_PLAY 1 125#define MPEG_STATUS_PLAY 1
124#define MPEG_STATUS_PAUSE 2 126#define MPEG_STATUS_PAUSE 2
125#define MPEG_STATUS_RECORD 4 127#define MPEG_STATUS_RECORD 4
126#define MPEG_STATUS_ERROR 8 128#define MPEG_STATUS_PRERECORD 8
129#define MPEG_STATUS_ERROR 16
127 130
128#define MPEGERR_DISK_FULL 1 131#define MPEGERR_DISK_FULL 1
129 132
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 80e871597e..43da221800 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -44,6 +44,7 @@ extern void bitswap(unsigned char *data, int length);
44#ifdef HAVE_MAS3587F 44#ifdef HAVE_MAS3587F
45static void init_recording(void); 45static void init_recording(void);
46static void init_playback(void); 46static void init_playback(void);
47static void start_prerecording(void);
47static void start_recording(void); 48static void start_recording(void);
48static void stop_recording(void); 49static void stop_recording(void);
49static int get_unsaved_space(void); 50static int get_unsaved_space(void);
@@ -497,6 +498,17 @@ static char recording_filename[MAX_PATH];
497static int rec_frequency_index; /* For create_xing_header() calls */ 498static int rec_frequency_index; /* For create_xing_header() calls */
498static int rec_version_index; /* For create_xing_header() calls */ 499static int rec_version_index; /* For create_xing_header() calls */
499static bool disable_xing_header; /* When splitting files */ 500static bool disable_xing_header; /* When splitting files */
501
502static bool prerecording; /* True if prerecording is enabled */
503static bool is_prerecording; /* True if we are prerecording */
504static int prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS]; /* Array of buffer
505 indexes for each
506 prerecorded
507 second */
508static int prerecord_index; /* Current index in the prerecord buffer */
509static int prerecording_max_seconds; /* Max number of seconds to store */
510static int prerecord_count; /* Number of seconds in the prerecord buffer */
511static int prerecord_timeout; /* The tick count of the next prerecord data store */
500#endif 512#endif
501 513
502static int mpeg_file; 514static int mpeg_file;
@@ -865,17 +877,38 @@ static void dma_tick(void)
865 877
866 num_rec_bytes += i; 878 num_rec_bytes += i;
867 879
868 /* Signal to save the data if we are running out of buffer 880 if(is_prerecording)
869 space */ 881 {
870 num_bytes = mp3buf_write - mp3buf_read; 882 if(TIME_AFTER(current_tick, prerecord_timeout))
871 if(num_bytes < 0) 883 {
872 num_bytes += mp3buflen; 884 prerecord_timeout = current_tick + HZ;
885
886 /* Store the write pointer every second */
887 prerecord_buffer[prerecord_index++] = mp3buf_write;
888
889 /* Wrap if necessary */
890 if(prerecord_index == prerecording_max_seconds)
891 prerecord_index = 0;
873 892
874 if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving) 893 /* Update the number of seconds recorded */
894 if(prerecord_count < prerecording_max_seconds)
895 prerecord_count++;
896 }
897 }
898 else
875 { 899 {
876 saving = true; 900 /* Signal to save the data if we are running out of buffer
877 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); 901 space */
878 wake_up_thread(); 902 num_bytes = mp3buf_write - mp3buf_read;
903 if(num_bytes < 0)
904 num_bytes += mp3buflen;
905
906 if(mp3buflen - num_bytes < MPEG_RECORDING_LOW_WATER && !saving)
907 {
908 saving = true;
909 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
910 wake_up_thread();
911 }
879 } 912 }
880 } 913 }
881 } 914 }
@@ -1887,20 +1920,84 @@ static void mpeg_thread(void)
1887 switch(ev.id) 1920 switch(ev.id)
1888 { 1921 {
1889 case MPEG_RECORD: 1922 case MPEG_RECORD:
1890 DEBUGF("Recording...\n"); 1923 if(is_prerecording)
1891 reset_mp3_buffer(); 1924 {
1925 int startpos, i;
1926
1927 /* Go back prerecord_count seconds in the buffer */
1928 startpos = prerecord_index - prerecord_count;
1929 if(startpos < 0)
1930 startpos += prerecording_max_seconds;
1931
1932 /* Read the mp3 buffer pointer from the prerecord buffer */
1933 startpos = prerecord_buffer[startpos];
1934
1935 DEBUGF("Start looking at address %x (%x)\n",
1936 mp3buf+startpos, startpos);
1937
1938 saved_header = get_last_recorded_header();
1939
1940 mem_find_next_frame(startpos, &offset, 5000,
1941 saved_header);
1942
1943 mp3buf_read = startpos + offset;
1944
1945 DEBUGF("New mp3buf_read address: %x (%x)\n",
1946 mp3buf+mp3buf_read, mp3buf_read);
1892 1947
1893 /* Advance the write pointer to make 1948 /* Make room for headers */
1894 room for an ID3 tag plus a VBR header */ 1949 mp3buf_read -= MPEG_RESERVED_HEADER_SPACE;
1895 mp3buf_write = MPEG_RESERVED_HEADER_SPACE; 1950 if(mp3buf_read < 0)
1896 memset(mp3buf, 0, MPEG_RESERVED_HEADER_SPACE); 1951 {
1952 /* Clear the bottom half */
1953 memset(mp3buf, 0,
1954 mp3buf_read + MPEG_RESERVED_HEADER_SPACE);
1897 1955
1898 /* Insert the ID3 header */ 1956 /* And the top half */
1899 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); 1957 mp3buf_read += mp3buflen;
1958 memset(mp3buf + mp3buf_read, 0,
1959 mp3buflen - mp3buf_read);
1960 }
1961 else
1962 {
1963 memset(mp3buf + mp3buf_read, 0,
1964 MPEG_RESERVED_HEADER_SPACE);
1965 }
1966
1967 /* Copy the empty ID3 header */
1968 startpos = mp3buf_read;
1969 for(i = 0;i < (int)sizeof(empty_id3_header);i++)
1970 {
1971 mp3buf[startpos++] = empty_id3_header[i];
1972 if(startpos == mp3buflen)
1973 startpos = 0;
1974 }
1975
1976 DEBUGF("New mp3buf_read address (reservation): %x\n",
1977 mp3buf+mp3buf_read);
1978
1979 DEBUGF("Prerecording...\n");
1980 }
1981 else
1982 {
1983 reset_mp3_buffer();
1984
1985 num_rec_bytes = 0;
1986
1987 /* Advance the write pointer to make
1988 room for an ID3 tag plus a VBR header */
1989 mp3buf_write = MPEG_RESERVED_HEADER_SPACE;
1990 memset(mp3buf, 0, MPEG_RESERVED_HEADER_SPACE);
1991
1992 /* Insert the ID3 header */
1993 memcpy(mp3buf, empty_id3_header,
1994 sizeof(empty_id3_header));
1995
1996 DEBUGF("Recording...\n");
1997 }
1900 1998
1901 start_recording(); 1999 start_recording();
1902 demand_irq_enable(true); 2000
1903
1904 mpeg_file = open(recording_filename, O_WRONLY|O_CREAT); 2001 mpeg_file = open(recording_filename, O_WRONLY|O_CREAT);
1905 2002
1906 if(mpeg_file < 0) 2003 if(mpeg_file < 0)
@@ -1910,14 +2007,13 @@ static void mpeg_thread(void)
1910 2007
1911 case MPEG_STOP: 2008 case MPEG_STOP:
1912 DEBUGF("MPEG_STOP\n"); 2009 DEBUGF("MPEG_STOP\n");
1913 demand_irq_enable(false);
1914 2010
1915 /* Store the last recorded header for later use by the 2011 /* Store the last recorded header for later use by the
1916 Xing header generation */ 2012 Xing header generation */
1917 saved_header = get_last_recorded_header(); 2013 saved_header = get_last_recorded_header();
1918 2014
1919 stop_recording(); 2015 stop_recording();
1920 2016
1921 /* Save the remaining data in the buffer */ 2017 /* Save the remaining data in the buffer */
1922 stop_pending = true; 2018 stop_pending = true;
1923 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); 2019 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
@@ -1942,6 +2038,11 @@ static void mpeg_thread(void)
1942 if(num_recorded_frames == 0x7ffff) 2038 if(num_recorded_frames == 0x7ffff)
1943 num_recorded_frames = 0; 2039 num_recorded_frames = 0;
1944 2040
2041 /* Also, if we have been prerecording, the frame count
2042 will be wrong */
2043 if(prerecording)
2044 num_recorded_frames = 0;
2045
1945 /* saved_header is saved right before stopping 2046 /* saved_header is saved right before stopping
1946 the MAS */ 2047 the MAS */
1947 framelen = create_xing_header(mpeg_file, 0, 2048 framelen = create_xing_header(mpeg_file, 0,
@@ -1970,6 +2071,11 @@ static void mpeg_thread(void)
1970 } 2071 }
1971 } 2072 }
1972#endif 2073#endif
2074
2075 if(prerecording)
2076 {
2077 start_prerecording();
2078 }
1973 mpeg_stop_done = true; 2079 mpeg_stop_done = true;
1974 break; 2080 break;
1975 2081
@@ -2117,7 +2223,6 @@ static void mpeg_thread(void)
2117 if(errno == ENOSPC) 2223 if(errno == ENOSPC)
2118 { 2224 {
2119 mpeg_errno = MPEGERR_DISK_FULL; 2225 mpeg_errno = MPEGERR_DISK_FULL;
2120 demand_irq_enable(false);
2121 stop_recording(); 2226 stop_recording();
2122 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0); 2227 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
2123 break; 2228 break;
@@ -2161,18 +2266,22 @@ static void mpeg_thread(void)
2161 break; 2266 break;
2162 2267
2163 case SYS_USB_CONNECTED: 2268 case SYS_USB_CONNECTED:
2164 is_playing = false; 2269 /* We can safely go to USB mode if no recording
2165 paused = false; 2270 is taking place */
2166 stop_playing(); 2271 if((!is_recording || is_prerecording) && mpeg_stop_done)
2167#ifndef SIMULATOR 2272 {
2273 /* Even if we aren't recording, we still call this
2274 function, to put the MAS in monitoring mode,
2275 to save power. */
2276 stop_recording();
2168 2277
2169 /* Tell the USB thread that we are safe */ 2278 /* Tell the USB thread that we are safe */
2170 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n"); 2279 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
2171 usb_acknowledge(SYS_USB_CONNECTED_ACK); 2280 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2172 2281
2173 /* Wait until the USB cable is extracted again */ 2282 /* Wait until the USB cable is extracted again */
2174 usb_wait_for_disconnect(&mpeg_queue); 2283 usb_wait_for_disconnect(&mpeg_queue);
2175#endif 2284 }
2176 break; 2285 break;
2177 } 2286 }
2178 } 2287 }
@@ -2245,22 +2354,90 @@ bool mpeg_has_changed_track(void)
2245} 2354}
2246 2355
2247#ifdef HAVE_MAS3587F 2356#ifdef HAVE_MAS3587F
2248void mpeg_init_recording(void) 2357void mpeg_init_playback(void)
2249{ 2358{
2250 init_recording_done = false; 2359 init_playback_done = false;
2251 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL); 2360 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL);
2252 2361
2253 while(!init_recording_done) 2362 while(!init_playback_done)
2254 sleep_thread(); 2363 sleep_thread();
2255 wake_up_thread(); 2364 wake_up_thread();
2256} 2365}
2257 2366
2258void mpeg_init_playback(void) 2367static void init_playback(void)
2259{ 2368{
2260 init_playback_done = false; 2369 unsigned long val;
2261 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, NULL); 2370 int rc;
2262 2371
2263 while(!init_playback_done) 2372 if(mpeg_mode == MPEG_ENCODER)
2373 stop_recording();
2374
2375 stop_dma();
2376
2377 mas_reset();
2378
2379 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2380 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
2381 if(rc < 0)
2382 panicf("mas_ctrl_w: %d", rc);
2383
2384 /* Stop the current application */
2385 val = 0;
2386 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2387 do
2388 {
2389 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2390 } while(val);
2391
2392 /* Enable the D/A Converter */
2393 mas_codec_writereg(0x0, 0x0001);
2394
2395 /* ADC scale 0%, DSP scale 100% */
2396 mas_codec_writereg(6, 0x0000);
2397 mas_codec_writereg(7, 0x4000);
2398
2399 /* Disable SDO and SDI */
2400 val = 0x0d;
2401 mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
2402
2403 /* Set Demand mode and validate all settings */
2404 val = 0x25;
2405 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
2406
2407 /* Start the Layer2/3 decoder applications */
2408 val = 0x0c;
2409 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2410 do
2411 {
2412 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2413 } while((val & 0x0c) != 0x0c);
2414
2415 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
2416
2417 mpeg_mode = MPEG_DECODER;
2418
2419 /* set IRQ6 to edge detect */
2420 ICR |= 0x02;
2421
2422 /* set IRQ6 prio 8 */
2423 IPRB = ( IPRB & 0xff0f ) | 0x0080;
2424
2425 DEBUGF("MAS Decoding application started\n");
2426}
2427
2428/****************************************************************************
2429 **
2430 **
2431 ** Recording functions
2432 **
2433 **
2434 ***************************************************************************/
2435void mpeg_init_recording(void)
2436{
2437 init_recording_done = false;
2438 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, NULL);
2439
2440 while(!init_recording_done)
2264 sleep_thread(); 2441 sleep_thread();
2265 wake_up_thread(); 2442 wake_up_thread();
2266} 2443}
@@ -2270,6 +2447,9 @@ static void init_recording(void)
2270 unsigned long val; 2447 unsigned long val;
2271 int rc; 2448 int rc;
2272 2449
2450 /* Disable IRQ6 */
2451 IPRB &= 0xff0f;
2452
2273 stop_playing(); 2453 stop_playing();
2274 is_playing = false; 2454 is_playing = false;
2275 paused = false; 2455 paused = false;
@@ -2283,6 +2463,9 @@ static void init_recording(void)
2283 2463
2284 /* Init the recording variables */ 2464 /* Init the recording variables */
2285 is_recording = false; 2465 is_recording = false;
2466 is_prerecording = false;
2467
2468 mpeg_stop_done = true;
2286 2469
2287 mas_reset(); 2470 mas_reset();
2288 2471
@@ -2324,7 +2507,7 @@ static void init_recording(void)
2324 2507
2325 /* No mute */ 2508 /* No mute */
2326 val = 0; 2509 val = 0;
2327 mas_writemem(MAS_BANK_D0, 0x7f9, &val, 1); 2510 mas_writemem(MAS_BANK_D0, 0x7f9, &val, 1);
2328 2511
2329 /* Set Demand mode, no monitoring and validate all settings */ 2512 /* Set Demand mode, no monitoring and validate all settings */
2330 val = 0x125; 2513 val = 0x125;
@@ -2345,70 +2528,16 @@ static void init_recording(void)
2345 Now let's wait for some data to be encoded. */ 2528 Now let's wait for some data to be encoded. */
2346 sleep(20); 2529 sleep(20);
2347 2530
2348 /* Disable IRQ6 */ 2531 /* Now set it to Monitoring mode as default, saves power */
2349 IPRB &= 0xff0f; 2532 val = 0x525;
2533 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1);
2350 2534
2351 mpeg_mode = MPEG_ENCODER; 2535 mpeg_mode = MPEG_ENCODER;
2352 2536
2353 DEBUGF("MAS Recording application started\n"); 2537 DEBUGF("MAS Recording application started\n");
2354}
2355
2356static void init_playback(void)
2357{
2358 unsigned long val;
2359 int rc;
2360
2361 stop_dma();
2362
2363 mas_reset();
2364
2365 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2366 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
2367 if(rc < 0)
2368 panicf("mas_ctrl_w: %d", rc);
2369
2370 /* Stop the current application */
2371 val = 0;
2372 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2373 do
2374 {
2375 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2376 } while(val);
2377
2378 /* Enable the D/A Converter */
2379 mas_codec_writereg(0x0, 0x0001);
2380
2381 /* ADC scale 0%, DSP scale 100% */
2382 mas_codec_writereg(6, 0x0000);
2383 mas_codec_writereg(7, 0x4000);
2384
2385 /* Disable SDO and SDI */
2386 val = 0x0d;
2387 mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
2388
2389 /* Set Demand mode and validate all settings */
2390 val = 0x25;
2391 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
2392
2393 /* Start the Layer2/3 decoder applications */
2394 val = 0x0c;
2395 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2396 do
2397 {
2398 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2399 } while((val & 0x0c) != 0x0c);
2400
2401 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
2402
2403 mpeg_mode = MPEG_DECODER;
2404
2405 /* set IRQ6 to edge detect */
2406 ICR |= 0x02;
2407
2408 /* set IRQ6 prio 8 */
2409 IPRB = ( IPRB & 0xff0f ) | 0x0080;
2410 2538
2411 DEBUGF("MAS Decoding application started\n"); 2539 /* At this point, all settings are the reset MAS defaults, next thing is to
2540 call mpeg_set_recording_options(). */
2412} 2541}
2413 2542
2414void mpeg_record(char *filename) 2543void mpeg_record(char *filename)
@@ -2418,53 +2547,109 @@ void mpeg_record(char *filename)
2418 strncpy(recording_filename, filename, MAX_PATH - 1); 2547 strncpy(recording_filename, filename, MAX_PATH - 1);
2419 recording_filename[MAX_PATH - 1] = 0; 2548 recording_filename[MAX_PATH - 1] = 0;
2420 2549
2421 num_rec_bytes = 0;
2422 disable_xing_header = false; 2550 disable_xing_header = false;
2423 queue_post(&mpeg_queue, MPEG_RECORD, NULL); 2551 queue_post(&mpeg_queue, MPEG_RECORD, NULL);
2424} 2552}
2425 2553
2426static void start_recording(void) 2554static void start_prerecording(void)
2427{ 2555{
2428 unsigned long val; 2556 unsigned long val;
2429 2557
2430 num_recorded_frames = 0; 2558 DEBUGF("Starting prerecording\n");
2431 2559
2432 /* Stop monitoring and record for real */ 2560 prerecord_index = 0;
2561 prerecord_count = 0;
2562 prerecord_timeout = current_tick + HZ;
2563 memset(prerecord_buffer, 0, sizeof(prerecord_buffer));
2564 reset_mp3_buffer();
2565
2566 is_prerecording = true;
2567
2568 /* Stop monitoring and start the encoder */
2433 mas_readmem(MAS_BANK_D0, 0x7f1, &val, 1); 2569 mas_readmem(MAS_BANK_D0, 0x7f1, &val, 1);
2434 val &= ~(1 << 10); 2570 val &= ~(1 << 10);
2435 val |= 1; 2571 val |= 1;
2436 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1); 2572 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1);
2573 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f1, %x)\n", val);
2437 2574
2438 /* Wait until the DSP has accepted the settings */ 2575 /* Wait until the DSP has accepted the settings */
2439 do 2576 do
2440 { 2577 {
2441 mas_readmem(MAS_BANK_D0, 0x7f1, &val,1); 2578 mas_readmem(MAS_BANK_D0, 0x7f1, &val,1);
2442 } while(val & 1); 2579 } while(val & 1);
2443
2444 sleep(20);
2445 2580
2446 /* Store the current time */ 2581 sleep(20);
2447 record_start_time = current_tick;
2448 2582
2449 is_recording = true; 2583 is_recording = true;
2450 stop_pending = false; 2584 stop_pending = false;
2451 saving = false; 2585 saving = false;
2586
2587 demand_irq_enable(true);
2588}
2589
2590static void start_recording(void)
2591{
2592 unsigned long val;
2593
2594 num_recorded_frames = 0;
2595
2596 if(is_prerecording)
2597 {
2598 /* This will make the IRQ handler start recording
2599 for real, i.e send MPEG_SAVE_DATA messages when
2600 the buffer is full */
2601 is_prerecording = false;
2602 }
2603 else
2604 {
2605 /* If prerecording is off, we need to stop the monitoring
2606 and start the encoder */
2607 mas_readmem(MAS_BANK_D0, 0x7f1, &val, 1);
2608 val &= ~(1 << 10);
2609 val |= 1;
2610 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1);
2611 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f1, %x)\n", val);
2612
2613 /* Wait until the DSP has accepted the settings */
2614 do
2615 {
2616 mas_readmem(MAS_BANK_D0, 0x7f1, &val,1);
2617 } while(val & 1);
2618
2619 sleep(20);
2620 }
2621
2622 is_recording = true;
2623 stop_pending = false;
2624 saving = false;
2625
2626 /* Store the current time */
2627 if(prerecording)
2628 record_start_time = current_tick - prerecord_count * HZ;
2629 else
2630 record_start_time = current_tick;
2631
2632 demand_irq_enable(true);
2452} 2633}
2453 2634
2454static void stop_recording(void) 2635static void stop_recording(void)
2455{ 2636{
2456 unsigned long val; 2637 unsigned long val;
2457 2638
2458 is_recording = false; 2639 demand_irq_enable(false);
2459 2640
2641 is_recording = false;
2642 is_prerecording = false;
2643
2460 /* Read the number of frames recorded */ 2644 /* Read the number of frames recorded */
2461 mas_readmem(MAS_BANK_D0, 0xfd0, &num_recorded_frames, 1); 2645 mas_readmem(MAS_BANK_D0, 0xfd0, &num_recorded_frames, 1);
2462 2646
2463 /* Start monitoring */ 2647 /* Start monitoring */
2464 mas_readmem(MAS_BANK_D0, 0x7f1, &val, 1); 2648 mas_readmem(MAS_BANK_D0, 0x7f1, &val, 1);
2465 val |= (1 << 10) | 1; 2649 val |= (1 << 10) | 1;
2466 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1); 2650 mas_writemem(MAS_BANK_D0, 0x7f1, &val, 1);
2467 2651 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f1, %x)\n", val);
2652
2468 /* Wait until the DSP has accepted the settings */ 2653 /* Wait until the DSP has accepted the settings */
2469 do 2654 do
2470 { 2655 {
@@ -2474,6 +2659,82 @@ static void stop_recording(void)
2474 drain_dma_buffer(); 2659 drain_dma_buffer();
2475} 2660}
2476 2661
2662void mpeg_set_recording_options(int frequency, int quality,
2663 int source, int channel_mode,
2664 bool editable, int prerecord_time)
2665{
2666 bool is_mpeg1;
2667 unsigned long val;
2668
2669 is_mpeg1 = (frequency < 3)?true:false;
2670
2671 rec_version_index = is_mpeg1?3:2;
2672 rec_frequency_index = frequency % 3;
2673
2674 val = (quality << 17) |
2675 (rec_frequency_index << 10) |
2676 ((is_mpeg1?1:0) << 9) |
2677 (1 << 8) | /* CRC on */
2678 (((channel_mode * 2 + 1) & 3) << 6) |
2679 (1 << 5) /* MS-stereo */ |
2680 (1 << 2) /* Is an original */;
2681 mas_writemem(MAS_BANK_D0, 0x7f0, &val,1);
2682
2683 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val);
2684
2685 val = editable?4:0;
2686 mas_writemem(MAS_BANK_D0, 0x7f9, &val,1);
2687
2688 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f9, %x)\n", val);
2689
2690 val = (((source < 2)?1:2) << 8) | /* Input select */
2691 (1 << 5) | /* SDO strobe invert */
2692 ((is_mpeg1?0:1) << 3) |
2693 (1 << 2) | /* Inverted SIBC clock signal */
2694 1; /* Validate */
2695 mas_writemem(MAS_BANK_D0, 0x7f1, &val,1);
2696
2697 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f1, %x)\n", val);
2698
2699 drain_dma_buffer();
2700
2701 if(source == 0) /* Mic */
2702 {
2703 /* Copy left channel to right (mono mode) */
2704 mas_codec_writereg(8, 0x8000);
2705 }
2706 else
2707 {
2708 /* Stereo input mode */
2709 mas_codec_writereg(8, 0);
2710 }
2711
2712 prerecording_max_seconds = prerecord_time;
2713 if(prerecording_max_seconds)
2714 {
2715 prerecording = true;
2716 start_prerecording();
2717 }
2718 else
2719 {
2720 prerecording = false;
2721 is_prerecording = false;
2722 is_recording = false;
2723 }
2724}
2725
2726/* If use_mic is true, the left gain is used */
2727void mpeg_set_recording_gain(int left, int right, bool use_mic)
2728{
2729 /* Enable both left and right A/D */
2730 mas_codec_writereg(0x0,
2731 (left << 12) |
2732 (right << 8) |
2733 (left << 4) |
2734 (use_mic?0x0008:0) | /* Connect left A/D to mic */
2735 0x0007);
2736}
2737
2477void mpeg_new_file(char *filename) 2738void mpeg_new_file(char *filename)
2478{ 2739{
2479 mpeg_errno = 0; 2740 mpeg_errno = 0;
@@ -2492,16 +2753,37 @@ void mpeg_new_file(char *filename)
2492 2753
2493unsigned long mpeg_recorded_time(void) 2754unsigned long mpeg_recorded_time(void)
2494{ 2755{
2756 if(is_prerecording)
2757 return prerecord_count * HZ;
2758
2495 if(is_recording) 2759 if(is_recording)
2496 return current_tick - record_start_time; 2760 return current_tick - record_start_time;
2497 else 2761
2498 return 0; 2762 return 0;
2499} 2763}
2500 2764
2501unsigned long mpeg_num_recorded_bytes(void) 2765unsigned long mpeg_num_recorded_bytes(void)
2502{ 2766{
2767 int num_bytes;
2768 int index;
2769
2503 if(is_recording) 2770 if(is_recording)
2504 return num_rec_bytes; 2771 {
2772 if(is_prerecording)
2773 {
2774 index = prerecord_index - prerecord_count;
2775 if(index < 0)
2776 index += prerecording_max_seconds;
2777
2778 num_bytes = mp3buf_write - prerecord_buffer[index];
2779 if(num_bytes < 0)
2780 num_bytes += mp3buflen;
2781
2782 return num_bytes;;
2783 }
2784 else
2785 return num_rec_bytes;
2786 }
2505 else 2787 else
2506 return 0; 2788 return 0;
2507} 2789}
@@ -2660,8 +2942,11 @@ int mpeg_status(void)
2660 ret |= MPEG_STATUS_PAUSE; 2942 ret |= MPEG_STATUS_PAUSE;
2661 2943
2662#ifdef HAVE_MAS3587F 2944#ifdef HAVE_MAS3587F
2663 if(is_recording) 2945 if(is_recording && !is_prerecording)
2664 ret |= MPEG_STATUS_RECORD; 2946 ret |= MPEG_STATUS_RECORD;
2947
2948 if(is_prerecording)
2949 ret |= MPEG_STATUS_PRERECORD;
2665#endif 2950#endif
2666 2951
2667 if(mpeg_errno) 2952 if(mpeg_errno)
@@ -3057,73 +3342,6 @@ void mpeg_set_pitch(int pitch)
3057} 3342}
3058#endif 3343#endif
3059 3344
3060#ifdef HAVE_MAS3587F
3061void mpeg_set_recording_options(int frequency, int quality,
3062 int source, int channel_mode,
3063 bool editable)
3064{
3065 bool is_mpeg1;
3066 unsigned long val;
3067
3068 is_mpeg1 = (frequency < 3)?true:false;
3069
3070 rec_version_index = is_mpeg1?3:2;
3071 rec_frequency_index = frequency % 3;
3072
3073 val = (quality << 17) |
3074 (rec_frequency_index << 10) |
3075 ((is_mpeg1?1:0) << 9) |
3076 (1 << 8) | /* CRC on */
3077 (((channel_mode * 2 + 1) & 3) << 6) |
3078 (1 << 5) /* MS-stereo */ |
3079 (1 << 2) /* Is an original */;
3080 mas_writemem(MAS_BANK_D0, 0x7f0, &val,1);
3081
3082 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val);
3083
3084 val = editable?4:0;
3085 mas_writemem(MAS_BANK_D0, 0x7f9, &val,1);
3086
3087 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f9, %x)\n", val);
3088
3089 val = ((!is_recording << 10) | /* Monitoring */
3090 ((source < 2)?1:2) << 8) | /* Input select */
3091 (1 << 5) | /* SDO strobe invert */
3092 ((is_mpeg1?0:1) << 3) |
3093 (1 << 2) | /* Inverted SIBC clock signal */
3094 1; /* Validate */
3095 mas_writemem(MAS_BANK_D0, 0x7f1, &val,1);
3096
3097 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f1, %x)\n", val);
3098
3099 drain_dma_buffer();
3100
3101 if(source == 0) /* Mic */
3102 {
3103 /* Copy left channel to right (mono mode) */
3104 mas_codec_writereg(8, 0x8000);
3105 }
3106 else
3107 {
3108 /* Stereo input mode */
3109 mas_codec_writereg(8, 0);
3110 }
3111}
3112
3113/* If use_mic is true, the left gain is used */
3114void mpeg_set_recording_gain(int left, int right, bool use_mic)
3115{
3116 /* Enable both left and right A/D */
3117 mas_codec_writereg(0x0,
3118 (left << 12) |
3119 (right << 8) |
3120 (left << 4) |
3121 (use_mic?0x0008:0) | /* Connect left A/D to mic */
3122 0x0007);
3123}
3124
3125#endif
3126
3127#ifdef SIMULATOR 3345#ifdef SIMULATOR
3128static char mpeg_stack[DEFAULT_STACK_SIZE]; 3346static char mpeg_stack[DEFAULT_STACK_SIZE];
3129static char mpeg_thread_name[] = "mpeg"; 3347static char mpeg_thread_name[] = "mpeg";