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 ****************************************************************************/
33 #if defined(HAVE_UDA1380)
35 #elif defined(HAVE_TLV320)
49 #include "lcd-remote.h"
50 #include "pcm_playback.h"
51 #include "pcm_record.h"
54 /***************************************************************************/
56 static volatile bool is_recording
; /* We are recording */
57 static volatile bool is_stopping
; /* Are we going to stop */
58 static volatile bool is_paused
; /* We have paused */
60 static volatile int num_rec_bytes
;
61 static volatile int int_count
; /* Number of DMA completed interrupts */
62 static volatile int error_count
; /* Number of DMA errors */
64 static unsigned long record_start_time
; /* Value of current_tick when recording was started */
65 static unsigned long pause_start_time
; /* Value of current_tick when pause was started */
67 static int rec_gain
, rec_volume
;
68 static bool show_waveform
;
69 static int init_done
= 0;
71 static char recording_filename
[MAX_PATH
];
73 /***************************************************************************/
77 44100 HZ * 4 = 176400 bytes/s
78 Refresh LCD 10 HZ = 176400 / 10 = 17640 bytes ~=~ 1024*16 bytes
80 If NUM_BUFFERS is 80 we can hold ~8 sec of data in memory
81 ALL_BUFFER_SIZE will be 1024*16 * 80 = 1310720 bytes
84 #define NUM_BUFFERS 80
85 #define EACH_BUFFER_SIZE (1024*16) /* Multiple of 4. Use small value to get responsive waveform */
86 #define ALL_BUFFERS_SIZE (NUM_BUFFERS * EACH_BUFFER_SIZE)
88 #define WRITE_THRESHOLD 40 /* Minimum number of buffers before write to file */
90 static unsigned char *rec_buffers
[NUM_BUFFERS
];
93 Overrun occures when DMA needs to write a new buffer and write_index == read_index
94 Solution to this is to optimize pcmrec_callback, use cpu_boost somewhere or increase
95 the total buffer size (or WRITE_THRESHOLD)
98 static int write_index
; /* Which buffer the DMA is currently recording */
99 static int read_index
; /* The oldest buffer that the pcmrec_callback has not read */
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);
110 #define PCMREC_OPEN 1 /* Enable recording */
111 #define PCMREC_CLOSE 2 /* Disable recording */
112 #define PCMREC_START 3 /* Start a new recording */
113 #define PCMREC_STOP 4 /* Stop the current recording */
114 #define PCMREC_PAUSE 10
115 #define PCMREC_RESUME 11
116 #define PCMREC_NEW_FILE 12
117 #define PCMREC_SET_GAIN 13
118 #define PCMREC_GOT_DATA 20 /* DMA1 notifies when data has arrived */
121 /*******************************************************************/
122 /* Functions that are not executing in the pcmrec_thread first */
123 /*******************************************************************/
125 void pcm_init_recording(void)
138 queue_init(&pcmrec_queue
);
139 create_thread(pcmrec_thread
, pcmrec_stack
, sizeof(pcmrec_stack
), pcmrec_thread_name
);
142 void pcm_open_recording(void)
146 logf("pcm_open_rec");
148 queue_post(&pcmrec_queue
, PCMREC_OPEN
, 0);
155 logf("pcm_open_rec done");
158 void pcm_close_recording(void)
160 /* todo: synchronize completion with pcmrec thread */
161 queue_post(&pcmrec_queue
, PCMREC_CLOSE
, 0);
166 unsigned long pcm_status(void)
168 unsigned long ret
= 0;
171 ret
|= AUDIO_STATUS_RECORD
;
178 void pcm_new_file(const char *filename
)
185 unsigned long pcm_recorded_time(void)
190 return pause_start_time
- record_start_time
;
192 return current_tick
- record_start_time
;
198 unsigned long pcm_num_recorded_bytes(void)
203 return num_rec_bytes
;
209 void pcm_pause_recording(void)
214 void pcm_resume_recording(void)
221 * Sets the audio source
223 * Side effect: This functions starts feeding the CPU with audio data over the I2S bus
225 * @param source 0=line-in, 1=mic
227 void pcm_set_recording_options(int source
, bool enable_waveform
)
229 #if defined(HAVE_UDA1380)
230 uda1380_enable_recording(source
);
231 #elif defined(HAVE_TLV320)
232 tlv320_enable_recording(source
);
234 show_waveform
= enable_waveform
;
240 * @param gain line-in and microphone gain (0-15)
241 * @param volume ADC volume (0-255)
243 void pcm_set_recording_gain(int gain
, int volume
)
248 queue_post(&pcmrec_queue
, PCMREC_SET_GAIN
, 0);
254 * Use pcm_set_recording_options before calling record
256 void pcm_record(const char *filename
)
258 strncpy(recording_filename
, filename
, MAX_PATH
- 1);
259 recording_filename
[MAX_PATH
- 1] = 0;
261 queue_post(&pcmrec_queue
, PCMREC_START
, 0);
267 void pcm_stop_recording(void)
272 queue_post(&pcmrec_queue
, PCMREC_STOP
, 0);
274 logf("pcm_stop_recording");
281 logf("pcm_stop_recording done");
285 /***************************************************************************/
286 /* Functions that executes in the context of pcmrec_thread */
287 /***************************************************************************/
291 * Process the buffers using read_index and write_index.
293 * DMA1 handler posts to pcmrec_queue so that pcmrec_thread calls this
294 * function. Also pcmrec_stop will call this function when the recording
295 * is stopping, and that call will have flush = true.
299 void pcmrec_callback(bool flush
) __attribute__ ((section (".icode")));
300 void pcmrec_callback(bool flush
)
304 num_ready
= write_index
- read_index
;
306 num_ready
+= NUM_BUFFERS
;
308 /* we can consume up to num_ready buffers */
310 #ifdef HAVE_REMOTE_LCD
311 /* Draw waveform on remote LCD */
312 if (show_waveform
&& num_ready
>0)
318 /* Just display the last buffer (most recent one) */
319 show_index
= read_index
+ num_ready
- 1;
320 buf
= (short*)rec_buffers
[show_index
];
322 lcd_remote_clear_display();
325 for (x
=0; x
<LCD_REMOTE_WIDTH
-1; x
++)
327 y
= buf
[offset
] * (LCD_REMOTE_HEIGHT
/ 2) *5; /* The 5 is just 'zooming' */
328 y
= y
>> 15; /* Divide with SHRT_MAX */
329 y
+= LCD_REMOTE_HEIGHT
/2;
332 if (y
>= LCD_REMOTE_HEIGHT
-2) y
= LCD_REMOTE_HEIGHT
-2;
334 lcd_remote_drawpixel(x
,y
);
336 offset
+= (EACH_BUFFER_SIZE
/2) / LCD_REMOTE_WIDTH
;
344 /* Note: This might be a good place to call the 'codec' later */
346 /* Check that we have the minimum amount of data to save or */
347 /* that if it's closing time which mean we have to save.. */
350 if (num_ready
>= WRITE_THRESHOLD
|| flush
)
352 unsigned short *ptr
= (unsigned short*)rec_buffers
[read_index
];
355 for (i
=0; i
<EACH_BUFFER_SIZE
* num_ready
/ 2; i
++)
357 *ptr
= htole16(*ptr
);
361 write(wav_file
, rec_buffers
[read_index
], EACH_BUFFER_SIZE
* num_ready
);
363 read_index
+=num_ready
;
364 if (read_index
>= NUM_BUFFERS
)
365 read_index
-= NUM_BUFFERS
;
370 /* In this case we must consume the buffers otherwise we will */
371 /* get 'dma1 overrun' pretty fast */
373 read_index
+=num_ready
;
374 if (read_index
>= NUM_BUFFERS
)
375 read_index
-= NUM_BUFFERS
;
380 void pcmrec_dma_start(void)
382 DAR1
= (unsigned long)rec_buffers
[write_index
++]; /* Destination address */
383 SAR1
= (unsigned long)&PDIR2
; /* Source address */
384 BCR1
= EACH_BUFFER_SIZE
; /* Bytes to transfer */
386 /* Start the DMA transfer.. */
387 DCR1
= DMA_INT
| DMA_EEXT
| DMA_CS
| DMA_DINC
| DMA_START
;
389 logf("dma1 started");
393 /* DMA1 Interrupt is called when the DMA has finished transfering a chunk */
394 void DMA1(void) __attribute__ ((interrupt_handler
, section(".icode")));
399 DSR1
= 1; /* Clear interrupt */
405 DCR1
= 0; /* Stop DMA transfer */
409 logf("dma1 err 0x%x", res
);
413 num_rec_bytes
+= EACH_BUFFER_SIZE
;
416 if (write_index
>= NUM_BUFFERS
)
419 if (is_stopping
|| !is_recording
)
421 DCR1
= 0; /* Stop DMA transfer */
424 logf("dma1 stopping");
426 } else if (write_index
== read_index
)
428 DCR1
= 0; /* Stop DMA transfer */
431 logf("dma1 overrun");
435 DAR1
= (unsigned long)rec_buffers
[write_index
]; /* Destination address */
436 BCR1
= EACH_BUFFER_SIZE
;
438 queue_post(&pcmrec_queue
, PCMREC_GOT_DATA
, NULL
);
443 IPR
|= (1<<15); /* Clear pending interrupt request */
446 static int start_wave(void)
448 unsigned char header
[44] =
450 'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',
451 0x10,0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,
452 4,0,0x10,0,'d','a','t','a',0,0,0,0
455 wav_file
= open(recording_filename
, O_RDWR
|O_CREAT
|O_TRUNC
);
459 logf("create failed: %d", wav_file
);
463 if (sizeof(header
) != write(wav_file
, header
, sizeof(header
)))
467 logf("write failed");
474 /* Update header and set correct length values */
475 static void close_wave(void)
479 l
= htole32(num_rec_bytes
+ 36);
480 lseek(wav_file
, 4, SEEK_SET
);
481 write(wav_file
, &l
, 4);
483 l
= htole32(num_rec_bytes
);
484 lseek(wav_file
, 40, SEEK_SET
);
485 write(wav_file
, &l
, 4);
491 static void pcmrec_start(void)
493 logf("pcmrec_start");
501 logf("rec: %s", recording_filename
);
503 start_wave(); /* todo: send signal to pcm_record if we have failed */
507 /* Store the current time */
508 record_start_time
= current_tick
;
521 static void pcmrec_stop(void)
523 /* wait for recording to finish */
525 /* todo: Abort current DMA transfer using DCR1.. */
534 logf("pcmrec_stop done");
536 /* Write unfinished buffers to file */
537 pcmrec_callback(true);
544 static void pcmrec_open(void)
546 unsigned long buffer_start
;
557 buffer_start
= (unsigned long)(&audiobuf
[(audiobufend
- audiobuf
) - (ALL_BUFFERS_SIZE
+ 16)]);
560 for (i
=0; i
<NUM_BUFFERS
; i
++)
562 rec_buffers
[i
] = (unsigned char*)(buffer_start
+ EACH_BUFFER_SIZE
* i
);
565 IIS1CONFIG
= 0x800; /* Stop any playback */
566 AUDIOGLOB
|= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
567 DATAINCONTROL
= 0xc000; /* Generate Interrupt when 6 samples in fifo */
568 DATAINCONTROL
|= 0x20; /* PDIR2 source = IIS1recv */
570 DIVR1
= 55; /* DMA1 is mapped into vector 55 in system.c */
571 DMACONFIG
= 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
572 DMAROUTE
= (DMAROUTE
& 0xffff00ff) | DMA1_REQ_AUDIO_2
;
573 ICR4
= (ICR4
& 0xffffff00) | 0x0000001c; /* Enable interrupt at level 7, priority 0 */
574 IMR
&= ~(1<<15); /* bit 15 is DMA1 */
579 static void pcmrec_close(void)
581 #if defined(HAVE_UDA1380)
582 uda1380_disable_recording();
583 #elif defined(HAVE_TLV320)
584 tlv320_disable_recording();
587 DMAROUTE
= (DMAROUTE
& 0xffff00ff);
588 ICR4
= (ICR4
& 0xffffff00); /* Disable interrupt */
589 IMR
|= (1<<15); /* bit 15 is DMA1 */
593 static void pcmrec_thread(void)
597 logf("thread pcmrec start");
601 queue_wait(&pcmrec_queue
, &ev
);
629 case PCMREC_NEW_FILE
:
633 case PCMREC_SET_GAIN
:
634 #if defined(HAVE_UDA1380)
635 uda1380_set_recvol(rec_gain
, rec_gain
, rec_volume
);
636 #elif defined(HAVE_TLV320)
641 case PCMREC_GOT_DATA
:
642 pcmrec_callback(false);
645 case SYS_USB_CONNECTED
:
646 if (!is_recording
&& !is_stopping
)
648 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
649 usb_wait_for_disconnect(&pcmrec_queue
);
655 logf("thread pcmrec done");
658 void pcmrec_set_mux(int source
)
661 and_l(~0x00800000, &GPIO_OUT
); /* Line In */
663 or_l(0x00800000, &GPIO_OUT
); /* FM radio */
665 or_l(0x00800000, &GPIO_ENABLE
);
666 or_l(0x00800000, &GPIO_FUNCTION
);