summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/drivers/uda1380.c4
-rw-r--r--firmware/export/mcf5249.h5
-rw-r--r--firmware/export/pcm_record.h51
-rw-r--r--firmware/pcm_record.c650
5 files changed, 711 insertions, 2 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index dbe84267d2..f0a3501903 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -126,4 +126,7 @@ drivers/uda1380.c
126#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR) 126#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
127pcm_playback.c 127pcm_playback.c
128#endif 128#endif
129#if defined(IRIVER_H100) && !defined(SIMULATOR)
130pcm_record.c
131#endif
129sound.c 132sound.c
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 23d917f8ae..bba7d19d04 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -200,7 +200,7 @@ void uda1380_close(void)
200 */ 200 */
201void uda1380_enable_recording(bool source_mic) 201void uda1380_enable_recording(bool source_mic)
202{ 202{
203 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC); 203 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC);
204 204
205 if (source_mic) 205 if (source_mic)
206 { 206 {
@@ -214,6 +214,8 @@ void uda1380_enable_recording(bool source_mic)
214 uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & PGA_GAIN_MASK) | PGA_GAINL(0) | PGA_GAINR(0)); /* PGA_GAIN: 0=0 dB, F=24dB */ 214 uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & PGA_GAIN_MASK) | PGA_GAINL(0) | PGA_GAINR(0)); /* PGA_GAIN: 0=0 dB, F=24dB */
215 } 215 }
216 216
217 sleep(HZ/8);
218
217 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER); 219 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER);
218 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(3)); /* Not sure which mode is the best one.. */ 220 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(3)); /* Not sure which mode is the best one.. */
219 221
diff --git a/firmware/export/mcf5249.h b/firmware/export/mcf5249.h
index 398b31156d..66e92eeb50 100644
--- a/firmware/export/mcf5249.h
+++ b/firmware/export/mcf5249.h
@@ -159,7 +159,7 @@
159#define PDOR1_R (*(volatile unsigned long *)(MBAR2 + 0x044)) 159#define PDOR1_R (*(volatile unsigned long *)(MBAR2 + 0x044))
160#define PDOR2_L (*(volatile unsigned long *)(MBAR2 + 0x054)) 160#define PDOR2_L (*(volatile unsigned long *)(MBAR2 + 0x054))
161#define PDOR2_R (*(volatile unsigned long *)(MBAR2 + 0x064)) 161#define PDOR2_R (*(volatile unsigned long *)(MBAR2 + 0x064))
162#define PDIR3 (*(volatile unsigned long *)(MBAR2 + 0x074)) 162#define PDIR2 (*(volatile unsigned long *)(MBAR2 + 0x074))
163#define PDOR3 (*(volatile unsigned long *)(MBAR2 + 0x074)) 163#define PDOR3 (*(volatile unsigned long *)(MBAR2 + 0x074))
164#define UCHANNELTRANSMIT (*(volatile unsigned long *)(MBAR2 + 0x084)) 164#define UCHANNELTRANSMIT (*(volatile unsigned long *)(MBAR2 + 0x084))
165#define U1CHANNELRECEIVE (*(volatile unsigned long *)(MBAR2 + 0x088)) 165#define U1CHANNELRECEIVE (*(volatile unsigned long *)(MBAR2 + 0x088))
@@ -262,5 +262,8 @@
262/* DMAROUTE config */ 262/* DMAROUTE config */
263#define DMA0_REQ_AUDIO_1 0x80 263#define DMA0_REQ_AUDIO_1 0x80
264#define DMA0_REQ_AUDIO_2 0x81 264#define DMA0_REQ_AUDIO_2 0x81
265#define DMA1_REQ_AUDIO_1 0x8000
266#define DMA1_REQ_AUDIO_2 0x8100
267
265 268
266#endif 269#endif
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h
new file mode 100644
index 0000000000..964d3a003e
--- /dev/null
+++ b/firmware/export/pcm_record.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 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
20/*
21 * Function names are taken from apps/recorder/recording.c to
22 * make the integration later easier..
23 *
24 */
25
26#ifndef PCM_RECORD_H
27#define PCM_RECORD_H
28
29unsigned long pcm_status(void);
30
31void pcm_init_recording(void);
32
33void pcm_open_recording(void);
34void pcm_close_recording(void);
35
36
37void pcm_set_recording_options(int source, bool enable_waveform);
38void pcm_set_recording_gain(int gain, int volume);
39
40void pcm_record(const char *filename);
41void pcm_stop_recording(void);
42
43//void pcm_new_file(const char *filename);
44
45
46unsigned long pcm_recorded_time(void);
47unsigned long pcm_num_recorded_bytes(void);
48void pcm_pause_recording(void);
49void pcm_resume_recording(void);
50
51#endif
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
new file mode 100644
index 0000000000..d11458427d
--- /dev/null
+++ b/firmware/pcm_record.c
@@ -0,0 +1,650 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 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
20#include "config.h"
21#include "debug.h"
22#include "panic.h"
23#include "thread.h"
24
25#include <kernel.h>
26#include <stdio.h>
27#include <string.h>
28#include <stdarg.h>
29#include <string.h>
30
31#include "cpu.h"
32#include "i2c.h"
33#include "uda1380.h"
34#include "system.h"
35#include "usb.h"
36
37#include "buffer.h"
38#include "audio.h"
39#include "button.h"
40#include "file.h"
41#include "sprintf.h"
42#include "logf.h"
43#include "button.h"
44#include "lcd.h"
45#include "lcd-remote.h"
46#include "pcm_playback.h"
47#include "pcm_record.h"
48
49
50/***************************************************************************/
51
52static volatile bool is_recording; /* We are recording */
53static volatile bool is_stopping; /* Are we going to stop */
54static volatile bool is_paused; /* We have paused */
55
56static volatile int num_rec_bytes;
57static volatile int int_count; /* Number of DMA completed interrupts */
58static volatile int error_count; /* Number of DMA errors */
59
60static unsigned long record_start_time; /* Value of current_tick when recording was started */
61static unsigned long pause_start_time; /* Value of current_tick when pause was started */
62
63static int rec_gain, rec_volume;
64static bool show_waveform;
65static int init_done = 0;
66static int wav_file;
67static char recording_filename[MAX_PATH];
68
69/***************************************************************************/
70
71/*
72 Some estimates:
73 44100 HZ * 4 = 176400 bytes/s
74 Refresh LCD 10 HZ = 176400 / 10 = 17640 bytes ~=~ 1024*16 bytes
75
76 If NUM_BUFFERS is 80 we can hold ~8 sec of data in memory
77 ALL_BUFFER_SIZE will be 1024*16 * 80 = 1310720 bytes
78*/
79
80#define NUM_BUFFERS 80
81#define EACH_BUFFER_SIZE (1024*16) /* Multiple of 4. Use small value to get responsive waveform */
82#define ALL_BUFFERS_SIZE (NUM_BUFFERS * EACH_BUFFER_SIZE)
83
84#define WRITE_THRESHOLD 40 /* Minimum number of buffers before write to file */
85
86static unsigned char *rec_buffers[NUM_BUFFERS];
87
88/*
89 Overrun occures when DMA needs to write a new buffer and write_index == read_index
90 Solution to this is to optimize pcmrec_callback, use cpu_boost somewhere or increase
91 the total buffer size (or WRITE_THRESHOLD)
92*/
93
94static int write_index; /* Which buffer the DMA is currently recording */
95static int read_index; /* The oldest buffer that the pcmrec_callback has not read */
96
97/***************************************************************************/
98
99static struct event_queue pcmrec_queue;
100static long pcmrec_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
101static const char pcmrec_thread_name[] = "pcmrec";
102
103static void pcmrec_thread(void);
104
105/* Event IDs */
106#define PCMREC_OPEN 1 /* Enable recording */
107#define PCMREC_CLOSE 2 /* Disable recording */
108#define PCMREC_START 3 /* Start a new recording */
109#define PCMREC_STOP 4 /* Stop the current recording */
110#define PCMREC_PAUSE 10
111#define PCMREC_RESUME 11
112#define PCMREC_NEW_FILE 12
113#define PCMREC_SET_GAIN 13
114#define PCMREC_GOT_DATA 20 /* DMA1 notifies when data has arrived */
115
116
117/*******************************************************************/
118/* Functions that are not executing in the pcmrec_thread first */
119/*******************************************************************/
120
121void pcm_init_recording(void)
122{
123 int_count = 0;
124 error_count = 0;
125
126 show_waveform = 0;
127 is_recording = 0;
128 is_stopping = 0;
129 num_rec_bytes = 0;
130 wav_file = -1;
131 read_index = 0;
132 write_index = 0;
133
134 queue_init(&pcmrec_queue);
135 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), pcmrec_thread_name);
136}
137
138void pcm_open_recording(void)
139{
140 init_done = 0;
141
142 logf("pcm_open_rec");
143
144 queue_post(&pcmrec_queue, PCMREC_OPEN, 0);
145
146 while (init_done)
147 {
148 sleep(HZ >> 8);
149 }
150
151 logf("pcm_open_rec done");
152}
153
154void pcm_close_recording(void)
155{
156 /* todo: synchronize completion with pcmrec thread */
157 queue_post(&pcmrec_queue, PCMREC_CLOSE, 0);
158}
159
160
161
162unsigned long pcm_status(void)
163{
164 unsigned long ret = 0;
165
166 if (is_recording)
167 ret |= AUDIO_STATUS_RECORD;
168
169 return ret;
170}
171
172
173
174void pcm_new_file(const char *filename)
175{
176 /* todo */
177 filename = filename;
178
179}
180
181unsigned long pcm_recorded_time(void)
182{
183 if (is_recording)
184 {
185 if(is_paused)
186 return pause_start_time - record_start_time;
187 else
188 return current_tick - record_start_time;
189 }
190
191 return 0;
192}
193
194unsigned long pcm_num_recorded_bytes(void)
195{
196
197 if (is_recording)
198 {
199 return num_rec_bytes;
200 }
201 else
202 return 0;
203}
204
205void pcm_pause_recording(void)
206{
207 /* todo */
208}
209
210void pcm_resume_recording(void)
211{
212 /* todo */
213}
214
215
216/**
217 * Sets the audio source
218 *
219 * Side effect: This functions starts feeding the CPU with audio data over the I2S bus
220 *
221 * @param source 0=line-in, 1=mic
222 */
223void pcm_set_recording_options(int source, bool enable_waveform)
224{
225 uda1380_enable_recording(source);
226
227 show_waveform = enable_waveform;
228
229}
230
231
232/**
233 *
234 * @param gain line-in and microphone gain (0-15)
235 * @param volume ADC volume (0-255)
236 */
237void pcm_set_recording_gain(int gain, int volume)
238{
239 rec_gain = gain;
240 rec_volume = volume;
241
242 queue_post(&pcmrec_queue, PCMREC_SET_GAIN, 0);
243
244}
245
246/**
247 * Start recording
248 *
249 * Use pcm_set_recording_options before calling record
250 */
251void pcm_record(const char *filename)
252{
253 strncpy(recording_filename, filename, MAX_PATH - 1);
254 recording_filename[MAX_PATH - 1] = 0;
255
256 queue_post(&pcmrec_queue, PCMREC_START, 0);
257}
258
259/**
260 *
261 */
262void pcm_stop_recording(void)
263{
264 if (is_recording)
265 is_stopping = 1;
266
267 queue_post(&pcmrec_queue, PCMREC_STOP, 0);
268
269 logf("pcm_stop_recording");
270
271 while (is_stopping)
272 {
273 sleep(HZ >> 4);
274 }
275
276 logf("pcm_stop_recording done");
277
278
279}
280
281
282/***************************************************************************/
283/* Functions that executes in the context of pcmrec_thread */
284/***************************************************************************/
285
286
287/**
288 * Process the buffers using read_index and write_index.
289 *
290 * DMA1 handler posts to pcmrec_queue so that pcmrec_thread calls this
291 * function. Also pcmrec_stop will call this function when the recording
292 * is stopping, and that call will have flush = true.
293 *
294 */
295
296void pcmrec_callback(bool flush) __attribute__ ((section (".icode")));
297void pcmrec_callback(bool flush)
298{
299 int num_ready;
300
301 num_ready = write_index - read_index;
302 if (num_ready < 0)
303 num_ready += NUM_BUFFERS;
304
305 /* we can consume up to num_ready buffers */
306
307#ifdef HAVE_REMOTE_LCD
308 /* Draw waveform on remote LCD */
309 if (show_waveform && num_ready>0)
310 {
311 short *buf;
312 long x,y,offset;
313 int show_index;
314
315 /* Just display the last buffer (most recent one) */
316 show_index = read_index + num_ready - 1;
317 buf = (short*)rec_buffers[show_index];
318
319 lcd_remote_clear_display();
320
321 offset = 0;
322 for (x=0; x<LCD_REMOTE_WIDTH-1; x++)
323 {
324 y = buf[offset] * (LCD_REMOTE_HEIGHT / 2) *5; /* The 5 is just 'zooming' */
325 y = y >> 15; /* Divide with SHRT_MAX */
326 y += LCD_REMOTE_HEIGHT/2;
327
328 if (y < 2) y=2;
329 if (y >= LCD_REMOTE_HEIGHT-2) y = LCD_REMOTE_HEIGHT-2;
330
331 REMOTE_DRAW_PIXEL(x,y);
332
333 offset += (EACH_BUFFER_SIZE/2) / LCD_REMOTE_WIDTH;
334 }
335
336 lcd_remote_update();
337 }
338
339#endif
340
341 /* Note: This might be a good place to call the 'codec' later */
342
343 /* Check that we have the minimum amount of data to save or */
344 /* that if it's closing time which mean we have to save.. */
345 if (wav_file != -1)
346 {
347 if (num_ready >= WRITE_THRESHOLD || flush)
348 {
349 unsigned long *ptr = (unsigned long*)rec_buffers[read_index];
350 int i;
351
352 for (i=0; i<EACH_BUFFER_SIZE * num_ready / 4; i++)
353 {
354 *ptr = SWAB32(*ptr);
355 ptr++;
356 }
357
358 write(wav_file, rec_buffers[read_index], EACH_BUFFER_SIZE * num_ready);
359
360 read_index+=num_ready;
361 if (read_index >= NUM_BUFFERS)
362 read_index -= NUM_BUFFERS;
363 }
364
365 } else
366 {
367 /* In this case we must consume the buffers otherwise we will */
368 /* get 'dma1 overrun' pretty fast */
369
370 read_index+=num_ready;
371 if (read_index >= NUM_BUFFERS)
372 read_index -= NUM_BUFFERS;
373 }
374}
375
376
377
378
379void pcmrec_dma_start(void)
380{
381 DAR1 = (unsigned long)rec_buffers[write_index++]; /* Destination address */
382 SAR1 = (unsigned long)&PDIR2; /* Source address */
383 BCR1 = EACH_BUFFER_SIZE; /* Bytes to transfer */
384
385 /* Start the DMA transfer.. */
386 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
387
388 logf("dma1 started");
389}
390
391
392/* DMA1 Interrupt is called when the DMA has finished transfering a chunk */
393void DMA1(void) __attribute__ ((interrupt_handler, section(".icode")));
394void DMA1(void)
395{
396 int res = DSR1;
397
398 DSR1 = 1; /* Clear interrupt */
399
400 int_count++;
401
402 if (res & 0x70)
403 {
404 DCR1 = 0; /* Stop DMA transfer */
405 error_count++;
406 is_recording = 0;
407
408 logf("dma1 err 0x%x", res);
409
410 } else
411 {
412 num_rec_bytes += EACH_BUFFER_SIZE;
413
414 write_index++;
415 if (write_index >= NUM_BUFFERS)
416 write_index = 0;
417
418 if (is_stopping || !is_recording)
419 {
420 DCR1 = 0; /* Stop DMA transfer */
421 is_recording = 0;
422
423 logf("dma1 stopping");
424
425 } else if (write_index == read_index)
426 {
427 DCR1 = 0; /* Stop DMA transfer */
428 is_recording = 0;
429
430 logf("dma1 overrun");
431
432 } else
433 {
434 DAR1 = (unsigned long)rec_buffers[write_index]; /* Destination address */
435 BCR1 = EACH_BUFFER_SIZE;
436
437 queue_post(&pcmrec_queue, PCMREC_GOT_DATA, NULL);
438
439 }
440 }
441
442 IPR |= (1<<15); /* Clear pending interrupt request */
443}
444
445static int start_wave(void)
446{
447 unsigned char header[44] =
448 {
449 'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',
450 0x10,0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,
451 4,0,0x10,0,'d','a','t','a',0,0,0,0
452 };
453
454 wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
455 if (wav_file < 0)
456 {
457 wav_file = -1;
458 logf("create failed: %d", wav_file);
459 return -1;
460 }
461
462 if (sizeof(header) != write(wav_file, header, sizeof(header)))
463 {
464 close(wav_file);
465 wav_file = -1;
466 logf("write failed");
467 return -2;
468 }
469
470 return 0;
471}
472
473/* Update header and set correct length values */
474static void close_wave(void)
475{
476 long l;
477
478 l = SWAB32(num_rec_bytes + 36);
479 lseek(wav_file, 4, SEEK_SET);
480 write(wav_file, &l, 4);
481
482 l = SWAB32(num_rec_bytes);
483 lseek(wav_file, 40, SEEK_SET);
484 write(wav_file, &l, 4);
485
486 close(wav_file);
487 wav_file = -1;
488}
489
490static void pcmrec_start(void)
491{
492 logf("pcmrec_start");
493
494 if (is_recording)
495 return;
496
497 if (wav_file != -1)
498 close(wav_file);
499
500 logf("rec: %s", recording_filename);
501
502 start_wave(); /* todo: send signal to pcm_record if we have failed */
503
504 num_rec_bytes = 0;
505
506 /* Store the current time */
507 record_start_time = current_tick;
508
509 write_index = 0;
510 read_index = 0;
511
512 is_stopping = 0;
513 is_paused = 0;
514 is_recording = 1;
515
516 pcmrec_dma_start();
517
518}
519
520static void pcmrec_stop(void)
521{
522 /* wait for recording to finish */
523
524 /* todo: Abort current DMA transfer using DCR1.. */
525
526 logf("pcmrec_stop");
527
528 while (is_recording)
529 {
530 sleep(HZ >> 4);
531 }
532
533 logf("pcmrec_stop done");
534
535 /* Write unfinished buffers to file */
536 pcmrec_callback(true);
537
538 close_wave();
539
540 is_stopping = 0;
541}
542
543static void pcmrec_open(void)
544{
545 unsigned long buffer_start;
546 int i;
547
548 show_waveform = 0;
549 is_recording = 0;
550 is_stopping = 0;
551 num_rec_bytes = 0;
552 wav_file = -1;
553 read_index = 0;
554 write_index = 0;
555
556 buffer_start = (unsigned long)(&audiobuf[(audiobufend - audiobuf) - (ALL_BUFFERS_SIZE + 16)]);
557 buffer_start &= ~3;
558
559 for (i=0; i<NUM_BUFFERS; i++)
560 {
561 rec_buffers[i] = (unsigned char*)(buffer_start + EACH_BUFFER_SIZE * i);
562 }
563
564 IIS1CONFIG = 0x800; /* Stop any playback */
565 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
566 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */
567 DATAINCONTROL |= 0x20; /* PDIR2 source = IIS1recv */
568
569 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
570 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
571 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
572 ICR4 = (ICR4 & 0xffffff00) | 0x0000001c; /* Enable interrupt at level 7, priority 0 */
573 IMR &= ~(1<<15); /* bit 15 is DMA1 */
574
575 init_done = 1;
576}
577
578static void pcmrec_close(void)
579{
580 uda1380_disable_recording();
581
582 DMAROUTE = (DMAROUTE & 0xffff00ff);
583 ICR4 = (ICR4 & 0xffffff00); /* Disable interrupt */
584 IMR |= (1<<15); /* bit 15 is DMA1 */
585
586}
587
588static void pcmrec_thread(void)
589{
590 struct event ev;
591
592 logf("thread pcmrec start");
593
594 while (1)
595 {
596 queue_wait(&pcmrec_queue, &ev);
597
598 switch (ev.id)
599 {
600 case PCMREC_OPEN:
601 pcmrec_open();
602 break;
603
604 case PCMREC_CLOSE:
605 pcmrec_close();
606 break;
607
608 case PCMREC_START:
609 pcmrec_start();
610 break;
611
612 case PCMREC_STOP:
613 pcmrec_stop();
614 break;
615
616 case PCMREC_PAUSE:
617 /* todo */
618 break;
619
620 case PCMREC_RESUME:
621 /* todo */
622 break;
623
624 case PCMREC_NEW_FILE:
625 /* todo */
626 break;
627
628 case PCMREC_SET_GAIN:
629 uda1380_set_recvol(rec_gain, rec_gain, rec_volume);
630 break;
631
632 case PCMREC_GOT_DATA:
633 pcmrec_callback(false);
634 break;
635
636 case SYS_USB_CONNECTED:
637 if (!is_recording && !is_stopping)
638 {
639 usb_acknowledge(SYS_USB_CONNECTED_ACK);
640 usb_wait_for_disconnect(&pcmrec_queue);
641 }
642
643 break;
644 }
645 }
646
647 logf("thread pcmrec done");
648}
649
650