1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
45 #include "lcd-remote.h"
46 #include "pcm_playback.h"
47 #include "pcm_record.h"
50 /***************************************************************************/
52 static volatile bool is_recording
; /* We are recording */
53 static volatile bool is_stopping
; /* Are we going to stop */
54 static volatile bool is_paused
; /* We have paused */
55 static volatile bool is_error
; /* An error has occured */
57 static volatile unsigned long num_rec_bytes
; /* Num bytes recorded */
58 static volatile unsigned long num_file_bytes
; /* Num bytes written to current file */
59 static volatile int error_count
; /* Number of DMA errors */
61 static long record_start_time
; /* Value of current_tick when recording was started */
62 static long pause_start_time
; /* Value of current_tick when pause was started */
63 static volatile int buffered_chunks
; /* number of valid chunks in buffer */
66 static char recording_filename
[MAX_PATH
];
68 static volatile bool init_done
, close_done
, record_done
, stop_done
, pause_done
, resume_done
, new_file_done
;
70 static short peak_left
, peak_right
;
72 /***************************************************************************/
76 Normal recording rate: 44100 HZ * 4 = 176 KB/s
77 Total buffer size: 32 MB / 176 KB/s = 181s before writing to disk
80 #define CHUNK_SIZE 8192 /* Multiple of 4 */
81 #define WRITE_THRESHOLD 250 /* (2 MB) Write when this many chunks (or less) until buffer full */
83 #define GET_CHUNK(x) (short*)(&rec_buffer[CHUNK_SIZE*(x)])
85 static unsigned char *rec_buffer
; /* Circular recording buffer */
86 static int num_chunks
; /* Number of chunks available in rec_buffer */
90 Overrun occures when DMA needs to write a new chunk and write_index == read_index
91 Solution to this is to optimize pcmrec_callback, use cpu_boost or save to disk
95 static volatile int write_index
; /* Current chunk the DMA is writing to */
96 static volatile int read_index
; /* Oldest chunk that is not written to disk */
97 static volatile int read2_index
; /* Latest chunk that has not been converted to little endian */
98 static long pre_record_ticks
; /* pre-record time expressed in ticks */
99 static int pre_record_chunks
; /* pre-record time expressed in chunks */
101 /***************************************************************************/
103 static struct event_queue pcmrec_queue
;
104 static long pcmrec_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
105 static const char pcmrec_thread_name
[] = "pcmrec";
107 static void pcmrec_thread(void);
108 static void pcmrec_dma_start(void);
109 static void pcmrec_dma_stop(void);
112 #define PCMREC_INIT 1 /* Enable recording */
113 #define PCMREC_CLOSE 2
115 #define PCMREC_START 3 /* Start a new recording */
116 #define PCMREC_STOP 4 /* Stop the current recording */
117 #define PCMREC_PAUSE 10
118 #define PCMREC_RESUME 11
119 #define PCMREC_NEW_FILE 12
120 #define PCMREC_SET_GAIN 13
122 /*******************************************************************/
123 /* Functions that are not executing in the pcmrec_thread first */
124 /*******************************************************************/
126 /* Creates pcmrec_thread */
127 void pcm_rec_init(void)
129 queue_init(&pcmrec_queue
);
130 create_thread(pcmrec_thread
, pcmrec_stack
, sizeof(pcmrec_stack
), pcmrec_thread_name
);
134 /* Initializes recording:
135 * - Set up the UDA1380 for recording
136 * - Prepare for DMA transfers
139 void audio_init_recording(void)
142 queue_post(&pcmrec_queue
, PCMREC_INIT
, 0);
149 void audio_close_recording(void)
152 queue_post(&pcmrec_queue
, PCMREC_CLOSE
, 0);
159 unsigned long pcm_rec_status(void)
161 unsigned long ret
= 0;
164 ret
|= AUDIO_STATUS_RECORD
;
166 ret
|= AUDIO_STATUS_PAUSE
;
168 ret
|= AUDIO_STATUS_ERROR
;
173 unsigned long audio_recorded_time(void)
178 return pause_start_time
- record_start_time
;
180 return current_tick
- record_start_time
;
186 unsigned long audio_num_recorded_bytes(void)
189 return num_rec_bytes
;
196 * Sets the audio source
198 * This functions starts feeding the CPU with audio data over the I2S bus
200 * @param source 0=mic, 1=line-in, (todo: 2=spdif)
202 void audio_set_recording_options(int frequency
, int quality
,
203 int source
, int channel_mode
,
204 bool editable
, int prerecord_time
)
212 /* WARNING: calculation below uses fixed frequency! */
213 pre_record_ticks
= prerecord_time
* HZ
;
214 pre_record_chunks
= ((44100 * prerecord_time
* 4)/CHUNK_SIZE
)+1;
215 if(pre_record_chunks
>= (num_chunks
-250))
217 /* we can't prerecord more than our buffersize minus treshold to write to disk! */
218 pre_record_chunks
= num_chunks
-250;
219 /* don't forget to recalculate that time! */
220 pre_record_ticks
= ((pre_record_chunks
* CHUNK_SIZE
)/(4*44100)) * HZ
;
223 //logf("pcmrec: src=%d", source);
229 uda1380_enable_recording(true);
234 uda1380_enable_recording(false);
238 uda1380_set_monitor(true);
243 * Note that microphone is mono, only left value is used
244 * See uda1380_set_recvol() for exact ranges.
246 * @param type 0=line-in (radio), 1=mic, 2=ADC
249 void audio_set_recording_gain(int left
, int right
, int type
)
251 //logf("rcmrec: t=%d l=%d r=%d", type, left, right);
252 uda1380_set_recvol(left
, right
, type
);
259 * Use audio_set_recording_options first to select recording options
261 void audio_record(const char *filename
)
265 logf("record while recording");
269 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
270 recording_filename
[MAX_PATH
- 1] = 0;
273 queue_post(&pcmrec_queue
, PCMREC_START
, 0);
281 void audio_new_file(const char *filename
)
283 logf("pcm_new_file");
285 new_file_done
= false;
287 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
288 recording_filename
[MAX_PATH
- 1] = 0;
290 queue_post(&pcmrec_queue
, PCMREC_NEW_FILE
, 0);
292 while(!new_file_done
)
296 logf("pcm_new_file done");
302 void audio_stop_recording(void)
310 queue_post(&pcmrec_queue
, PCMREC_STOP
, 0);
316 logf("pcm_stop done");
319 void audio_pause_recording(void)
323 logf("pause when not recording");
328 logf("pause when paused");
333 queue_post(&pcmrec_queue
, PCMREC_PAUSE
, 0);
340 void audio_resume_recording(void)
344 logf("resume when not paused");
349 queue_post(&pcmrec_queue
, PCMREC_RESUME
, 0);
356 /* return peaks as int, so convert from short first
357 note that peak values are always positive */
358 void pcm_rec_get_peaks(int *left
, int *right
)
361 *left
= (int)peak_left
;
363 *right
= (int)peak_right
;
368 /***************************************************************************/
369 /* Functions that executes in the context of pcmrec_thread */
370 /***************************************************************************/
373 * Process the chunks using read_index and write_index.
375 * This function is called when queue_get_w_tmo times out.
377 * Other functions can also call this function with flush = true when
378 * they want to save everything in the buffers to disk.
382 static void pcmrec_callback(bool flush
) __attribute__ ((section (".icode")));
383 static void pcmrec_callback(bool flush
)
385 int num_ready
, num_free
, num_new
;
392 num_new
= w
- read2_index
;
394 num_new
+= num_chunks
;
396 for (i
=0; i
<num_new
; i
++)
398 /* Convert the samples to little-endian so we only have to write later
399 (Less hd-spinning time), also do peak detection while we're at it
401 ptr
= GET_CHUNK(read2_index
);
402 for (j
=0; j
<CHUNK_SIZE
/4; j
++)
405 if(value
> peak_left
)
407 else if (-value
> peak_left
)
410 *ptr
= htole16(value
);
414 if(value
> peak_right
)
416 else if (-value
> peak_right
)
419 *ptr
= htole16(value
);
423 if(is_recording
&& !is_paused
)
424 num_rec_bytes
+= CHUNK_SIZE
;
427 if (read2_index
>= num_chunks
)
431 if ((!is_recording
|| is_paused
) && !flush
)
433 /* not recording = no saving to disk, fake buffer clearing */
434 read_index
= write_index
;
438 num_ready
= w
- read_index
;
440 num_ready
+= num_chunks
;
442 num_free
= num_chunks
- num_ready
;
444 if (num_free
<= WRITE_THRESHOLD
|| flush
)
446 logf("writing: %d (%d)", num_ready
, flush
);
448 for (i
=0; i
<num_ready
; i
++)
450 if (write(wav_file
, GET_CHUNK(read_index
), CHUNK_SIZE
) != CHUNK_SIZE
)
452 logf("pcmrec: write err");
457 num_file_bytes
+= CHUNK_SIZE
;
460 if (read_index
>= num_chunks
)
472 /* Abort dma transfer */
473 static void pcmrec_dma_stop(void)
478 is_recording
= false;
482 logf("dma1 stopped");
485 static void pcmrec_dma_start(void)
487 DAR1
= (unsigned long)GET_CHUNK(write_index
); /* Destination address */
488 SAR1
= (unsigned long)&PDIR2
; /* Source address */
489 BCR1
= CHUNK_SIZE
; /* Bytes to transfer */
491 /* Start the DMA transfer.. */
492 DCR1
= DMA_INT
| DMA_EEXT
| DMA_CS
| DMA_DINC
| DMA_START
;
494 /* pre-recording: buffer count */
497 logf("dma1 started");
501 /* DMA1 Interrupt is called when the DMA has finished transfering a chunk */
502 void DMA1(void) __attribute__ ((interrupt_handler
, section(".icode")));
507 DSR1
= 1; /* Clear interrupt */
511 DCR1
= 0; /* Stop DMA transfer */
513 is_recording
= false;
515 logf("dma1 err: 0x%x", res
);
517 /* Flush recorded data to disk and stop recording */
518 queue_post(&pcmrec_queue
, PCMREC_STOP
, NULL
);
523 if (write_index
>= num_chunks
)
526 /* update number of valid chunks for pre-recording */
527 if(buffered_chunks
< num_chunks
)
532 DCR1
= 0; /* Stop DMA transfer */
535 logf("dma1 stopping");
537 } else if (write_index
== read_index
)
539 DCR1
= 0; /* Stop DMA transfer */
540 is_recording
= false;
542 logf("dma1 overrun");
546 DAR1
= (unsigned long)GET_CHUNK(write_index
); /* Destination address */
551 IPR
|= (1<<15); /* Clear pending interrupt request */
554 /* Create WAVE file and write header */
555 /* Sets returns 0 if success, -1 on failure */
556 static int start_wave(void)
558 unsigned char header
[44] =
560 'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',
561 0x10,0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,
562 4,0,0x10,0,'d','a','t','a',0,0,0,0
565 wav_file
= open(recording_filename
, O_RDWR
|O_CREAT
|O_TRUNC
);
569 logf("rec: create failed: %d", wav_file
);
574 if (sizeof(header
) != write(wav_file
, header
, sizeof(header
)))
578 logf("rec: write failed");
586 /* Update header and set correct length values */
587 static void close_wave(void)
593 l
= htole32(num_file_bytes
+ 36);
594 lseek(wav_file
, 4, SEEK_SET
);
595 write(wav_file
, &l
, 4);
597 l
= htole32(num_file_bytes
);
598 lseek(wav_file
, 40, SEEK_SET
);
599 write(wav_file
, &l
, 4);
606 static void pcmrec_start(void)
608 int pre_chunks
= pre_record_chunks
; /* recalculate every time! */
609 long pre_ticks
= pre_record_ticks
; /* recalculate every time! */
611 logf("pcmrec_start");
615 logf("already recording");
623 if (start_wave() != 0)
625 /* failed to create the file */
630 /* pre-recording calculation */
631 if(buffered_chunks
< pre_chunks
)
633 /* not enough good chunks available - limit pre-record time */
634 pre_chunks
= buffered_chunks
;
635 pre_ticks
= ((buffered_chunks
* CHUNK_SIZE
)/(4*44100)) * HZ
;
637 record_start_time
= current_tick
- pre_ticks
;
639 read_index
= write_index
- pre_chunks
;
642 read_index
+= num_chunks
;
648 num_rec_bytes
= pre_chunks
* CHUNK_SIZE
;
650 pause_start_time
= 0;
659 static void pcmrec_stop(void)
671 /* wait for recording to finish */
674 while (is_stopping
&& is_recording
)
681 is_recording
= false;
683 /* Flush buffers to file */
684 pcmrec_callback(true);
690 /* Finally start dma again for peakmeters and pre-recoding to work. */
693 logf("pcmrec_stop done");
696 static void pcmrec_new_file(void)
698 logf("pcmrec_new_file");
702 logf("not recording");
703 new_file_done
= true;
707 /* Since pcmrec_callback() blocks until the data has been written,
708 here is a good approximation when recording to the new file starts
710 record_start_time
= current_tick
;
714 pause_start_time
= record_start_time
;
716 /* Flush what we got in buffers to file */
717 pcmrec_callback(true);
723 /* start the new file */
724 if (start_wave() != 0)
726 logf("new_file failed");
730 new_file_done
= true;
731 logf("pcmrec_new_file done");
734 static void pcmrec_pause(void)
736 logf("pcmrec_pause");
740 logf("pause: not recording");
745 /* Abort DMA transfer and flush to file? */
749 while (is_stopping
&& is_recording
)
753 pause_start_time
= current_tick
;
756 /* Flush what we got in buffers to file */
757 pcmrec_callback(true);
761 logf("pcmrec_pause done");
765 static void pcmrec_resume(void)
767 logf("pcmrec_resume");
771 logf("resume: not paused");
779 /* Compensate for the time we have been paused */
780 if (pause_start_time
)
782 record_start_time
+= current_tick
- pause_start_time
;
783 pause_start_time
= 0;
790 logf("pcmrec_resume done");
795 * audio_init_recording calls this function using PCMREC_INIT
798 static void pcmrec_init(void)
800 unsigned long buffer_size
;
806 pre_record_chunks
= 0;
807 pre_record_ticks
= 0;
814 record_start_time
= 0;
815 pause_start_time
= 0;
818 is_recording
= false;
823 rec_buffer
= (unsigned char*)(((unsigned long)audiobuf
) & ~3);
824 buffer_size
= (long)audiobufend
- (long)audiobuf
- 16;
826 logf("buf size: %d kb", buffer_size
/1024);
828 num_chunks
= buffer_size
/ CHUNK_SIZE
;
830 logf("num_chunks: %d", num_chunks
);
832 IIS1CONFIG
= 0x800; /* Stop any playback */
833 AUDIOGLOB
|= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
834 DATAINCONTROL
= 0xc000; /* Generate Interrupt when 6 samples in fifo */
835 DATAINCONTROL
|= 0x20; /* PDIR2 source = IIS1recv */
837 DIVR1
= 55; /* DMA1 is mapped into vector 55 in system.c */
838 DMACONFIG
= 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
839 DMAROUTE
= (DMAROUTE
& 0xffff00ff) | DMA1_REQ_AUDIO_2
;
840 ICR7
= 0x1c; /* Enable interrupt at level 7, priority 0 */
841 IMR
&= ~(1<<15); /* bit 15 is DMA1 */
848 static void pcmrec_close(void)
850 uda1380_disable_recording();
852 DMAROUTE
= (DMAROUTE
& 0xffff00ff);
853 ICR7
= 0x00; /* Disable interrupt */
854 IMR
|= (1<<15); /* bit 15 is DMA1 */
859 static void pcmrec_thread(void)
863 logf("thread pcmrec start");
869 queue_wait_w_tmo(&pcmrec_queue
, &ev
, HZ
/ 40);
897 case PCMREC_NEW_FILE
:
902 pcmrec_callback(false);
905 case SYS_USB_CONNECTED
:
906 if (!is_recording
&& !is_stopping
)
908 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
909 usb_wait_for_disconnect(&pcmrec_queue
);
915 logf("thread pcmrec done");
918 /* Select VINL & VINR source: 0=Line-in, 1=FM Radio */
919 void pcm_rec_mux(int source
)
921 #ifdef IRIVER_H300_SERIES
923 and_l(~0x40000000, &GPIO_OUT
); /* Line In */
925 or_l(0x40000000, &GPIO_OUT
); /* FM radio */
927 or_l(0x40000000, &GPIO_ENABLE
);
928 or_l(0x40000000, &GPIO_FUNCTION
);
931 and_l(~0x00800000, &GPIO_OUT
); /* Line In */
933 or_l(0x00800000, &GPIO_OUT
); /* FM radio */
935 or_l(0x00800000, &GPIO_ENABLE
);
936 or_l(0x00800000, &GPIO_FUNCTION
);