summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:18:05 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:18:05 +0000
commit5efee7c94adb691799becb605002e85e13bf11e5 (patch)
treec8f3e198cf40b5fad4f50ee558195ee906c261c5
parent0f5cb94aa4a334366a746fcbb22f3335ca413265 (diff)
downloadrockbox-5efee7c94adb691799becb605002e85e13bf11e5.tar.gz
rockbox-5efee7c94adb691799becb605002e85e13bf11e5.zip
Forgot to use cvs add on a few new files in the fresh checkout I used. woops.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11453 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/enc_config.c432
-rw-r--r--apps/enc_config.h73
-rw-r--r--firmware/enc_base.c46
-rw-r--r--firmware/export/enc_base.h270
-rw-r--r--firmware/export/general.h38
-rw-r--r--firmware/export/pcm_sampr.h310
-rw-r--r--firmware/general.c77
-rw-r--r--firmware/pcm_sampr.c76
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c738
9 files changed, 2060 insertions, 0 deletions
diff --git a/apps/enc_config.c b/apps/enc_config.c
new file mode 100644
index 0000000000..384e679c42
--- /dev/null
+++ b/apps/enc_config.c
@@ -0,0 +1,432 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Michael Sevakis
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 <stdio.h>
20#include <sprintf.h>
21#include <string.h>
22#include "config.h"
23#include "atoi.h"
24#include "lang.h"
25#include "misc.h"
26#include "talk.h"
27#include "general.h"
28#include "codecs.h"
29#include "menu.h"
30#include "statusbar.h"
31#include "settings.h"
32#include "audio.h"
33#include "pcm_record.h"
34#include "enc_config.h"
35
36#define MENU_ITEM_FN(fn) \
37 ((bool (*)(void))fn)
38
39#define ENC_MENU_ITEM_FN(fn) \
40 ((bool (*)(struct encoder_config *))fn)
41
42#define CALL_FN_(fn, ...) \
43 if (fn) fn(__VA_ARGS__)
44
45static bool enc_run_menu(int m, const struct menu_item items[],
46 struct encoder_config *cfg);
47static bool enc_no_config_menu(struct encoder_config *cfg);
48
49/** Function definitions for each codec - add these to enc_data
50 list following the definitions **/
51
52/** mp3_enc.codec **/
53/* mp3_enc: return encoder capabilities */
54static void mp3_enc_get_caps(const struct encoder_config *cfg,
55 struct encoder_caps *caps,
56 bool for_config)
57{
58 int i;
59 unsigned long bitr;
60
61 if (!for_config)
62 {
63 /* Overall encoder capabilities */
64 caps->samplerate_caps = MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS;
65 caps->channel_caps = CHN_CAP_ALL;
66 return;
67 }
68
69 /* Restrict caps based on config */
70 i = round_value_to_list32(cfg->mp3_enc.bitrate, mp3_enc_bitr,
71 MP3_ENC_NUM_BITR, false);
72 bitr = mp3_enc_bitr[i];
73
74 /* sample rate caps */
75
76 /* check if MPEG1 sample rates are available */
77 if ((bitr >= 32 && bitr <= 128) || bitr >= 160)
78 caps->samplerate_caps |= MPEG1_SAMPR_CAPS;
79
80 /* check if MPEG2 sample rates and mono are available */
81 if (bitr <= 160)
82 {
83 caps->samplerate_caps |= MPEG2_SAMPR_CAPS;
84 caps->channel_caps |= CHN_CAP_MONO;
85 }
86
87 /* check if stereo is available */
88 if (bitr >= 32)
89 caps->channel_caps |= CHN_CAP_STEREO;
90} /* mp3_enc_get_caps */
91
92/* mp3_enc: return the default configuration */
93static void mp3_enc_default_config(struct encoder_config *cfg)
94{
95 cfg->mp3_enc.bitrate = 128; /* default that works for all types */
96} /* mp3_enc_default_config */
97
98static void mp3_enc_convert_config(struct encoder_config *cfg,
99 bool to_encoder)
100{
101 if (to_encoder)
102 {
103 if ((unsigned)global_settings.mp3_enc_config.bitrate > MP3_ENC_NUM_BITR)
104 global_settings.mp3_enc_config.bitrate = MP3_ENC_BITRATE_CFG_DEFAULT;
105 cfg->mp3_enc.bitrate = mp3_enc_bitr[global_settings.mp3_enc_config.bitrate];
106 }
107 else
108 {
109 global_settings.mp3_enc_config.bitrate =
110 round_value_to_list32(cfg->mp3_enc.bitrate, mp3_enc_bitr,
111 MP3_ENC_NUM_BITR, false);
112 }
113} /* mp3_enc_convert_config */
114
115/* mp3_enc: show the bitrate setting options */
116static bool mp3_enc_bitrate(struct encoder_config *cfg)
117{
118 static const struct opt_items items[] =
119 {
120 /* Available in MPEG Version: */
121#ifdef HAVE_MPEG2_SAMPR
122#if 0
123 /* this sounds awful no matter what */
124 { "8 kBit/s", TALK_ID(8, UNIT_KBIT) }, /* 2 */
125#endif
126 /* mono only */
127 { "16 kBit/s", TALK_ID(16, UNIT_KBIT) }, /* 2 */
128 { "24 kBit/s", TALK_ID(24, UNIT_KBIT) }, /* 2 */
129#endif
130 /* stereo/mono */
131 { "32 kBit/s", TALK_ID(32, UNIT_KBIT) }, /* 1,2 */
132 { "40 kBit/s", TALK_ID(40, UNIT_KBIT) }, /* 1,2 */
133 { "48 kBit/s", TALK_ID(48, UNIT_KBIT) }, /* 1,2 */
134 { "56 kBit/s", TALK_ID(56, UNIT_KBIT) }, /* 1,2 */
135 { "64 kBit/s", TALK_ID(64, UNIT_KBIT) }, /* 1,2 */
136 { "80 kBit/s", TALK_ID(80, UNIT_KBIT) }, /* 1,2 */
137 { "96 kBit/s", TALK_ID(96, UNIT_KBIT) }, /* 1,2 */
138 { "112 kBit/s", TALK_ID(112, UNIT_KBIT) }, /* 1,2 */
139 { "128 kBit/s", TALK_ID(128, UNIT_KBIT) }, /* 1,2 */
140#if 0
141 /* oddball MPEG2-only rate stuck in the middle */
142 { "144 kBit/s", TALK_ID(144, UNIT_KBIT) }, /* 2 */
143#endif
144 { "160 kBit/s", TALK_ID(160, UNIT_KBIT) }, /* 1,2 */
145 /* stereo only */
146 { "192 kBit/s", TALK_ID(192, UNIT_KBIT) }, /* 1 */
147 { "224 kBit/s", TALK_ID(224, UNIT_KBIT) }, /* 1 */
148 { "256 kBit/s", TALK_ID(256, UNIT_KBIT) }, /* 1 */
149 { "320 kBit/s", TALK_ID(320, UNIT_KBIT) }, /* 1 */
150 };
151
152 unsigned long rate_list[ARRAYLEN(items)];
153
154 /* This is rather constant based upon the build but better than
155 storing and maintaining yet another list of numbers */
156 int n_rates = make_list_from_caps32(
157 MPEG1_BITR_CAPS | MPEG2_BITR_CAPS, mp3_enc_bitr,
158 MPEG1_BITR_CAPS
159#ifdef HAVE_MPEG2_SAMPR
160 | (MPEG2_BITR_CAPS & ~(MP3_BITR_CAP_144 | MP3_BITR_CAP_8)),
161#endif
162 rate_list);
163
164 int index = round_value_to_list32(cfg->mp3_enc.bitrate, rate_list,
165 n_rates, false);
166 bool res = set_option(str(LANG_BITRATE), &index, INT,
167 items, n_rates, NULL);
168 index = round_value_to_list32(rate_list[index], mp3_enc_bitr,
169 MP3_ENC_NUM_BITR, false);
170 cfg->mp3_enc.bitrate = mp3_enc_bitr[index];
171
172 return res;
173} /* mp3_enc_bitrate */
174
175/* mp3_enc: show the configuration menu */
176static bool mp3_enc_menu(struct encoder_config *cfg)
177{
178 static const struct menu_item items[] =
179 {
180 { ID2P(LANG_BITRATE), MENU_ITEM_FN(mp3_enc_bitrate) }
181 };
182
183 bool result;
184 int m = menu_init(items, ARRAYLEN(items), NULL, NULL, NULL, NULL);
185 result = enc_run_menu(m, items, cfg);
186 menu_exit(m);
187 return result;
188} /* mp3_enc_menu */
189
190/** wav_enc.codec **/
191/* wav_enc: show the configuration menu */
192#if 0
193static bool wav_enc_menu(struct encoder_config *cfg);
194#endif
195
196/** wavpack_enc.codec **/
197/* wavpack_enc: show the configuration menu */
198#if 0
199static bool wavpack_enc_menu(struct encoder_config *cfg);
200#endif
201
202/** config function pointers and/or data for each codec **/
203static const struct encoder_data
204{
205 void (*get_caps)(const struct encoder_config *, struct encoder_caps *,
206 bool);
207 void (*default_cfg)(struct encoder_config *);
208 void (*convert_cfg)(struct encoder_config *, bool to_encoder);
209 bool (*menu)(struct encoder_config *);
210} enc_data[REC_NUM_FORMATS] =
211{
212 /* mp3_enc.codec */
213 [REC_FORMAT_MPA_L3] = {
214 mp3_enc_get_caps,
215 mp3_enc_default_config,
216 mp3_enc_convert_config,
217 mp3_enc_menu,
218 },
219 /* wav_enc.codec */
220 [REC_FORMAT_PCM_WAV] = {
221 NULL,
222 NULL,
223 NULL,
224 enc_no_config_menu,
225 },
226 /* wavpack_enc.codec */
227 [REC_FORMAT_WAVPACK] = {
228 NULL,
229 NULL,
230 NULL,
231 enc_no_config_menu,
232 },
233};
234
235static inline bool rec_format_ok(int rec_format)
236{
237 return (unsigned)rec_format < REC_NUM_FORMATS;
238}
239
240static bool enc_run_menu(int m, const struct menu_item items[],
241 struct encoder_config *cfg)
242{
243 int selected;
244 while (1)
245 {
246 switch (selected=menu_show(m))
247 {
248 case MENU_SELECTED_EXIT:
249 return false;
250
251 case MENU_ATTACHED_USB:
252 return true;
253
254 default:
255 if (items[selected].function &&
256 ENC_MENU_ITEM_FN(items[selected].function)(cfg))
257 return true;
258 gui_syncstatusbar_draw(&statusbars, true);
259 }
260 }
261} /* enc_run_menu */
262
263/* menu created when encoder has no configuration options */
264static bool enc_no_config_menu(struct encoder_config *cfg)
265{
266 static const struct menu_item items[] =
267 {
268 { ID2P(LANG_NO_SETTINGS), NULL }
269 };
270 int m;
271 bool result;
272
273 m = menu_init(items, ARRAYLEN(items), NULL, NULL, NULL, NULL);
274 result = enc_run_menu(m, items, NULL);
275 menu_exit(m);
276
277 return result;
278 (void)cfg;
279} /* enc_no_config_menu */
280
281/* update settings dependent upon encoder settings */
282static void enc_rec_settings_changed(struct encoder_config *cfg)
283{
284 struct encoder_config enc_config;
285 struct encoder_caps caps;
286 long table[MAX(CHN_NUM_MODES, REC_NUM_FREQ)];
287 int n;
288
289 if (cfg == NULL)
290 {
291 cfg = &enc_config;
292 cfg->rec_format = global_settings.rec_format;
293 global_to_encoder_config(cfg);
294 }
295
296 /* have to sync other settings when encoder settings change */
297 if (!enc_get_caps(cfg, &caps, true))
298 return;
299
300 /* rec_channels */
301 n = make_list_from_caps32(CHN_CAP_ALL, NULL,
302 caps.channel_caps, table);
303
304 /* no zero check needed: encoder must support at least one
305 sample rate that recording supports or it shouldn't be in
306 available in the recording options */
307 n = round_value_to_list32(global_settings.rec_channels,
308 table, n, true);
309 global_settings.rec_channels = table[n];
310
311 /* rec_frequency */
312 n = make_list_from_caps32(REC_SAMPR_CAPS, rec_freq_sampr,
313 caps.samplerate_caps, table);
314
315 n = round_value_to_list32(
316 rec_freq_sampr[global_settings.rec_frequency],
317 table, n, false);
318
319 global_settings.rec_frequency = round_value_to_list32(
320 table[n], rec_freq_sampr, REC_NUM_FREQ, false);
321} /* enc_rec_settings_changed */
322
323/** public stuff **/
324void global_to_encoder_config(struct encoder_config *cfg)
325{
326 const struct encoder_data *data = &enc_data[cfg->rec_format];
327 CALL_FN_(data->convert_cfg, cfg, true);
328} /* global_to_encoder_config */
329
330void encoder_config_to_global(const struct encoder_config *cfg)
331{
332 const struct encoder_data *data = &enc_data[cfg->rec_format];
333 CALL_FN_(data->convert_cfg, (struct encoder_config *)cfg, false);
334} /* encoder_config_to_global */
335
336bool enc_get_caps(const struct encoder_config *cfg,
337 struct encoder_caps *caps,
338 bool for_config)
339{
340 /* get_caps expects caps to be zeroed first */
341 memset(caps, 0, sizeof (*caps));
342
343 if (!rec_format_ok(cfg->rec_format))
344 return false;
345
346 if (enc_data[cfg->rec_format].get_caps)
347 {
348 enc_data[cfg->rec_format].get_caps(cfg, caps, for_config);
349 }
350 else
351 {
352 /* If no function provided...defaults to all */
353 caps->samplerate_caps = SAMPR_CAP_ALL;
354 caps->channel_caps = CHN_CAP_ALL;
355 }
356
357 return true;
358} /* enc_get_caps */
359
360/* Initializes the config struct with default values */
361bool enc_init_config(struct encoder_config *cfg)
362{
363 if (!rec_format_ok(cfg->rec_format))
364 return false;
365 CALL_FN_(enc_data[cfg->rec_format].default_cfg, cfg);
366 return true;
367} /* enc_init_config */
368
369/** Encoder Menus **/
370bool enc_config_menu(struct encoder_config *cfg)
371{
372 if (!rec_format_ok(cfg->rec_format))
373 return false;
374 return enc_data[cfg->rec_format].menu(cfg);
375} /* enc_config_menu */
376
377/** Global Settings **/
378
379/* Reset all codecs to defaults */
380void enc_global_settings_reset(void)
381{
382 struct encoder_config cfg;
383 cfg.rec_format = 0;
384
385 do
386 {
387 global_to_encoder_config(&cfg);
388 enc_init_config(&cfg);
389 encoder_config_to_global(&cfg);
390 if (cfg.rec_format == global_settings.rec_format)
391 enc_rec_settings_changed(&cfg);
392 }
393 while (++cfg.rec_format < REC_NUM_FORMATS);
394} /* enc_global_settings_reset */
395
396/* Apply new settings */
397void enc_global_settings_apply(void)
398{
399 struct encoder_config cfg;
400 if (!rec_format_ok(global_settings.rec_format))
401 global_settings.rec_format = REC_FORMAT_DEFAULT;
402
403 cfg.rec_format = global_settings.rec_format;
404 global_to_encoder_config(&cfg);
405 enc_rec_settings_changed(&cfg);
406 encoder_config_to_global(&cfg);
407} /* enc_global_settings_apply */
408
409/* Show an encoder's config menu based on the global_settings.
410 Modified settings are placed in global_settings.enc_config. */
411bool enc_global_config_menu(void)
412{
413 struct encoder_config cfg;
414
415 bool res;
416
417 if (!rec_format_ok(global_settings.rec_format))
418 global_settings.rec_format = REC_FORMAT_DEFAULT;
419
420 cfg.rec_format = global_settings.rec_format;
421
422 global_to_encoder_config(&cfg);
423
424 res = enc_config_menu(&cfg);
425 if (!res)
426 {
427 enc_rec_settings_changed(&cfg);
428 encoder_config_to_global(&cfg);
429 }
430
431 return res;
432} /* enc_global_config_menu */
diff --git a/apps/enc_config.h b/apps/enc_config.h
new file mode 100644
index 0000000000..53fa7638e9
--- /dev/null
+++ b/apps/enc_config.h
@@ -0,0 +1,73 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Michael Sevakis
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#ifndef ENC_CONFIG_H
20#define ENC_CONFIG_H
21
22#include "misc.h"
23#include "enc_base.h"
24
25/** Capabilities **/
26
27/* Capabilities returned by enc_get_caps that depend upon encoder settings */
28struct encoder_caps
29{
30 unsigned long samplerate_caps; /* Mask composed of SAMPR_CAP_* flags */
31 unsigned long channel_caps; /* Mask composed of CHN_CAP_* flags */
32};
33
34/* for_config:
35 * true- the capabilities returned should be contextual based upon the
36 * settings in the config structure
37 * false- the overall capabilities are being requested
38 */
39bool enc_get_caps(const struct encoder_config *cfg,
40 struct encoder_caps *caps,
41 bool for_config);
42
43/** Configuration **/
44
45/* These translate to a back between the global format and the per-
46 instance format */
47void global_to_encoder_config(struct encoder_config *cfg);
48void encoder_config_to_global(const struct encoder_config *cfg);
49
50/* Initializes the config struct with default values.
51 set afmt member before calling. */
52bool enc_init_config(struct encoder_config *cfg);
53
54/** Encoder Menus **/
55
56/* Shows an encoder's config menu given an encoder config returned by one
57 of the enc_api functions. Modified settings are not saved to disk but
58 instead are placed in the structure. Call enc_save_config to commit
59 the data. */
60bool enc_config_menu(struct encoder_config *cfg);
61
62/** Global Settings **/
63
64/* Reset all codecs to defaults */
65void enc_global_settings_reset(void);
66
67/* Apply new settings */
68void enc_global_settings_apply(void);
69
70/* Show an encoder's config menu based on the global_settings.
71 Modified settings are placed in global_settings.enc_config. */
72bool enc_global_config_menu(void);
73#endif /* ENC_CONFIG_H */
diff --git a/firmware/enc_base.c b/firmware/enc_base.c
new file mode 100644
index 0000000000..e346064fe2
--- /dev/null
+++ b/firmware/enc_base.c
@@ -0,0 +1,46 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Michael Sevakis
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 "config.h"
20#include "audio.h"
21
22/** mp3_enc.codec **/
23
24/* These are in descending order rather than in MPEG frequency index
25 order */
26const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR] =
27{
28 48000, 44100, 32000, /* MPEG 1 */
29 24000, 22050, 16000, /* MPEG 2 */
30#if 0
31 12000, 11025, 8000, /* MPEG 2.5 */
32#endif
33};
34
35/* All bitrates used in the MPA L3 standard */
36const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR] =
37{
38 8, 16, 24, 32, 40, 48, 56, 64, 80,
39 96, 112, 128, 144, 160, 192, 224, 256, 320
40};
41
42/** wav_enc.codec **/
43
44/** wavpack_enc.codec **/
45
46/** public functions **/
diff --git a/firmware/export/enc_base.h b/firmware/export/enc_base.h
new file mode 100644
index 0000000000..85101ac7fd
--- /dev/null
+++ b/firmware/export/enc_base.h
@@ -0,0 +1,270 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Base declarations for working with software encoders
11 *
12 * Copyright (C) 2006 Michael Sevakis
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef ENC_BASE_H
23#define ENC_BASE_H
24
25/** encoder config structures **/
26
27/** mp3_enc.codec **/
28#define MP3_BITR_CAP_8 (1 << 0)
29#define MP3_BITR_CAP_16 (1 << 1)
30#define MP3_BITR_CAP_24 (1 << 2)
31#define MP3_BITR_CAP_32 (1 << 3)
32#define MP3_BITR_CAP_40 (1 << 4)
33#define MP3_BITR_CAP_48 (1 << 5)
34#define MP3_BITR_CAP_56 (1 << 6)
35#define MP3_BITR_CAP_64 (1 << 7)
36#define MP3_BITR_CAP_80 (1 << 8)
37#define MP3_BITR_CAP_96 (1 << 9)
38#define MP3_BITR_CAP_112 (1 << 10)
39#define MP3_BITR_CAP_128 (1 << 11)
40#define MP3_BITR_CAP_144 (1 << 12)
41#define MP3_BITR_CAP_160 (1 << 13)
42#define MP3_BITR_CAP_192 (1 << 14)
43#define MP3_BITR_CAP_224 (1 << 15)
44#define MP3_BITR_CAP_256 (1 << 16)
45#define MP3_BITR_CAP_320 (1 << 17)
46#define MP3_ENC_NUM_BITR 18
47
48/* MPEG 1 */
49#define MPEG1_SAMPR_CAPS (SAMPR_CAP_32 | SAMPR_CAP_48 | SAMPR_CAP_44)
50#define MPEG1_BITR_CAPS (MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \
51 MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \
52 MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \
53 MP3_BITR_CAP_160 | MP3_BITR_CAP_192 | MP3_BITR_CAP_224 | \
54 MP3_BITR_CAP_256 | MP3_BITR_CAP_320)
55
56/* MPEG 2 */
57#define MPEG2_SAMPR_CAPS (SAMPR_CAP_22 | SAMPR_CAP_24 | SAMPR_CAP_16)
58#define MPEG2_BITR_CAPS (MP3_BITR_CAP_8 | MP3_BITR_CAP_16 | MP3_BITR_CAP_24 | \
59 MP3_BITR_CAP_32 | MP3_BITR_CAP_40 | MP3_BITR_CAP_48 | \
60 MP3_BITR_CAP_56 | MP3_BITR_CAP_64 | MP3_BITR_CAP_80 | \
61 MP3_BITR_CAP_96 | MP3_BITR_CAP_112 | MP3_BITR_CAP_128 | \
62 MP3_BITR_CAP_144 | MP3_BITR_CAP_160)
63
64#if 0
65/* MPEG 2.5 */
66#define MPEG2_5_SAMPR_CAPS (SAMPR_CAP_8 | SAMPR_CAP_12 | SAMPR_CAP_11)
67#define MPEG2_5_BITR_CAPS MPEG2_BITR_CAPS
68#endif
69
70/* Assume 44100 is always available and therefore MPEG1 */
71
72/* HAVE_MPEG* defines mainly apply to the bitrate menu */
73#if (REC_SAMPR_CAPS & MPEG2_SAMPR_CAPS) || defined (HAVE_SPDIF_IN)
74#define HAVE_MPEG2_SAMPR
75#endif
76
77#if 0
78#if (REC_SAMPR_CAPS & MPEG2_5_SAMPR_CAPS) || defined (HAVE_SPDIF_IN)
79#define HAVE_MPEG2_5_SAMPR
80#endif
81#endif /* 0 */
82
83#define MP3_ENC_SAMPR_CAPS (MPEG1_SAMPR_CAPS | MPEG2_SAMPR_CAPS)
84
85/* This number is count of full encoder set */
86#define MP3_ENC_NUM_SAMPR 6
87
88extern const unsigned long mp3_enc_sampr[MP3_ENC_NUM_SAMPR];
89extern const unsigned long mp3_enc_bitr[MP3_ENC_NUM_BITR];
90
91struct mp3_enc_config
92{
93 unsigned long bitrate;
94};
95
96#define MP3_ENC_BITRATE_CFG_DEFAULT 11 /* 128 */
97#define MP3_ENC_BITRATE_CFG_VALUE_LIST "8,16,24,32,40,48,56,64,80,96," \
98 "112,128,144,160,192,224,256,320"
99
100/** wav_enc.codec **/
101#define WAV_ENC_SAMPR_CAPS SAMPR_CAP_ALL
102
103struct wav_enc_config
104{
105#if 0
106 unsigned long sample_depth;
107#endif
108};
109
110/** wavpack_enc.codec **/
111#define WAVPACK_ENC_SAMPR_CAPS SAMPR_CAP_ALL
112
113struct wavpack_enc_config
114{
115#if 0
116 unsigned long sample_depth;
117#endif
118};
119
120struct encoder_config
121{
122 union
123 {
124 /* states which *_enc_config member is valid */
125 int rec_format; /* REC_FORMAT_* value */
126 int afmt; /* AFMT_* value */
127 };
128
129 union
130 {
131 struct mp3_enc_config mp3_enc;
132 struct wavpack_enc_config wavpack_enc;
133 struct wav_enc_config wav_enc;
134 };
135};
136
137/** Encoder chunk macros and definitions **/
138#define CHUNKF_START_FILE 0x0001 /* This chunk starts a new file */
139#define CHUNKF_END_FILE 0x0002 /* This chunk ends the current file */
140#define CHUNKF_PRERECORD 0x0010 /* This chunk is prerecord data,
141 a new file could start anytime */
142#define CHUNKF_ABORT 0x0020 /* Encoder should not finish this
143 chunk */
144#define CHUNKF_ERROR 0x80000000 /* An error has occured (passed to/
145 from encoder). Use the sign bit to
146 check (long)flags < 0. */
147
148/* Header at the beginning of every encoder chunk */
149struct enc_chunk_hdr
150{
151 unsigned long flags; /* in/out: flags used by encoder and file
152 writing */
153 size_t enc_size; /* out: amount of encoder data written to
154 chunk */
155 unsigned long num_pcm; /* out: number of PCM samples eaten during
156 processing
157 (<= size of allocated buffer) */
158 unsigned char *enc_data; /* out: pointer to enc_size_written bytes
159 of encoded audio data in chunk */
160 /* Encoder defined data follows header. Can be audio data + any other
161 stuff the encoder needs to handle on a per chunk basis */
162};
163
164/* Paranoia: be sure header size is 4-byte aligned */
165#define ENC_CHUNK_HDR_SIZE \
166 ALIGN_UP_P2(sizeof (struct enc_chunk_hdr), 2)
167/* Skip the chunk header and return data */
168#define ENC_CHUNK_SKIP_HDR(t, hdr) \
169 ((typeof (t))((char *)hdr + ENC_CHUNK_HDR_SIZE))
170/* Cast p to struct enc_chunk_hdr * */
171#define ENC_CHUNK_HDR(p) \
172 ((struct enc_chunk_hdr *)(p))
173
174enum enc_events
175{
176 /* File writing events - data points to enc_file_event_data */
177 ENC_START_FILE = 0, /* a new file has been opened and no data has yet
178 been written */
179 ENC_WRITE_CHUNK, /* write the current chunk to disk */
180 ENC_END_FILE, /* current file about to be closed and all valid
181 data has been written */
182 /* Encoder buffer events - data points to enc_buffer_event_data */
183 ENC_REC_NEW_STREAM, /* Take steps to finish current stream and start
184 new */
185};
186
187/**
188 * encoder can write extra data to the file such as headers or more encoded
189 * samples and must update sizes and samples accordingly.
190 */
191struct enc_file_event_data
192{
193 struct enc_chunk_hdr *chunk; /* Current chunk */
194 size_t new_enc_size; /* New size of chunk */
195 unsigned long new_num_pcm; /* New number of pcm in chunk */
196 const char *filename; /* filename to open if ENC_START_FILE */
197 int rec_file; /* Current file or < 0 if none */
198 unsigned long num_pcm_samples; /* Current pcm sample count written to
199 file so far. */
200};
201
202/**
203 * encoder may add some data to the end of the last and start of the next
204 * but must never yield when called so any encoding done should be absolutely
205 * minimal.
206 */
207struct enc_buffer_event_data
208{
209 unsigned long flags; /* in: One or more of:
210 * CHUNKF_PRERECORD
211 * CHUNKF_END_FILE
212 * CHUNKF_START_FILE
213 */
214 struct enc_chunk_hdr *pre_chunk; /* in: pointer to first prerecord
215 * chunk
216 */
217 struct enc_chunk_hdr *chunk; /* in,out: chunk were split occurs -
218 * first chunk of start
219 */
220};
221
222/** Callbacks called by encoder codec **/
223
224/* parameters passed to encoder by enc_get_inputs */
225struct enc_inputs
226{
227 unsigned long sample_rate; /* out - pcm frequency */
228 int num_channels; /* out - number of audio channels */
229 struct encoder_config *config; /* out - encoder settings */
230};
231
232void enc_get_inputs(struct enc_inputs *inputs);
233
234/* parameters pass from encoder to enc_set_parameters */
235struct enc_parameters
236{
237 /* IN parameters */
238 int afmt; /* AFMT_* id - sanity checker */
239 size_t chunk_size; /* max chunk size required */
240 unsigned long enc_sample_rate; /* actual sample rate used by encoder
241 (for recorded time calculation) */
242 size_t reserve_bytes; /* number of bytes to reserve immediately
243 following chunks */
244 void (*events_callback)(enum enc_events event,
245 void *data); /* pointer to events callback */
246 /* OUT parameters */
247 unsigned char *enc_buffer; /* pointer to enc_buffer */
248 size_t buf_chunk_size; /* size of chunks in enc_buffer */
249 int num_chunks; /* number of chunks allotted to encoder */
250 unsigned char *reserve_buffer; /* pointer to reserve_bytes bytes */
251};
252
253/* set the encoder dimensions - called by encoder codec at initialization
254 and termination */
255void enc_set_parameters(struct enc_parameters *params);
256/* returns pointer to next write chunk in circular buffer */
257struct enc_chunk_hdr * enc_get_chunk(void);
258/* releases the current chunk into the available chunks */
259void enc_finish_chunk(void);
260/* checks near empty state on pcm input buffer */
261int enc_pcm_buf_near_empty(void);
262
263#define PCM_MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */
264
265/* passes a pointer to next chunk of unprocessed wav data */
266unsigned char * enc_get_pcm_data(size_t size);
267/* puts some pcm data back in the queue */
268size_t enc_unget_pcm_data(size_t size);
269
270#endif /* ENC_BASE_H */
diff --git a/firmware/export/general.h b/firmware/export/general.h
new file mode 100644
index 0000000000..427e2773b8
--- /dev/null
+++ b/firmware/export/general.h
@@ -0,0 +1,38 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
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#ifndef GENERAL_H
21#define GENERAL_H
22
23#include <stdbool.h>
24
25/* round a signed/unsigned 32bit value to the closest of a list of values */
26/* returns the index of the closest value */
27int round_value_to_list32(unsigned long value,
28 const unsigned long list[],
29 int count,
30 bool signd);
31
32int make_list_from_caps32(unsigned long src_mask,
33 const unsigned long *src_list,
34 unsigned long caps_mask,
35 unsigned long *caps_list);
36
37
38#endif /* GENERAL_H */
diff --git a/firmware/export/pcm_sampr.h b/firmware/export/pcm_sampr.h
new file mode 100644
index 0000000000..c4a399b62f
--- /dev/null
+++ b/firmware/export/pcm_sampr.h
@@ -0,0 +1,310 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
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#ifndef PCM_SAMPR_H
21#define PCM_SAMPR_H
22
23/* These must be macros for comparison with SAMPR_CAP_* flags by the
24 preprocessor. Add samplerate index in descending order renumbering
25 the ones later in the list if any */
26#define FREQ_96 0
27#define FREQ_88 1
28#define FREQ_64 2
29#define FREQ_48 3
30#define FREQ_44 4
31#define FREQ_32 5
32#define FREQ_24 6
33#define FREQ_22 7
34#define FREQ_16 8
35#define FREQ_12 9
36#define FREQ_11 10
37#define FREQ_8 11
38#define SAMPR_NUM_FREQ 12
39
40/* sample rate values in HZ */
41#define SAMPR_96 96000
42#define SAMPR_88 88200
43#define SAMPR_64 64000
44#define SAMPR_48 48000
45#define SAMPR_44 44100
46#define SAMPR_32 32000
47#define SAMPR_24 24000
48#define SAMPR_22 22050
49#define SAMPR_16 16000
50#define SAMPR_12 12000
51#define SAMPR_11 11025
52#define SAMPR_8 8000
53
54/* sample rate capability bits */
55#define SAMPR_CAP_96 (1 << FREQ_96)
56#define SAMPR_CAP_88 (1 << FREQ_88)
57#define SAMPR_CAP_64 (1 << FREQ_64)
58#define SAMPR_CAP_48 (1 << FREQ_48)
59#define SAMPR_CAP_44 (1 << FREQ_44)
60#define SAMPR_CAP_32 (1 << FREQ_32)
61#define SAMPR_CAP_24 (1 << FREQ_24)
62#define SAMPR_CAP_22 (1 << FREQ_22)
63#define SAMPR_CAP_16 (1 << FREQ_16)
64#define SAMPR_CAP_12 (1 << FREQ_12)
65#define SAMPR_CAP_11 (1 << FREQ_11)
66#define SAMPR_CAP_8 (1 << FREQ_8)
67#define SAMPR_CAP_ALL (SAMPR_CAP_96 | SAMPR_CAP_88 | SAMPR_CAP_64 | \
68 SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \
69 SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \
70 SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8)
71
72/* Master list of all "standard" rates supported. */
73extern const unsigned long audio_master_sampr_list[SAMPR_NUM_FREQ];
74
75/** Hardware sample rates **/
76
77/* Enumeration of supported frequencies where 0 is the highest rate
78 supported and REC_NUM_FREQUENCIES is the number available */
79enum hw_freq_indexes
80{
81 __HW_FREQ_START_INDEX = -1, /* Make sure first in list is 0 */
82
83/* 96000 */
84#if (HW_SAMPR_CAPS & SAMPR_CAP_96) /* Macros and enums for each FREQ: */
85 HW_FREQ_96, /* Index in enumeration */
86#define HW_HAVE_96 /* Defined if this FREQ is defined */
87#define HW_HAVE_96_(...) __VA_ARGS__ /* Output its parameters for this FREQ */
88#else
89#define HW_HAVE_96_(...) /* Discards its parameters for this FREQ */
90#endif
91/* 88200 */
92#if (HW_SAMPR_CAPS & SAMPR_CAP_88)
93 HW_FREQ_88,
94#define HW_HAVE_88
95#define HW_HAVE_88_(...) __VA_ARGS__
96#else
97#define HW_HAVE_88_(...)
98#endif
99/* 64000 */
100#if (HW_SAMPR_CAPS & SAMPR_CAP_64)
101 HW_FREQ_64,
102#define HW_HAVE_64
103#define HW_HAVE_64_(...) __VA_ARGS__
104#else
105#define HW_HAVE_64_(...)
106#endif
107/* 48000 */
108#if (HW_SAMPR_CAPS & SAMPR_CAP_48)
109 HW_FREQ_48,
110#define HW_HAVE_48
111#define HW_HAVE_48_(...) __VA_ARGS__
112#else
113#define HW_HAVE_48_(...)
114#endif
115/* 44100 */
116 HW_FREQ_44,
117#define HW_HAVE_44
118#define HW_HAVE_44_(...) __VA_ARGS__
119/* 32000 */
120#if (HW_SAMPR_CAPS & SAMPR_CAP_32)
121 HW_FREQ_32,
122#define HW_HAVE_32
123#define HW_HAVE_32_(...) __VA_ARGS__
124#else
125#define HW_HAVE_32_(...)
126#endif
127/* 24000 */
128#if (HW_SAMPR_CAPS & SAMPR_CAP_24)
129 HW_FREQ_24,
130#define HW_HAVE_24
131#define HW_HAVE_24_(...) __VA_ARGS__
132#else
133#define HW_HAVE_24_(...)
134#endif
135/* 22050 */
136#if (HW_SAMPR_CAPS & SAMPR_CAP_22)
137 HW_FREQ_22,
138#define HW_HAVE_22
139#define HW_HAVE_22_(...) __VA_ARGS__
140#else
141#define HW_HAVE_22_(...)
142#endif
143/* 16000 */
144#if (HW_SAMPR_CAPS & SAMPR_CAP_16)
145 HW_FREQ_16,
146#define HW_HAVE_16
147#define HW_HAVE_16_(...) __VA_ARGS__
148#else
149#define HW_HAVE_16_(...)
150#endif
151/* 12000 */
152#if (HW_SAMPR_CAPS & SAMPR_CAP_12)
153 HW_FREQ_12,
154#define HW_HAVE_12
155#define HW_HAVE_12_(...) __VA_ARGS__
156#else
157#define HW_HAVE_12_(...)
158#endif
159/* 11025 */
160#if (HW_SAMPR_CAPS & SAMPR_CAP_11)
161 HW_FREQ_11,
162#define HW_HAVE_11
163#define HW_HAVE_11_(...) __VA_ARGS__
164#else
165#define HW_HAVE_11_(...)
166#endif
167/* 8000 */
168#if (HW_SAMPR_CAPS & SAMPR_CAP_8 )
169 HW_FREQ_8,
170#define HW_HAVE_8
171#define HW_HAVE_8_(...) __VA_ARGS__
172#else
173#define HW_HAVE_8_(...)
174#endif
175 HW_NUM_FREQ,
176 HW_FREQ_DEFAULT = HW_FREQ_44,
177 HW_SAMPR_DEFAULT = SAMPR_44,
178}; /* enum hw_freq_indexes */
179
180/* list of hardware sample rates */
181extern const unsigned long hw_freq_sampr[HW_NUM_FREQ];
182
183#ifdef HAVE_RECORDING
184/* Enumeration of supported frequencies where 0 is the highest rate
185 supported and REC_NUM_FREQUENCIES is the number available */
186enum rec_freq_indexes
187{
188 __REC_FREQ_START_INDEX = -1, /* Make sure first in list is 0 */
189
190/* 96000 */
191#if (REC_SAMPR_CAPS & SAMPR_CAP_96) /* Macros and enums for each FREQ: */
192 REC_FREQ_96, /* Index in enumeration */
193#define REC_HAVE_96 /* Defined if this FREQ is defined */
194#define REC_HAVE_96_(...) __VA_ARGS__ /* Output its parameters for this FREQ */
195#else
196#define REC_HAVE_96_(...) /* Discards its parameters for this FREQ */
197#endif
198/* 88200 */
199#if (REC_SAMPR_CAPS & SAMPR_CAP_88)
200 REC_FREQ_88,
201#define REC_HAVE_88
202#define REC_HAVE_88_(...) __VA_ARGS__
203#else
204#define REC_HAVE_88_(...)
205#endif
206/* 64000 */
207#if (REC_SAMPR_CAPS & SAMPR_CAP_64)
208 REC_FREQ_64,
209#define REC_HAVE_64
210#define REC_HAVE_64_(...) __VA_ARGS__
211#else
212#define REC_HAVE_64_(...)
213#endif
214/* 48000 */
215#if (REC_SAMPR_CAPS & SAMPR_CAP_48)
216 REC_FREQ_48,
217#define REC_HAVE_48
218#define REC_HAVE_48_(...) __VA_ARGS__
219#else
220#define REC_HAVE_48_(...)
221#endif
222/* 44100 */
223#if (REC_SAMPR_CAPS & SAMPR_CAP_44)
224 REC_FREQ_44,
225#define REC_HAVE_44
226#define REC_HAVE_44_(...) __VA_ARGS__
227#else
228#define REC_HAVE_44_(...)
229#endif
230/* 32000 */
231#if (REC_SAMPR_CAPS & SAMPR_CAP_32)
232 REC_FREQ_32,
233#define REC_HAVE_32
234#define REC_HAVE_32_(...) __VA_ARGS__
235#else
236#define REC_HAVE_32_(...)
237#endif
238/* 24000 */
239#if (REC_SAMPR_CAPS & SAMPR_CAP_24)
240 REC_FREQ_24,
241#define REC_HAVE_24
242#define REC_HAVE_24_(...) __VA_ARGS__
243#else
244#define REC_HAVE_24_(...)
245#endif
246/* 22050 */
247#if (REC_SAMPR_CAPS & SAMPR_CAP_22)
248 REC_FREQ_22,
249#define REC_HAVE_22
250#define REC_HAVE_22_(...) __VA_ARGS__
251#else
252#define REC_HAVE_22_(...)
253#endif
254/* 16000 */
255#if (REC_SAMPR_CAPS & SAMPR_CAP_16)
256 REC_FREQ_16,
257#define REC_HAVE_16
258#define REC_HAVE_16_(...) __VA_ARGS__
259#else
260#define REC_HAVE_16_(...)
261#endif
262/* 12000 */
263#if (REC_SAMPR_CAPS & SAMPR_CAP_12)
264 REC_FREQ_12,
265#define REC_HAVE_12
266#define REC_HAVE_12_(...) __VA_ARGS__
267#else
268#define REC_HAVE_12_(...)
269#endif
270/* 11025 */
271#if (REC_SAMPR_CAPS & SAMPR_CAP_11)
272 REC_FREQ_11,
273#define REC_HAVE_11
274#define REC_HAVE_11_(...) __VA_ARGS__
275#else
276#define REC_HAVE_11_(...)
277#endif
278/* 8000 */
279#if (REC_SAMPR_CAPS & SAMPR_CAP_8 )
280 REC_FREQ_8,
281#define REC_HAVE_8
282#define REC_HAVE_8_(...) __VA_ARGS__
283#else
284#define REC_HAVE_8_(...)
285#endif
286 REC_NUM_FREQ,
287 /* This should always come out I reckon */
288 REC_FREQ_DEFAULT = REC_FREQ_44,
289 /* Get the minimum bitcount needed to save the range of values */
290 REC_FREQ_CFG_NUM_BITS = (REC_NUM_FREQ > 8 ?
291 4 : (REC_NUM_FREQ > 4 ?
292 3 : (REC_NUM_FREQ > 2 ?
293 2 : 1
294 )
295 )
296 ),
297}; /* enum rec_freq_indexes */
298
299#define REC_FREQ_CFG_VAL_LIST &REC_HAVE_96_(",96") REC_HAVE_88_(",88") \
300 REC_HAVE_64_(",64") REC_HAVE_48_(",48") \
301 REC_HAVE_44_(",44") REC_HAVE_32_(",32") \
302 REC_HAVE_24_(",24") REC_HAVE_22_(",22") \
303 REC_HAVE_16_(",16") REC_HAVE_12_(",12") \
304 REC_HAVE_11_(",11") REC_HAVE_8_(",8")[1]
305
306/* List of recording supported sample rates (set or subset of master list) */
307extern const unsigned long rec_freq_sampr[REC_NUM_FREQ];
308#endif /* HAVE_RECORDING */
309
310#endif /* PCM_SAMPR_H */
diff --git a/firmware/general.c b/firmware/general.c
new file mode 100644
index 0000000000..7f4348046c
--- /dev/null
+++ b/firmware/general.c
@@ -0,0 +1,77 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
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 <limits.h>
20#include "config.h"
21#include "general.h"
22
23int round_value_to_list32(unsigned long value,
24 const unsigned long list[],
25 int count,
26 bool signd)
27{
28 unsigned long dmin = ULONG_MAX;
29 int idmin = -1, i;
30
31 for (i = 0; i < count; i++)
32 {
33 unsigned long diff;
34
35 if (list[i] == value)
36 {
37 idmin = i;
38 break;
39 }
40
41 if (signd ? ((long)list[i] < (long)value) : (list[i] < value))
42 diff = value - list[i];
43 else
44 diff = list[i] - value;
45
46 if (diff < dmin)
47 {
48 dmin = diff;
49 idmin = i;
50 }
51 }
52
53 return idmin;
54} /* round_value_to_list32 */
55
56/* Number of bits set in src_mask should equal src_list length */
57int make_list_from_caps32(unsigned long src_mask,
58 const unsigned long *src_list,
59 unsigned long caps_mask,
60 unsigned long *caps_list)
61{
62 int i, count;
63 unsigned long mask;
64
65 for (mask = src_mask, count = 0, i = 0;
66 mask != 0;
67 src_mask = mask, i++)
68 {
69 unsigned long test_bit;
70 mask &= mask - 1; /* Zero lowest bit set */
71 test_bit = mask ^ src_mask; /* Isolate the bit */
72 if (test_bit & caps_mask) /* Add item if caps has test bit set */
73 caps_list[count++] = src_list ? src_list[i] : (unsigned long)i;
74 }
75
76 return count;
77} /* make_list_from_caps32 */
diff --git a/firmware/pcm_sampr.c b/firmware/pcm_sampr.c
new file mode 100644
index 0000000000..cceb4b7399
--- /dev/null
+++ b/firmware/pcm_sampr.c
@@ -0,0 +1,76 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Michael Sevakis
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 "config.h"
20#include "pcm_sampr.h"
21
22/* Master list of all "standard" rates supported. */
23const unsigned long audio_master_sampr_list[SAMPR_NUM_FREQ] =
24{
25 [0 ... SAMPR_NUM_FREQ-1] = -1, /* any gaps set to -1 */
26 [FREQ_96] = SAMPR_96,
27 [FREQ_88] = SAMPR_88,
28 [FREQ_64] = SAMPR_64,
29 [FREQ_48] = SAMPR_48,
30 [FREQ_44] = SAMPR_44,
31 [FREQ_32] = SAMPR_32,
32 [FREQ_24] = SAMPR_24,
33 [FREQ_22] = SAMPR_22,
34 [FREQ_16] = SAMPR_16,
35 [FREQ_12] = SAMPR_12,
36 [FREQ_11] = SAMPR_11,
37 [FREQ_8 ] = SAMPR_8,
38};
39
40/* List of all hardware rates supported (set or subset of master list) */
41const unsigned long hw_freq_sampr[HW_NUM_FREQ] =
42{
43 [0 ... HW_NUM_FREQ-1] = -1,
44 HW_HAVE_96_([HW_FREQ_96] = SAMPR_96,)
45 HW_HAVE_88_([HW_FREQ_88] = SAMPR_88,)
46 HW_HAVE_64_([HW_FREQ_64] = SAMPR_64,)
47 HW_HAVE_48_([HW_FREQ_48] = SAMPR_48,)
48 HW_HAVE_44_([HW_FREQ_44] = SAMPR_44,)
49 HW_HAVE_32_([HW_FREQ_32] = SAMPR_32,)
50 HW_HAVE_24_([HW_FREQ_24] = SAMPR_24,)
51 HW_HAVE_22_([HW_FREQ_22] = SAMPR_22,)
52 HW_HAVE_16_([HW_FREQ_16] = SAMPR_16,)
53 HW_HAVE_12_([HW_FREQ_12] = SAMPR_12,)
54 HW_HAVE_11_([HW_FREQ_11] = SAMPR_11,)
55 HW_HAVE_8_( [HW_FREQ_8 ] = SAMPR_8 ,)
56};
57
58#ifdef HAVE_RECORDING
59/* List of recording supported sample rates (set or subset of master list) */
60const unsigned long rec_freq_sampr[REC_NUM_FREQ] =
61{
62 [0 ... REC_NUM_FREQ-1] = -1,
63 REC_HAVE_96_([REC_FREQ_96] = SAMPR_96,)
64 REC_HAVE_88_([REC_FREQ_88] = SAMPR_88,)
65 REC_HAVE_64_([REC_FREQ_64] = SAMPR_64,)
66 REC_HAVE_48_([REC_FREQ_48] = SAMPR_48,)
67 REC_HAVE_44_([REC_FREQ_44] = SAMPR_44,)
68 REC_HAVE_32_([REC_FREQ_32] = SAMPR_32,)
69 REC_HAVE_24_([REC_FREQ_24] = SAMPR_24,)
70 REC_HAVE_22_([REC_FREQ_22] = SAMPR_22,)
71 REC_HAVE_16_([REC_FREQ_16] = SAMPR_16,)
72 REC_HAVE_12_([REC_FREQ_12] = SAMPR_12,)
73 REC_HAVE_11_([REC_FREQ_11] = SAMPR_11,)
74 REC_HAVE_8_( [REC_FREQ_8 ] = SAMPR_8 ,)
75};
76#endif /* HAVE_RECORDING */
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
new file mode 100644
index 0000000000..6b92f9cc14
--- /dev/null
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -0,0 +1,738 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Michael Sevakis
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 <stdlib.h>
20#include "system.h"
21#include "kernel.h"
22#include "logf.h"
23#include "audio.h"
24#if defined(HAVE_UDA1380)
25#include "uda1380.h"
26#elif defined(HAVE_TLV320)
27#include "tlv320.h"
28#endif
29
30/* Avoid further #ifdef's for some codec functions */
31#if defined(HAVE_UDA1380)
32#define ac_init uda1380_init
33#define ac_mute uda1380_mute
34#define ac_set_frequency uda1380_set_frequency
35#elif defined(HAVE_TLV320)
36#define ac_init tlv320_init
37#define ac_mute tlv320_mute
38#define ac_set_frequency tlv320_set_frequency
39#endif
40
41/** Semi-private shared symbols **/
42
43/* the registered callback function to ask for more pcm data */
44extern pcm_more_callback_type pcm_callback_for_more;
45extern bool pcm_playing;
46extern bool pcm_paused;
47
48/* the registered callback function for when more data is available */
49extern pcm_more_callback_type pcm_callback_more_ready;
50extern bool pcm_recording;
51
52/* peaks */
53static int play_peak_left, play_peak_right;
54static unsigned long *rec_peak_addr;
55static int rec_peak_left, rec_peak_right;
56
57#define IIS_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \
58 (pcm_txsrc_select[pcm_monitor+1] << 8) | \
59 (4 << 2) ) /* 64 bit clocks / word clock */
60#define IIS_RESET 0x800
61
62#ifdef IAUDIO_X5
63#define SET_IIS_CONFIG(x) IIS1CONFIG = (x);
64#define IIS_CONFIG IIS1CONFIG
65#define PLLCR_SET_AUDIO_BITS_DEFPARM \
66 ((freq_ent[FPARM_CLSEL] << 28) | (1 << 22))
67#else
68#define SET_IIS_CONFIG(x) IIS2CONFIG = (x);
69#define IIS_CONFIG IIS2CONFIG
70#define PLLCR_SET_AUDIO_BITS_DEFPARM \
71 ((freq_ent[FPARM_CLSEL] << 28) | (3 << 22))
72
73#ifdef HAVE_SPDIF_OUT
74#define EBU_DEFPARM ((7 << 12) | (3 << 8) | (1 << 5) | (5 << 2))
75#endif
76#endif
77
78/** Sample rates **/
79#define FPARM_CLOCKSEL 0
80#define FPARM_CLSEL 1
81#define FPARM_FSEL 2
82#if CONFIG_CPU == MCF5249 && defined(HAVE_UDA1380)
83static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] =
84{
85 [HW_FREQ_88] = { 0x0c, 0x01, 0x03 },
86 [HW_FREQ_44] = { 0x06, 0x01, 0x02 },
87 [HW_FREQ_22] = { 0x04, 0x02, 0x01 },
88 [HW_FREQ_11] = { 0x02, 0x02, 0x00 },
89};
90#endif
91
92#if CONFIG_CPU == MCF5250 && defined(HAVE_TLV320)
93static const unsigned char pcm_freq_parms[HW_NUM_FREQ][3] =
94{
95 [HW_FREQ_88] = { 0x0c, 0x01, 0x02 },
96 [HW_FREQ_44] = { 0x06, 0x01, 0x01 },
97 [HW_FREQ_22] = { 0x04, 0x01, 0x00 },
98 [HW_FREQ_11] = { 0x02, 0x02, 0x00 },
99};
100#endif
101
102static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
103static const unsigned char *freq_ent = pcm_freq_parms[HW_FREQ_DEFAULT];
104
105/* set frequency used by the audio hardware */
106void pcm_set_frequency(unsigned int frequency)
107{
108 int index;
109
110 switch(frequency)
111 {
112 case SAMPR_11:
113 index = HW_FREQ_11;
114 break;
115 case SAMPR_22:
116 index = HW_FREQ_22;
117 break;
118 default:
119 case SAMPR_44:
120 index = HW_FREQ_44;
121 break;
122 case SAMPR_88:
123 index = HW_FREQ_88;
124 break;
125 }
126
127 /* remember table entry and rate */
128 freq_ent = pcm_freq_parms[index];
129 pcm_freq = hw_freq_sampr[index];
130} /* pcm_set_frequency */
131
132/** monitoring/source selection **/
133static int pcm_monitor = AUDIO_SRC_PLAYBACK;
134
135static const unsigned char pcm_txsrc_select[AUDIO_NUM_SOURCES+1] =
136{
137 [AUDIO_SRC_PLAYBACK+1] = 3, /* PDOR3 */
138 [AUDIO_SRC_MIC+1] = 4, /* IIS1 RcvData */
139 [AUDIO_SRC_LINEIN+1] = 4, /* IIS1 RcvData */
140#ifdef HAVE_FMRADIO_IN
141 [AUDIO_SRC_FMRADIO+1] = 4, /* IIS1 RcvData */
142#endif
143#ifdef HAVE_SPDIF_IN
144 [AUDIO_SRC_SPDIF+1] = 7, /* EBU1 RcvData */
145#endif
146};
147
148static const unsigned short pcm_dataincontrol[AUDIO_NUM_SOURCES+1] =
149{
150 [AUDIO_SRC_PLAYBACK+1] = 0x0200, /* Reset PDIR2 data flow */
151 [AUDIO_SRC_MIC+1] = 0xc020, /* Int. when 6 samples in FIFO,
152 PDIR2 src = ebu1RcvData */
153 [AUDIO_SRC_LINEIN+1] = 0xc020, /* Int. when 6 samples in FIFO,
154 PDIR2 src = ebu1RcvData */
155#ifdef HAVE_FMRADIO_IN
156 [AUDIO_SRC_FMRADIO+1] = 0xc020, /* Int. when 6 samples in FIFO,
157 PDIR2 src = ebu1RcvData */
158#endif
159#ifdef HAVE_SPDIF_IN
160 [AUDIO_SRC_SPDIF+1] = 0xc038, /* Int. when 6 samples in FIFO,
161 PDIR2 src = ebu1RcvData */
162#endif
163};
164
165static int pcm_rec_src = AUDIO_SRC_PLAYBACK;
166
167void pcm_set_monitor(int monitor)
168{
169 if ((unsigned)monitor >= AUDIO_NUM_SOURCES)
170 monitor = AUDIO_SRC_PLAYBACK;
171 pcm_monitor = monitor;
172} /* pcm_set_monitor */
173
174void pcm_set_rec_source(int source)
175{
176 if ((unsigned)source >= AUDIO_NUM_SOURCES)
177 source = AUDIO_SRC_PLAYBACK;
178 pcm_rec_src = source;
179} /* pcm_set_rec_source */
180
181/* apply audio settings */
182void pcm_apply_settings(bool reset)
183{
184 static int last_pcm_freq = HW_SAMPR_DEFAULT;
185#if 0
186 static int last_pcm_monitor = AUDIO_SRC_PLAYBACK;
187#endif
188 static int last_pcm_rec_src = AUDIO_SRC_PLAYBACK;
189
190 /* Playback must prevent pops and record monitoring won't work at all
191 adding IIS_RESET when setting IIS_CONFIG. Use a different method for
192 each. */
193 if (reset && (pcm_monitor != AUDIO_SRC_PLAYBACK))
194 {
195 /* Not playback - reset first */
196 SET_IIS_CONFIG(IIS_RESET);
197 reset = false;
198 }
199
200 if (pcm_rec_src != last_pcm_rec_src)
201 {
202 last_pcm_rec_src = pcm_rec_src;
203 DATAINCONTROL = pcm_dataincontrol[pcm_rec_src+1];
204 }
205
206 if (pcm_freq != last_pcm_freq)
207 {
208 last_pcm_freq = pcm_freq;
209 ac_set_frequency(freq_ent[FPARM_FSEL]);
210 coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
211 }
212
213 SET_IIS_CONFIG(IIS_DEFPARM | (reset ? IIS_RESET : 0));
214} /* pcm_apply_settings */
215
216/** DMA **/
217
218/****************************************************************************
219 ** Playback DMA transfer
220 **/
221
222/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
223void pcm_play_dma_start(const void *addr, size_t size)
224{
225 logf("pcm_play_dma_start");
226
227 addr = (void *)((unsigned long)addr & ~3); /* Align data */
228 size &= ~3; /* Size must be multiple of 4 */
229
230 pcm_playing = true;
231
232 /* Reset the audio FIFO */
233#ifdef HAVE_SPDIF_OUT
234 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
235#endif
236
237 /* Set up DMA transfer */
238 SAR0 = (unsigned long)addr; /* Source address */
239 DAR0 = (unsigned long)&PDOR3; /* Destination address */
240 BCR0 = size; /* Bytes to transfer */
241
242 /* Enable the FIFO and force one write to it */
243 pcm_apply_settings(false);
244
245 /* Also send the audio to S/PDIF */
246#ifdef HAVE_SPDIF_OUT
247 EBU1CONFIG = EBU_DEFPARM;
248#endif
249
250 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA |
251 DMA_SINC | DMA_SSIZE(3) | DMA_START;
252} /* pcm_play_dma_start */
253
254/* Stops the DMA transfer and interrupt */
255void pcm_play_dma_stop(void)
256{
257 logf("pcm_play_dma_stop");
258
259 pcm_playing = false;
260
261 DCR0 = 0;
262 DSR0 = 1;
263
264 /* Reset the FIFO */
265 pcm_apply_settings(false);
266
267#ifdef HAVE_SPDIF_OUT
268 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
269#endif
270} /* pcm_play_dma_stop */
271
272void pcm_init(void)
273{
274 logf("pcm_init");
275
276 pcm_playing = false;
277 pcm_paused = false;
278 pcm_callback_for_more = NULL;
279
280 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
281 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
282 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
283 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
284
285 /* Reset the audio FIFO */
286 SET_IIS_CONFIG(IIS_RESET);
287
288 pcm_set_frequency(-1);
289 pcm_set_monitor(-1);
290
291 /* Prevent pops (resets DAC to zero point) */
292 SET_IIS_CONFIG(IIS_DEFPARM | IIS_RESET);
293
294 /* Initialize default register values. */
295 ac_init();
296
297#if defined(HAVE_UDA1380)
298 /* Sleep a while so the power can stabilize (especially a long
299 delay is needed for the line out connector). */
300 sleep(HZ);
301 /* Power on FSDAC and HP amp. */
302 uda1380_enable_output(true);
303#elif defined(HAVE_TLV320)
304 sleep(HZ/4);
305#endif
306
307 /* UDA1380: Unmute the master channel
308 (DAC should be at zero point now). */
309 ac_mute(false);
310
311 /* Call pcm_play_dma_stop to initialize everything. */
312 pcm_play_dma_stop();
313
314 /* Enable interrupt at level 7, priority 0 */
315 ICR6 = (7 << 2);
316 IMR &= ~(1 << 14); /* bit 14 is DMA0 */
317} /* pcm_init */
318
319size_t pcm_get_bytes_waiting(void)
320{
321 return BCR0 & 0xffffff;
322} /* pcm_get_bytes_waiting */
323
324/* DMA0 Interrupt is called when the DMA has finished transfering a chunk
325 from the caller's buffer */
326void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
327void DMA0(void)
328{
329 int res = DSR0;
330
331 DSR0 = 1; /* Clear interrupt */
332 DCR0 &= ~DMA_EEXT;
333
334 /* Stop on error */
335 if ((res & 0x70) == 0)
336 {
337 pcm_more_callback_type get_more = pcm_callback_for_more;
338 unsigned char *next_start;
339 size_t next_size = 0;
340
341 if (get_more)
342 get_more(&next_start, &next_size);
343
344 if (next_size > 0)
345 {
346 SAR0 = (unsigned long)next_start; /* Source address */
347 BCR0 = next_size; /* Bytes to transfer */
348 DCR0 |= DMA_EEXT;
349 return;
350 }
351 else
352 {
353 /* Finished playing */
354#if 0
355 /* int. logfs can trash the display */
356 logf("DMA0 No Data:0x%04x", res);
357#endif
358 }
359 }
360 else
361 {
362 logf("DMA Error:0x%04x", res);
363 }
364
365 pcm_play_dma_stop();
366} /* DMA0 */
367
368/****************************************************************************
369 ** Recording DMA transfer
370 **/
371void pcm_rec_dma_start(const void *addr, size_t size)
372{
373 logf("pcm_rec_dma_start");
374
375 addr = (void *)((unsigned long)addr & ~3); /* Align data */
376 size &= ~3; /* Size must be multiple of 4 */
377
378 pcm_recording = true;
379
380 DAR1 = (unsigned long)addr; /* Destination address */
381 SAR1 = (unsigned long)&PDIR2; /* Source address */
382 BCR1 = size; /* Bytes to transfer */
383
384 rec_peak_addr = (unsigned long *)addr;
385
386 pcm_apply_settings(false);
387
388 /* Start the DMA transfer.. */
389#ifdef HAVE_SPDIF_IN
390 INTERRUPTCLEAR = 0x03c00000;
391#endif
392
393 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC |
394 DMA_DSIZE(3) | DMA_START;
395} /* pcm_dma_start */
396
397void pcm_rec_dma_stop(void)
398{
399 logf("pcm_rec_dma_stop");
400
401 pcm_recording = false;
402
403 DCR1 = 0;
404 DSR1 = 1; /* Clear interrupt */
405} /* pcm_dma_stop */
406
407void pcm_init_recording(void)
408{
409 logf("pcm_init_recording");
410
411 pcm_recording = false;
412 pcm_callback_more_ready = NULL;
413
414 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
415
416 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
417 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
418 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
419
420#ifdef HAVE_SPDIF_IN
421 /* PHASECONFIG setup: gain = 3*2^13, source = EBUIN */
422 PHASECONFIG = (6 << 3) | (4 << 0);
423#endif
424
425 pcm_rec_dma_stop();
426
427 ICR7 = (7 << 2); /* Enable interrupt at level 7, priority 0 */
428 IMR &= ~(1 << 15); /* bit 15 is DMA1 */
429} /* pcm_init_recording */
430
431void pcm_close_recording(void)
432{
433 logf("pcm_close_recording");
434
435 pcm_rec_dma_stop();
436
437 DMAROUTE &= 0xffff00ff;
438 ICR7 = 0x00; /* Disable interrupt */
439 IMR |= (1 << 15); /* bit 15 is DMA1 */
440} /* pcm_close_recording */
441
442/* DMA1 Interrupt is called when the DMA has finished transfering a chunk
443 into the caller's buffer */
444void DMA1(void) __attribute__ ((interrupt_handler, section(".icode")));
445void DMA1(void)
446{
447 int res = DSR1;
448 pcm_more_callback_type more_ready;
449 unsigned char *next_start;
450 ssize_t next_size = 0; /* passing <> 0 is indicates
451 an error condition */
452
453 DSR1 = 1; /* Clear interrupt */
454 DCR1 &= ~DMA_EEXT;
455
456 if (res & 0x70)
457 {
458 next_size = DMA_REC_ERROR_DMA;
459 logf("DMA1 err: 0x%x", res);
460 }
461#ifdef HAVE_SPDIF_IN
462 else if (pcm_rec_src == AUDIO_SRC_SPDIF &&
463 (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
464 {
465 INTERRUPTCLEAR = 0x03c00000;
466 next_size = DMA_REC_ERROR_SPDIF;
467 logf("spdif err");
468 }
469#endif
470
471 more_ready = pcm_callback_more_ready;
472
473 if (more_ready)
474 more_ready(&next_start, &next_size);
475
476 if (next_size > 0)
477 {
478 /* Start peaking at dest */
479 rec_peak_addr = (unsigned long *)next_start;
480 DAR1 = (unsigned long)next_start; /* Destination address */
481 BCR1 = (unsigned long)next_size; /* Bytes to transfer */
482 DCR1 |= DMA_EEXT;
483 return;
484 }
485 else
486 {
487#if 0
488 /* int. logfs can trash the display */
489 logf("DMA1 No Data:0x%04x", res);
490#endif
491 }
492
493 /* Finished recording */
494 pcm_rec_dma_stop();
495} /* DMA1 */
496
497void pcm_mute(bool mute)
498{
499 ac_mute(mute);
500 if (mute)
501 sleep(HZ/16);
502} /* pcm_mute */
503
504void pcm_play_pause_pause(void)
505{
506 /* Disable DMA peripheral request. */
507 DCR0 &= ~DMA_EEXT;
508 pcm_apply_settings(true);
509#ifdef HAVE_SPDIF_OUT
510 EBU1CONFIG = EBU_DEFPARM;
511#endif
512} /* pcm_play_pause_pause */
513
514void pcm_play_pause_unpause(void)
515{
516 /* Enable the FIFO and force one write to it */
517 pcm_apply_settings(false);
518#ifdef HAVE_SPDIF_OUT
519 EBU1CONFIG = EBU_DEFPARM;
520#endif
521 DCR0 |= DMA_EEXT | DMA_START;
522} /* pcm_play_pause_unpause */
523
524/**
525 * Return playback peaks - Peaks ahead in the DMA buffer based upon the
526 * calling period to attempt to compensate for
527 * delay.
528 */
529void pcm_calculate_peaks(int *left, int *right)
530{
531 unsigned long samples;
532 unsigned long *addr, *end;
533 long peak_p, peak_n;
534 int level;
535
536 static unsigned long last_peak_tick = 0;
537 static unsigned long frame_period = 0;
538
539 /* Throttled peak ahead based on calling period */
540 unsigned long period = current_tick - last_peak_tick;
541
542 /* Keep reasonable limits on period */
543 if (period < 1)
544 period = 1;
545 else if (period > HZ/5)
546 period = HZ/5;
547
548 frame_period = (3*frame_period + period) >> 2;
549
550 last_peak_tick = current_tick;
551
552 if (!pcm_playing || pcm_paused)
553 {
554 play_peak_left = play_peak_right = 0;
555 goto peak_done;
556 }
557
558 /* prevent interrupt from setting up next transfer and
559 be sure SAR0 and BCR0 refer to current transfer */
560 level = set_irq_level(HIGHEST_IRQ_LEVEL);
561
562 addr = (long *)(SAR0 & ~3);
563 samples = (BCR0 & 0xffffff) >> 2;
564
565 set_irq_level(level);
566
567 samples = MIN(frame_period*pcm_freq/HZ, samples);
568 end = addr + samples;
569 peak_p = peak_n = 0;
570
571 if (left && right)
572 {
573 if (samples > 0)
574 {
575 long peak_rp = 0, peak_rn = 0;
576
577 do
578 {
579 long value = *addr;
580 long ch;
581
582 ch = value >> 16;
583 if (ch > peak_p) peak_p = ch;
584 else if (ch < peak_n) peak_n = ch;
585
586 ch = (short)value;
587 if (ch > peak_rp) peak_rp = ch;
588 else if (ch < peak_rn) peak_rn = ch;
589
590 addr += 4;
591 }
592 while (addr < end);
593
594 play_peak_left = MAX(peak_p, -peak_n);
595 play_peak_right = MAX(peak_rp, -peak_rn);
596 }
597 }
598 else if (left || right)
599 {
600 if (samples > 0)
601 {
602 if (left)
603 {
604 /* Put left channel in low word */
605 addr = (long *)((short *)addr - 1);
606 end = (long *)((short *)end - 1);
607 }
608
609 do
610 {
611 long value = *(short *)addr;
612
613 if (value > peak_p) peak_p = value;
614 else if (value < peak_n) peak_n = value;
615
616 addr += 4;
617 }
618 while (addr < end);
619
620 if (left)
621 play_peak_left = MAX(peak_p, -peak_n);
622 else
623 play_peak_right = MAX(peak_p, -peak_n);
624 }
625 }
626
627peak_done:
628 if (left)
629 *left = play_peak_left;
630
631 if (right)
632 *right = play_peak_right;
633} /* pcm_calculate_peaks */
634
635/**
636 * Return recording peaks - Looks at every 4th sample from last peak up to
637 * current write position.
638 */
639void pcm_calculate_rec_peaks(int *left, int *right)
640{
641 unsigned long *pkaddr, *addr, *end;
642 long peak_lp, peak_ln; /* L +,- */
643 long peak_rp, peak_rn; /* R +,- */
644 int level;
645
646 if (!pcm_recording)
647 {
648 rec_peak_left = rec_peak_right = 0;
649 goto peak_done;
650 }
651
652 /* read these atomically or each value may not refer to the
653 same data transfer */
654 level = set_irq_level(HIGHEST_IRQ_LEVEL);
655
656 pkaddr = rec_peak_addr;
657 addr = pkaddr;
658 end = (unsigned long *)(DAR1 & ~3);
659
660 set_irq_level(level);
661
662 if (addr < end)
663 {
664 peak_lp = peak_ln =
665 peak_rp = peak_rn = 0;
666
667 /* peak one sample per line */
668 do
669 {
670 long value = *addr;
671 long ch;
672
673 ch = value >> 16;
674 if (ch < peak_ln)
675 peak_ln = ch;
676 else if (ch > peak_lp)
677 peak_lp = ch;
678
679 ch = (short)value;
680 if (ch > peak_rp)
681 peak_rp = ch;
682 else if (ch < peak_rn)
683 peak_rn = ch;
684
685 addr += 4;
686 }
687 while (addr < end);
688
689 /* only update rec_peak_addr if a DMA interrupt hasn't already
690 done so */
691 level = set_irq_level(HIGHEST_IRQ_LEVEL);
692
693 if (pkaddr == rec_peak_addr)
694 rec_peak_addr = end;
695
696 set_irq_level(level);
697
698 /* save peaks */
699 rec_peak_left = MAX(peak_lp, -peak_ln);
700 rec_peak_right = MAX(peak_rp, -peak_rn);
701 }
702
703peak_done:
704 if (left)
705 *left = rec_peak_left;
706
707 if (right)
708 *right = rec_peak_right;
709} /* pcm_calculate_rec_peaks */
710
711/**
712 * Select VINL & VINR source: 0=Line-in, 1=FM Radio
713 */
714/* All use GPIO */
715#if defined(IAUDIO_X5)
716 #define REC_MUX_BIT (1 << 29)
717 #define REC_MUX_SET_LINE() or_l(REC_MUX_BIT, &GPIO_OUT)
718 #define REC_MUX_SET_FM() and_l(~REC_MUX_BIT, &GPIO_OUT)
719#else
720#if defined(IRIVER_H100_SERIES)
721 #define REC_MUX_BIT (1 << 23)
722#elif defined(IRIVER_H300_SERIES)
723 #define REC_MUX_BIT (1 << 30)
724#endif
725 #define REC_MUX_SET_LINE() and_l(~REC_MUX_BIT, &GPIO_OUT)
726 #define REC_MUX_SET_FM() or_l(REC_MUX_BIT, &GPIO_OUT)
727#endif
728
729void pcm_rec_mux(int source)
730{
731 if (source == 0)
732 REC_MUX_SET_LINE(); /* Line In */
733 else
734 REC_MUX_SET_FM(); /* FM radio */
735
736 or_l(REC_MUX_BIT, &GPIO_ENABLE);
737 or_l(REC_MUX_BIT, &GPIO_FUNCTION);
738} /* pcm_rec_mux */