summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:07:30 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-11-06 18:07:30 +0000
commit0f5cb94aa4a334366a746fcbb22f3335ca413265 (patch)
tree8f89a96628c1810d51ee9816daf78edb8c76fcd4 /firmware
parent0b22795e26ee09de14f6ac23219adeda12f2fd5b (diff)
downloadrockbox-0f5cb94aa4a334366a746fcbb22f3335ca413265.tar.gz
rockbox-0f5cb94aa4a334366a746fcbb22f3335ca413265.zip
Big Patch adds primarily: Samplerate and format selection to recording for SWCODEC. Supprort for samplerates changing in playback (just goes with the recording part inseparably). Samplerates to all encoders. Encoders can be configured individually on a menu specific to the encoder in the recording menu. File creation is delayed until flush time to reduce spinups when splitting. Misc: statusbar icons for numbers are individual digits to display any number. Audio buffer was rearranged to maximize memory available to recording and properly reinitialized when trashed. ColdFire PCM stuff moved to target tree to avoid a complicated mess when adding samplerate switching. Some needed API changes and to neaten up growing gap between hardware and software codecs.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11452 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES26
-rw-r--r--firmware/drivers/tlv320.c45
-rw-r--r--firmware/drivers/uda1380.c84
-rw-r--r--firmware/export/audio.h106
-rw-r--r--firmware/export/config-h100.h6
-rw-r--r--firmware/export/config-h120.h6
-rw-r--r--firmware/export/config-h300.h7
-rw-r--r--firmware/export/config-iaudiox5.h6
-rw-r--r--firmware/export/id3.h91
-rw-r--r--firmware/export/pcm_playback.h16
-rw-r--r--firmware/export/pcm_record.h46
-rw-r--r--firmware/export/system.h81
-rw-r--r--firmware/export/thread.h3
-rw-r--r--firmware/export/tlv320.h10
-rw-r--r--firmware/export/uda1380.h13
-rw-r--r--firmware/id3.c138
-rw-r--r--firmware/mpeg.c20
-rw-r--r--firmware/pcm_playback.c700
-rw-r--r--firmware/pcm_record.c2002
-rw-r--r--firmware/system.c3
-rw-r--r--firmware/target/coldfire/iaudio/x5/system-x5.c7
-rw-r--r--firmware/target/coldfire/iriver/system-iriver.c7
-rw-r--r--firmware/target/coldfire/system-coldfire.c7
-rw-r--r--firmware/target/coldfire/system-target.h29
-rw-r--r--firmware/thread.c8
25 files changed, 2053 insertions, 1414 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 1ec3c82616..df38169be3 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -4,6 +4,7 @@ logf.c
4#endif 4#endif
5backlight.c 5backlight.c
6buffer.c 6buffer.c
7general.c
7common/atoi.c 8common/atoi.c
8common/crc32.c 9common/crc32.c
9common/ctype.c 10common/ctype.c
@@ -45,7 +46,12 @@ target/coldfire/memcpy-coldfire.S
45target/coldfire/memmove-coldfire.S 46target/coldfire/memmove-coldfire.S
46target/coldfire/memset-coldfire.S 47target/coldfire/memset-coldfire.S
47target/coldfire/memset16-coldfire.S 48target/coldfire/memset16-coldfire.S
49#ifndef SIMULATOR
50#ifndef BOOTLOADER
51target/coldfire/pcm-coldfire.c
52#endif
48target/coldfire/system-coldfire.c 53target/coldfire/system-coldfire.c
54#endif
49#elif (CONFIG_CPU == SH7034) 55#elif (CONFIG_CPU == SH7034)
50target/sh/memcpy-sh.S 56target/sh/memcpy-sh.S
51target/sh/memmove-sh.S 57target/sh/memmove-sh.S
@@ -207,15 +213,21 @@ drivers/wm8731l.c
207#elif defined(HAVE_TLV320) && !defined(SIMULATOR) 213#elif defined(HAVE_TLV320) && !defined(SIMULATOR)
208drivers/tlv320.c 214drivers/tlv320.c
209#endif 215#endif
210#if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) 216#if (CONFIG_CODEC == SWCODEC) && !defined(BOOTLOADER)
211pcm_playback.c 217pcm_sampr.c
212#endif
213#if CONFIG_CODEC == SWCODEC
214replaygain.c 218replaygain.c
215#endif 219#ifndef SIMULATOR
216#if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 220pcm_playback.c
221#endif /* SIMULATOR */
222#ifdef HAVE_RECORDING
223enc_base.c
224#if defined(CPU_COLDFIRE)
225#ifndef SIMULATOR
217pcm_record.c 226pcm_record.c
218#endif 227#endif /* SIMULATOR */
228#endif /* CPU_COLDFIRE */
229#endif /* HAVE_RECORDING */
230#endif /* SWCODEC && !BOOTLOADER */
219sound.c 231sound.c
220#if defined(IRIVER_IFP7XX_SERIES) && defined(STUB) 232#if defined(IRIVER_IFP7XX_SERIES) && defined(STUB)
221common/sscanf.c 233common/sscanf.c
diff --git a/firmware/drivers/tlv320.c b/firmware/drivers/tlv320.c
index abce31ef81..7c4bbbd1ee 100644
--- a/firmware/drivers/tlv320.c
+++ b/firmware/drivers/tlv320.c
@@ -82,7 +82,7 @@ void tlv320_init(void)
82 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ 82 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */
83 tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S); 83 tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S);
84 tlv320_write_reg(REG_DIA, DIA_ACT); 84 tlv320_write_reg(REG_DIA, DIA_ACT);
85 tlv320_write_reg(REG_SRC, (1 << 5)); /* 44.1kHz */ 85 tlv320_set_frequency(-1); /* default */
86 /* All ON except ADC, MIC and LINE */ 86 /* All ON except ADC, MIC and LINE */
87 tlv320_write_reg(REG_PC, PC_ADC | PC_MIC | PC_LINE); 87 tlv320_write_reg(REG_PC, PC_ADC | PC_MIC | PC_LINE);
88} 88}
@@ -96,6 +96,32 @@ void tlv320_reset(void)
96} 96}
97 97
98/** 98/**
99 * Sets internal sample rate for DAC and ADC relative to MCLK
100 * Selection for frequency:
101 * Fs: tlv: with:
102 * 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
103 * 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
104 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
105 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
106 */
107void tlv320_set_frequency(unsigned fsel)
108{
109 /* All rates available for 11.2896MHz besides 8.021 */
110 unsigned char values_src[3] =
111 {
112 /* Fs: */
113 (0x8 << 2) | SRC_CLKIN, /* 11025, 22050 */
114 (0x8 << 2), /* 44100 */
115 (0xf << 2), /* 88200 */
116 };
117
118 if (fsel >= ARRAYLEN(values_src))
119 fsel = 1;
120
121 tlv320_write_reg(REG_SRC, values_src[fsel]);
122}
123
124/**
99 * Sets left and right headphone volume 125 * Sets left and right headphone volume
100 * 126 *
101 * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB 127 * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB
@@ -142,7 +168,6 @@ void tlv320_set_recvol(int left, int right, int type)
142 value_aap &= ~AAP_MICB; 168 value_aap &= ~AAP_MICB;
143 169
144 tlv320_write_reg(REG_AAP, value_aap); 170 tlv320_write_reg(REG_AAP, value_aap);
145
146 } 171 }
147 else if (type == AUDIO_GAIN_LINEIN) 172 else if (type == AUDIO_GAIN_LINEIN)
148 { 173 {
@@ -180,15 +205,17 @@ void tlv320_mute(bool mute)
180} 205}
181 206
182/* Nice shutdown of TLV320 codec */ 207/* Nice shutdown of TLV320 codec */
183void tlv320_close() 208void tlv320_close(void)
184{ 209{
210 tlv320_mute(true);
211 sleep(HZ/8);
212
185 tlv320_write_reg(REG_PC, PC_OFF | PC_CLK | PC_OSC | PC_OUT | 213 tlv320_write_reg(REG_PC, PC_OFF | PC_CLK | PC_OSC | PC_OUT |
186 PC_DAC | PC_ADC | PC_MIC | PC_LINE); /* All OFF */ 214 PC_DAC | PC_ADC | PC_MIC | PC_LINE); /* All OFF */
187} 215}
188 216
189void tlv320_enable_recording(bool source_mic) 217void tlv320_enable_recording(bool source_mic)
190{ 218{
191 unsigned value_daif = tlv320_regs[REG_DAIF];
192 unsigned value_aap, value_pc; 219 unsigned value_aap, value_pc;
193 220
194 if (source_mic) 221 if (source_mic)
@@ -205,20 +232,12 @@ void tlv320_enable_recording(bool source_mic)
205 232
206 tlv320_write_reg(REG_PC, value_pc); 233 tlv320_write_reg(REG_PC, value_pc);
207 tlv320_write_reg(REG_AAP, value_aap); 234 tlv320_write_reg(REG_AAP, value_aap);
208
209 /* Enable MASTER mode (start sending I2S data to the CPU) */
210 value_daif |= DAIF_MS;
211 tlv320_write_reg(REG_DAIF, value_daif);
212} 235}
213 236
214void tlv320_disable_recording() 237void tlv320_disable_recording(void)
215{ 238{
216 unsigned value_pc = tlv320_regs[REG_PC]; 239 unsigned value_pc = tlv320_regs[REG_PC];
217 unsigned value_aap = tlv320_regs[REG_AAP]; 240 unsigned value_aap = tlv320_regs[REG_AAP];
218 unsigned value_daif = tlv320_regs[REG_DAIF];
219
220 value_daif &= ~DAIF_MS; /* disable MASTER mode */
221 tlv320_write_reg(REG_DAIF, value_daif);
222 241
223 value_aap |= AAP_MICM; /* mute MIC */ 242 value_aap |= AAP_MICM; /* mute MIC */
224 tlv320_write_reg(REG_PC, value_aap); 243 tlv320_write_reg(REG_PC, value_aap);
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 241a117385..d6dfe6623b 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -49,9 +49,10 @@ short recgain_line;
49#define NUM_DEFAULT_REGS 13 49#define NUM_DEFAULT_REGS 13
50unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] = 50unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
51{ 51{
52 REG_0, EN_DAC | EN_INT | EN_DEC | SYSCLK_256FS | WSPLL_25_50, 52 REG_0, EN_DAC | EN_INT | EN_DEC | ADC_CLK | DAC_CLK |
53 SYSCLK_256FS | WSPLL_25_50,
53 REG_I2S, I2S_IFMT_IIS, 54 REG_I2S, I2S_IFMT_IIS,
54 REG_PWR, PON_BIAS, 55 REG_PWR, PON_PLL | PON_BIAS,
55 /* PON_HP & PON_DAC is enabled later */ 56 /* PON_HP & PON_DAC is enabled later */
56 REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f), 57 REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f),
57 /* 00=max, 3f=mute */ 58 /* 00=max, 3f=mute */
@@ -60,7 +61,7 @@ unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
60 REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff), 61 REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff),
61 /* 00=max, ff=mute */ 62 /* 00=max, ff=mute */
62 REG_EQ, EQ_MODE_MAX, 63 REG_EQ, EQ_MODE_MAX,
63 /* Bass and tremble = 0 dB */ 64 /* Bass and treble = 0 dB */
64 REG_MUTE, MUTE_MASTER | MUTE_CH2, 65 REG_MUTE, MUTE_MASTER | MUTE_CH2,
65 /* Mute everything to start with */ 66 /* Mute everything to start with */
66 REG_MIX_CTL, MIX_CTL_MIX, 67 REG_MIX_CTL, MIX_CTL_MIX,
@@ -192,6 +193,43 @@ void uda1380_reset(void)
192#endif 193#endif
193} 194}
194 195
196/**
197 * Sets frequency settings for DAC and ADC relative to MCLK
198 *
199 * Selection for frequency ranges:
200 * Fs: range: with:
201 * 11025: 0 = 6.25 to 12.5 MCLK/2 SCLK, LRCK: Audio Clk / 16
202 * 22050: 1 = 12.5 to 25 MCLK/2 SCLK, LRCK: Audio Clk / 8
203 * 44100: 2 = 25 to 50 MCLK SCLK, LRCK: Audio Clk / 4 (default)
204 * 88200: 3 = 50 to 100 MCLK SCLK, LRCK: Audio Clk / 2 <= TODO: Needs WSPLL
205 */
206void uda1380_set_frequency(unsigned fsel)
207{
208 static const unsigned short values_reg[4][2] =
209 {
210 /* Fs: */
211 { 0, WSPLL_625_125 | SYSCLK_512FS }, /* 11025 */
212 { 0, WSPLL_125_25 | SYSCLK_256FS }, /* 22050 */
213 { MIX_CTL_SEL_NS, WSPLL_25_50 | SYSCLK_256FS }, /* 44100 */
214 { MIX_CTL_SEL_NS, WSPLL_50_100 | SYSCLK_256FS }, /* 88200 */
215 };
216
217 const unsigned short *ent;
218
219 if (fsel >= ARRAYLEN(values_reg))
220 fsel = 2;
221
222 ent = values_reg[fsel];
223
224 /* Set WSPLL input frequency range or SYSCLK divider */
225 uda1380_regs[REG_0] &= ~0xf;
226 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ent[1]);
227
228 /* Choose 3rd order or 5th order noise shaper */
229 uda1380_regs[REG_MIX_CTL] &= ~MIX_CTL_SEL_NS;
230 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL] | ent[0]);
231}
232
195/* Initialize UDA1380 codec with default register values (uda1380_defaults) */ 233/* Initialize UDA1380 codec with default register values (uda1380_defaults) */
196int uda1380_init(void) 234int uda1380_init(void)
197{ 235{
@@ -227,30 +265,34 @@ void uda1380_close(void)
227 */ 265 */
228void uda1380_enable_recording(bool source_mic) 266void uda1380_enable_recording(bool source_mic)
229{ 267{
268 uda1380_regs[REG_0] &= ~(ADC_CLK | DAC_CLK);
230 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC); 269 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC);
231 270
232 if (source_mic) 271 if (source_mic)
233 { 272 {
234 /* VGA_GAIN: 0=0 dB, F=30dB */ 273 /* VGA_GAIN: 0=0 dB, F=30dB */
274 /* Output of left ADC is fed into right bitstream */
275 uda1380_regs[REG_PWR] &= ~(PON_PLL | PON_PGAR | PON_ADCR);
235 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL); 276 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL);
277 uda1380_regs[REG_ADC] &= ~SKIP_DCFIL;
236 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK) 278 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK)
237 | SEL_LNA | SEL_MIC | EN_DCFIL); 279 | SEL_LNA | SEL_MIC | EN_DCFIL);
238 uda1380_write_reg(REG_PGA, 0); 280 uda1380_write_reg(REG_PGA, 0);
239 } else 281 }
282 else
240 { 283 {
241 /* PGA_GAIN: 0=0 dB, F=24dB */ 284 /* PGA_GAIN: 0=0 dB, F=24dB */
285 uda1380_regs[REG_PWR] &= ~(PON_PLL | PON_LNA);
242 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL 286 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL
243 | PON_PGAR | PON_ADCR); 287 | PON_PGAR | PON_ADCR);
244 uda1380_write_reg(REG_ADC, EN_DCFIL); 288 uda1380_write_reg(REG_ADC, EN_DCFIL);
245 uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & PGA_GAIN_MASK) 289 uda1380_write_reg(REG_PGA, uda1380_regs[REG_PGA] & PGA_GAIN_MASK);
246 | PGA_GAINL(0) | PGA_GAINR(0));
247 } 290 }
248 291
249 sleep(HZ/8); 292 sleep(HZ/8);
250 293
251 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER); 294 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER);
252 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(1)); 295 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(1));
253
254} 296}
255 297
256/** 298/**
@@ -262,10 +304,13 @@ void uda1380_disable_recording(void)
262 sleep(HZ/8); 304 sleep(HZ/8);
263 305
264 uda1380_write_reg(REG_I2S, I2S_IFMT_IIS); 306 uda1380_write_reg(REG_I2S, I2S_IFMT_IIS);
265 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] & ~(PON_LNA | PON_ADCL 307
266 | PON_ADCR | PON_PGAL 308 uda1380_regs[REG_PWR] &= ~(PON_LNA | PON_ADCL | PON_ADCR | PON_PGAL | PON_PGAR);
267 | PON_PGAR)); 309 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PLL);
268 uda1380_write_reg(REG_0, uda1380_regs[REG_0] & ~EN_ADC); 310
311 uda1380_regs[REG_0] &= ~EN_ADC;
312 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ADC_CLK | DAC_CLK);
313
269 uda1380_write_reg(REG_ADC, SKIP_DCFIL); 314 uda1380_write_reg(REG_ADC, SKIP_DCFIL);
270} 315}
271 316
@@ -373,20 +418,3 @@ void uda1380_set_monitor(int enable)
373 else /* mute channel 2 */ 418 else /* mute channel 2 */
374 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] | MUTE_CH2); 419 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] | MUTE_CH2);
375} 420}
376
377/* Change the order of the noise chaper,
378 5th order is recommended above 32kHz */
379void uda1380_set_nsorder(int order)
380{
381 switch(order)
382 {
383 case 5:
384 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL]
385 | MIX_CTL_SEL_NS);
386 break;
387 case 3:
388 default:
389 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL]
390 & ~MIX_CTL_SEL_NS);
391 }
392}
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 9099cb3765..d3f544de94 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -20,6 +20,20 @@
20#define AUDIO_H 20#define AUDIO_H
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include <sys/types.h>
24/* These must always be included with audio.h for this to compile under
25 cetain conditions. Do it here or else spread the complication around to
26 many files. */
27#if CONFIG_CODEC == SWCODEC
28#include "pcm_sampr.h"
29#include "pcm_playback.h"
30#ifdef HAVE_RECORDING
31#include "pcm_record.h"
32#include "id3.h"
33#include "enc_base.h"
34#endif /* HAVE_RECORDING */
35#endif /* CONFIG_CODEC == SWCODEC */
36
23 37
24#ifdef SIMULATOR 38#ifdef SIMULATOR
25#define audio_play(x) sim_audio_play(x) 39#define audio_play(x) sim_audio_play(x)
@@ -31,9 +45,6 @@
31#define AUDIO_STATUS_PRERECORD 8 45#define AUDIO_STATUS_PRERECORD 8
32#define AUDIO_STATUS_ERROR 16 46#define AUDIO_STATUS_ERROR 16
33 47
34#define AUDIO_STATUS_STAYON_FLAGS \
35 (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE | AUDIO_STATUS_RECORD | AUDIO_)
36
37#define AUDIOERR_DISK_FULL 1 48#define AUDIOERR_DISK_FULL 1
38 49
39#define AUDIO_GAIN_LINEIN 0 50#define AUDIO_GAIN_LINEIN 0
@@ -72,10 +83,11 @@ void audio_resume(void);
72void audio_next(void); 83void audio_next(void);
73void audio_prev(void); 84void audio_prev(void);
74int audio_status(void); 85int audio_status(void);
75bool audio_query_poweroff(void); 86#if CONFIG_CODEC == SWCODEC
76int audio_track_count(void); /* SWCODEC only */ 87int audio_track_count(void); /* SWCODEC only */
77long audio_filebufused(void); /* SWCODEC only */ 88long audio_filebufused(void); /* SWCODEC only */
78void audio_pre_ff_rewind(void); /* SWCODEC only */ 89void audio_pre_ff_rewind(void); /* SWCODEC only */
90#endif /* CONFIG_CODEC == SWCODEC */
79void audio_ff_rewind(long newtime); 91void audio_ff_rewind(long newtime);
80void audio_flush_and_reload_tracks(void); 92void audio_flush_and_reload_tracks(void);
81struct mp3entry* audio_current_track(void); 93struct mp3entry* audio_current_track(void);
@@ -89,18 +101,28 @@ void audio_error_clear(void);
89int audio_get_file_pos(void); 101int audio_get_file_pos(void);
90void audio_beep(int duration); 102void audio_beep(int duration);
91void audio_init_playback(void); 103void audio_init_playback(void);
104unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
92 105
93/* audio recording functions */ 106/* channel modes */
94void audio_init_recording(unsigned int buffer_offset); 107enum rec_channel_modes
95void audio_close_recording(void); 108{
96void audio_record(const char *filename); 109 __CHN_MODE_START_INDEX = -1,
97void audio_stop_recording(void); 110
98void audio_pause_recording(void); 111 CHN_MODE_STEREO,
99void audio_resume_recording(void); 112 CHN_MODE_MONO,
100void audio_new_file(const char *filename); 113
114 CHN_NUM_MODES
115};
116
117#if CONFIG_CODEC == SWCODEC
118/* channel mode capability bits */
119#define CHN_CAP_STEREO (1 << CHN_MODE_STEREO)
120#define CHN_CAP_MONO (1 << CHN_MODE_MONO)
121#define CHN_CAP_ALL (CHN_CAP_STEREO | CHN_CAP_MONO)
122#endif /* CONFIG_CODEC == SWCODEC */
101 123
102/* audio sources */ 124/* audio sources */
103enum 125enum audio_sources
104{ 126{
105 AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */ 127 AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */
106 AUDIO_SRC_MIC, /* monitor mic */ 128 AUDIO_SRC_MIC, /* monitor mic */
@@ -123,33 +145,57 @@ enum
123 AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1 145 AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
124}; 146};
125 147
126/* channel modes */ 148#ifdef HAVE_RECORDING
127enum 149/* parameters for audio_set_recording_options */
150struct audio_recording_options
128{ 151{
129 CHN_MODE_MONO = 1, 152 int rec_source;
130 CHN_MODE_STEREO, 153 int rec_frequency;
154 int rec_channels;
155 int rec_prerecord_time;
156#if CONFIG_CODEC == SWCODEC
157 int rec_source_flags; /* for rec_set_source */
158 struct encoder_config enc_config;
159#else
160 int rec_quality;
161 bool rec_editable;
162#endif
131}; 163};
132void audio_set_recording_options(int frequency, int quality, 164
133 int source, int channel_mode, 165/* audio recording functions */
134 bool editable, int prerecord_time); 166void audio_init_recording(unsigned int buffer_offset);
167void audio_close_recording(void);
168void audio_record(const char *filename);
169void audio_stop_recording(void);
170void audio_pause_recording(void);
171void audio_resume_recording(void);
172void audio_new_file(const char *filename);
173void audio_set_recording_options(struct audio_recording_options *options);
135void audio_set_recording_gain(int left, int right, int type); 174void audio_set_recording_gain(int left, int right, int type);
136unsigned long audio_recorded_time(void); 175unsigned long audio_recorded_time(void);
137unsigned long audio_num_recorded_bytes(void); 176unsigned long audio_num_recorded_bytes(void);
138#if 0 177
139#ifdef HAVE_SPDIF_POWER
140void audio_set_spdif_power_setting(bool on);
141#endif
142#endif
143unsigned long audio_get_spdif_sample_rate(void);
144unsigned long audio_prev_elapsed(void);
145#if CONFIG_CODEC == SWCODEC 178#if CONFIG_CODEC == SWCODEC
146/* audio encoder functions (defined in playback.c) */ 179/* SWCODEC recoring functions */
147int audio_get_encoder_id(void); 180/* playback.c */
148void audio_load_encoder(int enc_id); 181bool audio_load_encoder(int afmt);
149void audio_remove_encoder(void); 182void audio_remove_encoder(void);
183unsigned char *audio_get_recording_buffer(size_t *buffer_size);
150#endif /* CONFIG_CODEC == SWCODEC */ 184#endif /* CONFIG_CODEC == SWCODEC */
185#endif /* HAVE_RECORDING */
151 186
187#ifdef HAVE_SPDIF_IN
188#ifdef HAVE_SPDIF_POWER
189void audio_set_spdif_power_setting(bool on);
190bool audio_get_spdif_power_setting(void);
191#endif
192/* returns index into rec_master_sampr_list */
193int audio_get_spdif_sample_rate(void);
194/* > 0: monitor EBUin, 0: Monitor IISrecv, <0: reset only */
195void audio_spdif_set_monitor(int monitor_spdif);
196#endif /* HAVE_SPDIF_IN */
152 197
198unsigned long audio_prev_elapsed(void);
153 199
154 200
155/***********************************************************************/ 201/***********************************************************************/
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index 6f74078e1e..285ab88930 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -84,6 +84,12 @@
84/* define this if you have recording possibility */ 84/* define this if you have recording possibility */
85#define HAVE_RECORDING 1 85#define HAVE_RECORDING 1
86 86
87/* define hardware samples rate caps mask */
88#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
89
90/* define the bitmask of recording sample rates */
91#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
92
87#define HAVE_AGC 93#define HAVE_AGC
88 94
89#ifndef SIMULATOR 95#ifndef SIMULATOR
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index 1476102100..b22ff0eb22 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -77,6 +77,12 @@
77/* define this if you have recording possibility */ 77/* define this if you have recording possibility */
78#define HAVE_RECORDING 1 78#define HAVE_RECORDING 1
79 79
80/* define hardware samples rate caps mask */
81#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
82
83/* define the bitmask of recording sample rates */
84#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
85
80#define HAVE_AGC 86#define HAVE_AGC
81 87
82#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */ 88#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index 31f0f6729f..748635dcb4 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -72,6 +72,12 @@
72/* define this if you have recording possibility */ 72/* define this if you have recording possibility */
73#define HAVE_RECORDING 1 73#define HAVE_RECORDING 1
74 74
75/* define hardware samples rate caps mask */
76#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
77
78/* define the bitmask of recording sample rates */
79#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
80
75#define HAVE_AGC 81#define HAVE_AGC
76 82
77#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */ 83#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
@@ -157,4 +163,3 @@
157 163
158/* Define this for FM radio input available */ 164/* Define this for FM radio input available */
159#define HAVE_FMRADIO_IN 165#define HAVE_FMRADIO_IN
160
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index 80b010a6b0..d4c904ed23 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -9,6 +9,12 @@
9/* define this if you have recording possibility */ 9/* define this if you have recording possibility */
10#define HAVE_RECORDING 1 10#define HAVE_RECORDING 1
11 11
12/* define the bitmask of hardware sample rates */
13#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
14
15/* define the bitmask of recording sample rates */
16#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
17
12/* define this if you have a bitmap LCD display */ 18/* define this if you have a bitmap LCD display */
13#define HAVE_LCD_BITMAP 1 19#define HAVE_LCD_BITMAP 1
14 20
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 1d07affbfa..dd099e0204 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -24,13 +24,19 @@
24#include "file.h" 24#include "file.h"
25 25
26/* Audio file types. */ 26/* Audio file types. */
27enum { 27enum
28{
28 AFMT_UNKNOWN = 0, /* Unknown file format */ 29 AFMT_UNKNOWN = 0, /* Unknown file format */
29 30
31 /* start formats */
32
30 AFMT_MPA_L1, /* MPEG Audio layer 1 */ 33 AFMT_MPA_L1, /* MPEG Audio layer 1 */
31 AFMT_MPA_L2, /* MPEG Audio layer 2 */ 34 AFMT_MPA_L2, /* MPEG Audio layer 2 */
32 AFMT_MPA_L3, /* MPEG Audio layer 3 */ 35 AFMT_MPA_L3, /* MPEG Audio layer 3 */
33 36
37 AFMT_AIFF, /* Audio Interchange File Format */
38
39#if CONFIG_CODEC == SWCODEC
34 AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */ 40 AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */
35 AFMT_OGG_VORBIS, /* Ogg Vorbis */ 41 AFMT_OGG_VORBIS, /* Ogg Vorbis */
36 AFMT_FLAC, /* FLAC */ 42 AFMT_FLAC, /* FLAC */
@@ -40,54 +46,91 @@ enum {
40 AFMT_ALAC, /* Apple Lossless Audio Codec */ 46 AFMT_ALAC, /* Apple Lossless Audio Codec */
41 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */ 47 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */
42 AFMT_SHN, /* Shorten */ 48 AFMT_SHN, /* Shorten */
43 AFMT_AIFF, /* Audio Interchange File Format */
44 AFMT_SID, /* SID File Format */ 49 AFMT_SID, /* SID File Format */
45 AFMT_ADX, /* ADX */ 50 AFMT_ADX, /* ADX File Format */
51#endif
46 52
47 /* New formats must be added to the end of this list */ 53 /* add new formats at any index above this line to have a sensible order -
54 specified array index inits are used */
55 /* format arrays defined in id3.c */
48 56
49 AFMT_NUM_CODECS, 57 AFMT_NUM_CODECS,
50 58
51#if CONFIG_CODEC == SWCODEC 59#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
52 /* masks to decompose parts */ 60 /* masks to decompose parts */
53 CODEC_AFMT_MASK = 0x0fff, 61 CODEC_AFMT_MASK = 0x0fff,
54 CODEC_TYPE_MASK = 0x7000, 62 CODEC_TYPE_MASK = 0x7000,
55 63
56 /* switch for specifying codec type when requesting a filename */ 64 /* switch for specifying codec type when requesting a filename */
57 CODEC_TYPE_DECODER = (0 << 12), /* default */ 65 CODEC_TYPE_DECODER = (0 << 12), /* default */
58 CODEC_TYPE_ENCODER = (1 << 12) 66 CODEC_TYPE_ENCODER = (1 << 12),
59#endif 67#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
60}; 68};
61 69
62#if CONFIG_CODEC == SWCODEC 70#if CONFIG_CODEC == SWCODEC
63#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \ 71#define CODEC_EXTENSION "codec"
64 { label, codec_fname, codec_enc_fname, enc_ext } 72
65#else 73#ifdef HAVE_RECORDING
66#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \ 74#define ENCODER_SUFFIX "_enc"
67 { label } 75enum rec_format_indexes
68#endif 76{
77 __REC_FORMAT_START_INDEX = -1,
78
79 /* start formats */
80
81 REC_FORMAT_PCM_WAV,
82 REC_FORMAT_WAVPACK,
83 REC_FORMAT_MPA_L3,
84
85 /* add new formats at any index above this line to have a sensible order -
86 specified array index inits are used
87 REC_FORMAT_CFG_NUM_BITS should allocate enough bits to hold the range
88 REC_FORMAT_CFG_VALUE_LIST should be in same order as indexes
89 */
90
91 REC_NUM_FORMATS,
92
93 REC_FORMAT_DEFAULT = REC_FORMAT_PCM_WAV,
94 REC_FORMAT_CFG_NUM_BITS = 2
95};
96
97#define REC_FORMAT_CFG_VAL_LIST "wave,wvpk,mpa3"
98
99/* get REC_FORMAT_* corresponding AFMT_* */
100extern const int rec_format_afmt[REC_NUM_FORMATS];
101/* get AFMT_* corresponding REC_FORMAT_* */
102extern const int afmt_rec_format[AFMT_NUM_CODECS];
103
104#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
105 { label, root_fname, enc_root_fname, ext_list }
106#else /* !HAVE_RECORDING */
107#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
108 { label, root_fname, ext_list }
109#endif /* HAVE_RECORDING */
110#else /* !SWCODEC */
111
112#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
113 { label, ext_list }
114#endif /* CONFIG_CODEC == SWCODEC */
69 115
70/* record describing the audio format */ 116/* record describing the audio format */
71struct afmt_entry 117struct afmt_entry
72{ 118{
73#if CONFIG_CODEC == SWCODEC
74 char label[8]; /* format label */ 119 char label[8]; /* format label */
75 char *codec_fn; /* filename of decoder codec */ 120#if CONFIG_CODEC == SWCODEC
76 char *codec_enc_fn; /* filename of encoder codec */ 121 char *codec_root_fn; /* root codec filename (sans _enc and .codec) */
77 char *ext; /* default extension for file (enc only for now) */ 122#ifdef HAVE_RECORDING
78#else 123 char *codec_enc_root_fn; /* filename of encoder codec */
79 char label[4]; 124#endif
80#endif 125#endif
126 char *ext_list; /* double NULL terminated extension
127 list for type with the first as
128 the default for recording */
81}; 129};
82 130
83/* database of labels and codecs. add formats per above enum */ 131/* database of labels and codecs. add formats per above enum */
84extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS]; 132extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS];
85 133
86#if CONFIG_CODEC == SWCODEC
87/* recording quality to AFMT_* */
88extern const int rec_quality_info_afmt[9];
89#endif
90
91struct mp3entry { 134struct mp3entry {
92 char path[MAX_PATH]; 135 char path[MAX_PATH];
93 char* title; 136 char* title;
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index a4cd93969b..9c3e96ba63 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -19,11 +19,23 @@
19#ifndef PCM_PLAYBACK_H 19#ifndef PCM_PLAYBACK_H
20#define PCM_PLAYBACK_H 20#define PCM_PLAYBACK_H
21 21
22#include <sys/types.h>
23
24/* Typedef for registered callback (play and record) */
25typedef void (*pcm_more_callback_type)(unsigned char **start,
26 size_t *size);
27
22void pcm_init(void); 28void pcm_init(void);
29
30/* set the pcm frequency - use values in hw_sampr_list
31 * use -1 for the default frequency
32 */
23void pcm_set_frequency(unsigned int frequency); 33void pcm_set_frequency(unsigned int frequency);
34/* apply settings to hardware immediately */
35void pcm_apply_settings(bool reset);
24 36
25/* This is for playing "raw" PCM data */ 37/* This is for playing "raw" PCM data */
26void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), 38void pcm_play_data(pcm_more_callback_type get_more,
27 unsigned char* start, size_t size); 39 unsigned char* start, size_t size);
28 40
29void pcm_calculate_peaks(int *left, int *right); 41void pcm_calculate_peaks(int *left, int *right);
@@ -35,4 +47,4 @@ void pcm_play_pause(bool play);
35bool pcm_is_paused(void); 47bool pcm_is_paused(void);
36bool pcm_is_playing(void); 48bool pcm_is_playing(void);
37 49
38#endif 50#endif /* PCM_PLAYBACK_H */
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h
index b217335340..c1187a4c6c 100644
--- a/firmware/export/pcm_record.h
+++ b/firmware/export/pcm_record.h
@@ -20,24 +20,44 @@
20#ifndef PCM_RECORD_H 20#ifndef PCM_RECORD_H
21#define PCM_RECORD_H 21#define PCM_RECORD_H
22 22
23void enc_set_parameters(int chunk_size, int num_chunks, 23#define DMA_REC_ERROR_DMA ((size_t)-1)
24 int samp_per_chunk, char *head_ptr, int head_size, 24#ifdef HAVE_SPDIF_IN
25 int enc_id); 25#define DMA_REC_ERROR_SPDIF ((size_t)-2)
26void enc_get_inputs(int *buffer_size, int *channels, int *quality); 26#endif
27unsigned int* enc_alloc_chunk(void); 27/* Use AUDIO_SRC_* enumeration values */
28void enc_free_chunk(void); 28void pcm_set_monitor(int monitor);
29int enc_wavbuf_near_empty(void); 29void pcm_set_rec_source(int source);
30char* enc_get_wav_data(int size); 30
31extern void (*enc_set_header_callback)(void *head_buffer, int head_size, 31/**
32 int num_pcm_samples, bool is_file_header); 32 * RAW pcm data recording
33 * These calls are nescessary only when using the raw pcm apis directly.
34 */
35
36/* Initialize pcm recording interface */
37void pcm_init_recording(void);
38/* Uninitialze pcm recording interface */
39void pcm_close_recording(void);
40
41/* Start recording "raw" PCM data */
42void pcm_record_data(pcm_more_callback_type more_ready,
43 unsigned char *start, size_t size);
33 44
45/* Stop tranferring data into supplied buffer */
46void pcm_stop_recording(void);
47
48void pcm_calculate_rec_peaks(int *left, int *right);
49
50/** General functions for high level codec recording **/
51void pcm_rec_error_clear(void);
34unsigned long pcm_rec_status(void); 52unsigned long pcm_rec_status(void);
35void pcm_rec_init(void); 53void pcm_rec_init(void);
36void pcm_rec_mux(int source); 54void pcm_rec_mux(int source);
37int pcm_rec_current_bitrate(void); 55int pcm_rec_current_bitrate(void);
56int pcm_rec_encoder_afmt(void); /* AFMT_* value, AFMT_UNKNOWN if none */
57int pcm_rec_rec_format(void); /* Format index or -1 otherwise */
58unsigned long pcm_rec_sample_rate(void);
38int pcm_get_num_unprocessed(void); 59int pcm_get_num_unprocessed(void);
39void pcm_rec_get_peaks(int *left, int *right);
40 60
41/* audio.h contains audio recording functions */ 61/* audio.h contains audio_* recording functions */
42 62
43#endif 63#endif /* PCM_RECORD_H */
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 4a33d80466..9b90a6e80c 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -21,7 +21,6 @@
21#define __SYSTEM_H__ 21#define __SYSTEM_H__
22 22
23#include "cpu.h" 23#include "cpu.h"
24#include "config.h"
25#include "stdbool.h" 24#include "stdbool.h"
26 25
27extern void system_reboot (void); 26extern void system_reboot (void);
@@ -111,6 +110,23 @@ const char *get_cpu_boost_tracker(void);
111#define MAX(a, b) (((a)>(b))?(a):(b)) 110#define MAX(a, b) (((a)>(b))?(a):(b))
112#endif 111#endif
113 112
113/* return number of elements in array a */
114#define ARRAYLEN(a) (sizeof(a)/sizeof((a)[0]))
115
116/* return p incremented by specified number of bytes */
117#define SKIPBYTES(p, count) ((typeof (p))((char *)(p) + (count)))
118
119#define P2_M1(p2) ((1 << (p2))-1)
120
121/* align up or down to nearest 2^p2 */
122#define ALIGN_DOWN_P2(n, p2) ((n) & ~P2_M1(p2))
123#define ALIGN_UP_P2(n, p2) ALIGN_DOWN_P2((n) + P2_M1(p2),p2)
124
125/* align up or down to nearest integer multiple of a */
126#define ALIGN_DOWN(n, a) ((n)/(a)*(a))
127#define ALIGN_UP(n, a) ALIGN_DOWN((n)+((a)-1),a)
128
129/* live endianness conversion */
114#ifdef ROCKBOX_LITTLE_ENDIAN 130#ifdef ROCKBOX_LITTLE_ENDIAN
115#define letoh16(x) (x) 131#define letoh16(x) (x)
116#define letoh32(x) (x) 132#define letoh32(x) (x)
@@ -120,6 +136,8 @@ const char *get_cpu_boost_tracker(void);
120#define betoh32(x) swap32(x) 136#define betoh32(x) swap32(x)
121#define htobe16(x) swap16(x) 137#define htobe16(x) swap16(x)
122#define htobe32(x) swap32(x) 138#define htobe32(x) swap32(x)
139#define swap_odd_even_be32(x) (x)
140#define swap_odd_even_le32(x) swap_odd_even32(x)
123#else 141#else
124#define letoh16(x) swap16(x) 142#define letoh16(x) swap16(x)
125#define letoh32(x) swap32(x) 143#define letoh32(x) swap32(x)
@@ -129,6 +147,37 @@ const char *get_cpu_boost_tracker(void);
129#define betoh32(x) (x) 147#define betoh32(x) (x)
130#define htobe16(x) (x) 148#define htobe16(x) (x)
131#define htobe32(x) (x) 149#define htobe32(x) (x)
150#define swap_odd_even_be32(x) swap_odd_even32(x)
151#define swap_odd_even_le32(x) (x)
152#endif
153
154/* static endianness conversion */
155#define SWAP_16(x) ((typeof(x))(unsigned short)(((unsigned short)(x) >> 8) | \
156 ((unsigned short)(x) << 8)))
157
158#define SWAP_32(x) ((typeof(x))(unsigned long)( ((unsigned long)(x) >> 24) | \
159 (((unsigned long)(x) & 0xff0000ul) >> 8) | \
160 (((unsigned long)(x) & 0xff00ul) << 8) | \
161 ((unsigned long)(x) << 24)))
162
163#ifdef ROCKBOX_LITTLE_ENDIAN
164#define LE_TO_H16(x) (x)
165#define LE_TO_H32(x) (x)
166#define H_TO_LE16(x) (x)
167#define H_TO_LE32(x) (x)
168#define BE_TO_H16(x) SWAP_16(x)
169#define BE_TO_H32(x) SWAP_32(x)
170#define H_TO_BE16(x) SWAP_16(x)
171#define H_TO_BE32(x) SWAP_32(x)
172#else
173#define LE_TO_H16(x) SWAP_16(x)
174#define LE_TO_H32(x) SWAP_32(x)
175#define H_TO_LE16(x) SWAP_16(x)
176#define H_TO_LE32(x) SWAP_32(x)
177#define BE_TO_H16(x) (x)
178#define BE_TO_H32(x) (x)
179#define H_TO_BE16(x) (x)
180#define H_TO_BE32(x) (x)
132#endif 181#endif
133 182
134 183
@@ -181,6 +230,7 @@ enum {
181 : /* %0 */ I_CONSTRAINT((char)(mask)), \ 230 : /* %0 */ I_CONSTRAINT((char)(mask)), \
182 /* %1 */ "z"(address-GBR)) 231 /* %1 */ "z"(address-GBR))
183 232
233
184#endif /* CONFIG_CPU == SH7034 */ 234#endif /* CONFIG_CPU == SH7034 */
185 235
186#ifndef SIMULATOR 236#ifndef SIMULATOR
@@ -388,7 +438,20 @@ static inline unsigned long swap32(unsigned long value)
388#define invalidate_icache() 438#define invalidate_icache()
389 439
390#endif 440#endif
391#else 441
442#ifndef CPU_COLDFIRE
443static inline unsigned long swap_odd_even32(unsigned long value)
444{
445 /*
446 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
447 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
448 */
449 unsigned long t = value & 0xff00ff00;
450 return (t >> 8) | ((t ^ value) << 8);
451}
452#endif
453
454#else /* SIMULATOR */
392 455
393static inline unsigned short swap16(unsigned short value) 456static inline unsigned short swap16(unsigned short value)
394 /* 457 /*
@@ -412,8 +475,18 @@ static inline unsigned long swap32(unsigned long value)
412 return (lo << 16) | hi; 475 return (lo << 16) | hi;
413} 476}
414 477
478static inline unsigned long swap_odd_even32(unsigned long value)
479{
480 /*
481 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
482 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
483 */
484 unsigned long t = value & 0xff00ff00;
485 return (t >> 8) | ((t ^ value) << 8);
486}
487
415#define invalidate_icache() 488#define invalidate_icache()
416 489
417#endif 490#endif /* !SIMULATOR */
418 491
419#endif 492#endif /* __SYSTEM_H__ */
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index 17e6e3aa88..72c692ec3b 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -142,7 +142,10 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list);
142void sleep_thread(int ticks); 142void sleep_thread(int ticks);
143void block_thread(struct thread_entry **thread, int timeout); 143void block_thread(struct thread_entry **thread, int timeout);
144void wakeup_thread(struct thread_entry **thread); 144void wakeup_thread(struct thread_entry **thread);
145#ifdef HAVE_PRIORITY_SCHEDULING
145int thread_set_priority(struct thread_entry *thread, int priority); 146int thread_set_priority(struct thread_entry *thread, int priority);
147int thread_get_priority(struct thread_entry *thread);
148#endif
146void init_threads(void); 149void init_threads(void);
147int thread_stack_usage(const struct thread_entry *thread); 150int thread_stack_usage(const struct thread_entry *thread);
148int thread_get_status(const struct thread_entry *thread); 151int thread_get_status(const struct thread_entry *thread);
diff --git a/firmware/export/tlv320.h b/firmware/export/tlv320.h
index dfcbec4373..023ec9d874 100644
--- a/firmware/export/tlv320.h
+++ b/firmware/export/tlv320.h
@@ -24,6 +24,16 @@
24 24
25extern void tlv320_init(void); 25extern void tlv320_init(void);
26extern void tlv320_reset(void); 26extern void tlv320_reset(void);
27/**
28 * Sets internal sample rate for DAC and ADC relative to MCLK
29 * Selection for frequency:
30 * Fs: tlv: with:
31 * 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
32 * 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
33 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
34 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
35 */
36extern void tlv320_set_frequency(unsigned fsel);
27extern void tlv320_enable_output(bool enable); 37extern void tlv320_enable_output(bool enable);
28extern void tlv320_set_headphone_vol(int vol_l, int vol_r); 38extern void tlv320_set_headphone_vol(int vol_l, int vol_r);
29extern void tlv320_set_recvol(int left, int right, int type); 39extern void tlv320_set_recvol(int left, int right, int type);
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index 9c761c6a7d..639ca8aa5c 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -28,8 +28,17 @@ extern void uda1380_set_bass(int value);
28extern void uda1380_set_treble(int value); 28extern void uda1380_set_treble(int value);
29extern int uda1380_mute(int mute); 29extern int uda1380_mute(int mute);
30extern void uda1380_close(void); 30extern void uda1380_close(void);
31extern void uda1380_set_nsorder(int order); 31/**
32 32 * Sets frequency settings for DAC and ADC relative to MCLK
33 *
34 * Selection for frequency ranges:
35 * Fs: range: with:
36 * 11025: 0 = 6.25 to 12.5 SCLK, LRCK: Audio Clk / 16
37 * 22050: 1 = 12.5 to 25 SCLK, LRCK: Audio Clk / 8
38 * 44100: 2 = 25 to 50 SCLK, LRCK: Audio Clk / 4 (default)
39 * 88200: 3 = 50 to 100 SCLK, LRCK: Audio Clk / 2
40 */
41extern void uda1380_set_frequency(unsigned fsel);
33extern void uda1380_enable_recording(bool source_mic); 42extern void uda1380_enable_recording(bool source_mic);
34extern void uda1380_disable_recording(void); 43extern void uda1380_disable_recording(void);
35extern void uda1380_set_recvol(int left, int right, int type); 44extern void uda1380_set_recvol(int left, int right, int type);
diff --git a/firmware/id3.c b/firmware/id3.c
index 92f60a2095..7d03c75331 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -44,6 +44,89 @@
44#include "replaygain.h" 44#include "replaygain.h"
45#include "rbunicode.h" 45#include "rbunicode.h"
46 46
47/** Database of audio formats **/
48const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
49{
50 /* Unknown file format */
51 [AFMT_UNKNOWN] =
52 AFMT_ENTRY("???", NULL, NULL, NULL ),
53
54 /* MPEG Audio layer 1 */
55 [AFMT_MPA_L1] =
56 AFMT_ENTRY("MP1", "mpa", NULL, "mp1\0" ),
57 /* MPEG Audio layer 2 */
58 [AFMT_MPA_L2] =
59 AFMT_ENTRY("MP2", "mpa", NULL, "mpa\0mp2\0" ),
60 /* MPEG Audio layer 3 */
61 [AFMT_MPA_L3] =
62 AFMT_ENTRY("MP3", "mpa", "mp3_enc", "mp3\0" ),
63
64 /* Audio Interchange File Format */
65 [AFMT_AIFF] =
66 AFMT_ENTRY("AIFF", "aiff", NULL, "aiff\0aif\0"),
67
68#if CONFIG_CODEC == SWCODEC
69 /* Uncompressed PCM in a WAV file */
70 [AFMT_PCM_WAV] =
71 AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
72 /* Ogg Vorbis */
73 [AFMT_OGG_VORBIS] =
74 AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0" ),
75 /* FLAC */
76 [AFMT_FLAC] =
77 AFMT_ENTRY("FLAC", "flac", NULL, "flac\0" ),
78 /* Musepack */
79 [AFMT_MPC] =
80 AFMT_ENTRY("MPC", "mpc", NULL, "mpc\0" ),
81 /* A/52 (aka AC3) audio */
82 [AFMT_A52] =
83 AFMT_ENTRY("AC3", "a52", NULL, "a52\0ac3\0" ),
84 /* WavPack */
85 [AFMT_WAVPACK] =
86 AFMT_ENTRY("WV", "wavpack", "wavpack_enc", "wv\0" ),
87 /* Apple Lossless Audio Codec */
88 [AFMT_ALAC] =
89 AFMT_ENTRY("ALAC", "alac", NULL, "m4a\0" ),
90 /* Advanced Audio Coding in M4A container */
91 [AFMT_AAC] =
92 AFMT_ENTRY("AAC", "aac", NULL, "mp4\0" ),
93 /* Shorten */
94 [AFMT_SHN] =
95 AFMT_ENTRY("SHN", "shorten", NULL, "shn\0" ),
96 /* SID File Format */
97 [AFMT_SID] =
98 AFMT_ENTRY("SID", "sid", NULL, "sid\0" ),
99 /* ADX File Format */
100 [AFMT_ADX] =
101 AFMT_ENTRY("ADX", "adx", NULL, "adx\0" ),
102#endif
103};
104
105#if CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING)
106/* get REC_FORMAT_* corresponding AFMT_* */
107const int rec_format_afmt[REC_NUM_FORMATS] =
108{
109 /* give AFMT_UNKNOWN by default */
110 [0 ... REC_NUM_FORMATS-1] = AFMT_UNKNOWN,
111 /* add new entries below this line */
112 [REC_FORMAT_MPA_L3] = AFMT_MPA_L3,
113 [REC_FORMAT_WAVPACK] = AFMT_WAVPACK,
114 [REC_FORMAT_PCM_WAV] = AFMT_PCM_WAV,
115};
116
117/* get AFMT_* corresponding REC_FORMAT_* */
118const int afmt_rec_format[AFMT_NUM_CODECS] =
119{
120 /* give -1 by default */
121 [0 ... AFMT_NUM_CODECS-1] = -1,
122 /* add new entries below this line */
123 [AFMT_MPA_L3] = REC_FORMAT_MPA_L3,
124 [AFMT_WAVPACK] = REC_FORMAT_WAVPACK,
125 [AFMT_PCM_WAV] = REC_FORMAT_PCM_WAV,
126};
127#endif /* CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING) */
128/****/
129
47#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \ 130#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \
48 ((long)(b1 & 0x7F) << (2*7)) | \ 131 ((long)(b1 & 0x7F) << (2*7)) | \
49 ((long)(b2 & 0x7F) << (1*7)) | \ 132 ((long)(b2 & 0x7F) << (1*7)) | \
@@ -85,61 +168,6 @@ static const char* const genres[] = {
85 "Synthpop" 168 "Synthpop"
86}; 169};
87 170
88/* database of audio formats */
89const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
90{
91 /* Unknown file format */
92 AFMT_ENTRY("???", NULL, NULL, NULL ),
93 /* MPEG Audio layer 1 */
94 AFMT_ENTRY("MP1", "mpa.codec", NULL, NULL ),
95 /* MPEG Audio layer 2 */
96 AFMT_ENTRY("MP2", "mpa.codec", NULL, NULL ),
97 /* MPEG Audio layer 3 */
98 AFMT_ENTRY("MP3", "mpa.codec", "mp3_enc.codec", ".mp3"),
99#if CONFIG_CODEC == SWCODEC
100 /* Uncompressed PCM in a WAV file */
101 AFMT_ENTRY("WAV", "wav.codec", "wav_enc.codec", ".wav"),
102 /* Ogg Vorbis */
103 AFMT_ENTRY("Ogg", "vorbis.codec", NULL, NULL ),
104 /* FLAC */
105 AFMT_ENTRY("FLAC", "flac.codec", NULL, NULL ),
106 /* Musepack */
107 AFMT_ENTRY("MPC", "mpc.codec", NULL, NULL ),
108 /* A/52 (aka AC3) audio */
109 AFMT_ENTRY("AC3", "a52.codec", NULL, NULL ),
110 /* WavPack */
111 AFMT_ENTRY("WV", "wavpack.codec", "wavpack_enc.codec", ".wv" ),
112 /* Apple Lossless Audio Codec */
113 AFMT_ENTRY("ALAC", "alac.codec", NULL, NULL ),
114 /* Advanced Audio Coding in M4A container */
115 AFMT_ENTRY("AAC", "aac.codec", NULL, NULL ),
116 /* Shorten */
117 AFMT_ENTRY("SHN", "shorten.codec", NULL, NULL ),
118 /* Audio Interchange File Format */
119 AFMT_ENTRY("AIFF", "aiff.codec", NULL, NULL ),
120 /* SID File Format */
121 AFMT_ENTRY("SID", "sid.codec", NULL, NULL ),
122 /* ADX File Format */
123 AFMT_ENTRY("ADX", "adx.codec", NULL, NULL ),
124#endif
125};
126
127#if CONFIG_CODEC == SWCODEC
128/* recording quality to AFMT_* */
129const int rec_quality_info_afmt[9] =
130{
131 AFMT_MPA_L3, /* MPEG L3 64 kBit/s */
132 AFMT_MPA_L3, /* MPEG L3 96 kBit/s */
133 AFMT_MPA_L3, /* MPEG L3 128 kBit/s */
134 AFMT_MPA_L3, /* MPEG L3 160 kBit/s */
135 AFMT_MPA_L3, /* MPEG L3 192 kBit/s */
136 AFMT_MPA_L3, /* MPEG L3 224 kBit/s */
137 AFMT_MPA_L3, /* MPEG L3 320 kBit/s */
138 AFMT_WAVPACK, /* WavPack 909 kBit/s */
139 AFMT_PCM_WAV, /* PCM Wav 1411 kBit/s */
140};
141#endif /* SWCODEC */
142
143char* id3_get_genre(const struct mp3entry* id3) 171char* id3_get_genre(const struct mp3entry* id3)
144{ 172{
145 if( id3->genre_string ) 173 if( id3->genre_string )
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index ce1d995461..bb438a3ab4 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -2453,34 +2453,32 @@ static void stop_recording(void)
2453 resume_recording(); 2453 resume_recording();
2454} 2454}
2455 2455
2456void audio_set_recording_options(int frequency, int quality, 2456void audio_set_recording_options(struct audio_recording_options *options)
2457 int source, int channel_mode,
2458 bool editable, int prerecord_time)
2459{ 2457{
2460 bool is_mpeg1; 2458 bool is_mpeg1;
2461 2459
2462 is_mpeg1 = (frequency < 3)?true:false; 2460 is_mpeg1 = (options->rec_frequency < 3)?true:false;
2463 2461
2464 rec_version_index = is_mpeg1?3:2; 2462 rec_version_index = is_mpeg1?3:2;
2465 rec_frequency_index = frequency % 3; 2463 rec_frequency_index = options->rec_frequency % 3;
2466 2464
2467 shadow_encoder_control = (quality << 17) | 2465 shadow_encoder_control = (options->rec_quality << 17) |
2468 (rec_frequency_index << 10) | 2466 (rec_frequency_index << 10) |
2469 ((is_mpeg1?1:0) << 9) | 2467 ((is_mpeg1?1:0) << 9) |
2470 (((channel_mode * 2 + 1) & 3) << 6) | 2468 (((options->rec_channels * 2 + 1) & 3) << 6) |
2471 (1 << 5) /* MS-stereo */ | 2469 (1 << 5) /* MS-stereo */ |
2472 (1 << 2) /* Is an original */; 2470 (1 << 2) /* Is an original */;
2473 mas_writemem(MAS_BANK_D0, MAS_D0_ENCODER_CONTROL, &shadow_encoder_control,1); 2471 mas_writemem(MAS_BANK_D0, MAS_D0_ENCODER_CONTROL, &shadow_encoder_control,1);
2474 2472
2475 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control); 2473 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control);
2476 2474
2477 shadow_soft_mute = editable?4:0; 2475 shadow_soft_mute = options->rec_editable?4:0;
2478 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute,1); 2476 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute,1);
2479 2477
2480 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute); 2478 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute);
2481 2479
2482 shadow_io_control_main = ((1 << 10) | /* Monitoring ON */ 2480 shadow_io_control_main = ((1 << 10) | /* Monitoring ON */
2483 ((source < 2)?1:2) << 8) | /* Input select */ 2481 ((options->rec_source < 2)?1:2) << 8) | /* Input select */
2484 (1 << 5) | /* SDO strobe invert */ 2482 (1 << 5) | /* SDO strobe invert */
2485 ((is_mpeg1?0:1) << 3) | 2483 ((is_mpeg1?0:1) << 3) |
2486 (1 << 2) | /* Inverted SIBC clock signal */ 2484 (1 << 2) | /* Inverted SIBC clock signal */
@@ -2489,7 +2487,7 @@ void audio_set_recording_options(int frequency, int quality,
2489 2487
2490 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main); 2488 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2491 2489
2492 if(source == AUDIO_SRC_MIC) 2490 if(options->rec_source == AUDIO_SRC_MIC)
2493 { 2491 {
2494 /* Copy left channel to right (mono mode) */ 2492 /* Copy left channel to right (mono mode) */
2495 mas_codec_writereg(8, 0x8000); 2493 mas_codec_writereg(8, 0x8000);
@@ -2500,7 +2498,7 @@ void audio_set_recording_options(int frequency, int quality,
2500 mas_codec_writereg(8, 0); 2498 mas_codec_writereg(8, 0);
2501 } 2499 }
2502 2500
2503 prerecording_max_seconds = prerecord_time; 2501 prerecording_max_seconds = options->rec_prerecord_time;
2504 if(prerecording_max_seconds) 2502 if(prerecording_max_seconds)
2505 { 2503 {
2506 prerecording = true; 2504 prerecording = true;
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index cd14f123d1..b7ea96f3d3 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -16,259 +16,86 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include <stdbool.h> 19#include "system.h"
20#include "config.h" 20#include "kernel.h"
21#include "debug.h" 21#include "logf.h"
22#include "panic.h" 22#include "audio.h"
23#include <kernel.h> 23#if defined(HAVE_WM8975)
24#include "cpu.h"
25#include "i2c.h"
26#if defined(HAVE_UDA1380)
27#include "uda1380.h"
28#elif defined(HAVE_WM8975)
29#include "wm8975.h" 24#include "wm8975.h"
30#elif defined(HAVE_WM8758) 25#elif defined(HAVE_WM8758)
31#include "wm8758.h" 26#include "wm8758.h"
32#elif defined(HAVE_TLV320)
33#include "tlv320.h"
34#elif defined(HAVE_WM8731) || defined(HAVE_WM8721) 27#elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
35#include "wm8731l.h" 28#include "wm8731l.h"
36#elif CONFIG_CPU == PNX0101 29#elif CONFIG_CPU == PNX0101
30#include "string.h"
37#include "pnx0101.h" 31#include "pnx0101.h"
38#endif 32#endif
39#include "system.h"
40#include "logf.h"
41 33
42#include <stdio.h> 34/**
43#include <string.h> 35 * APIs implemented in the target-specific portion:
44#include <stdarg.h> 36 * Public -
45#include "pcm_playback.h" 37 * pcm_init
46#include "lcd.h" 38 * pcm_get_bytes_waiting
47#include "button.h" 39 * pcm_calculate_peaks
48#include "file.h" 40 * Semi-private -
49#include "buffer.h" 41 * pcm_play_dma_start
50#include "sprintf.h" 42 * pcm_play_dma_stop
51#include "button.h" 43 * pcm_play_pause_pause
52#include <string.h> 44 * pcm_play_pause_unpause
53 45 */
54static bool pcm_playing; 46
55static bool pcm_paused; 47/** These items may be implemented target specifically or need to
48 be shared semi-privately **/
56 49
57/* the registered callback function to ask for more mp3 data */ 50/* the registered callback function to ask for more mp3 data */
58static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; 51pcm_more_callback_type pcm_callback_for_more = NULL;
52bool pcm_playing = false;
53bool pcm_paused = false;
54
55void pcm_play_dma_start(const void *addr, size_t size);
56void pcm_play_dma_stop(void);
57void pcm_play_pause_pause(void);
58void pcm_play_pause_unpause(void);
59
60/** Functions that require targeted implementation **/
61
62#ifndef CPU_COLDFIRE
59 63
60#if (CONFIG_CPU == S3C2440) 64#if (CONFIG_CPU == S3C2440)
61 65
62/* TODO: Implement for Gigabeat 66/* TODO: Implement for Gigabeat
63 For now, just implement some dummy functions. 67 For now, just implement some dummy functions.
64*/ 68*/
65
66void pcm_init(void) 69void pcm_init(void)
67{ 70{
68
69} 71}
70 72
71static void dma_start(const void *addr, size_t size) 73void pcm_play_dma_start(const void *addr, size_t size)
72{ 74{
73 (void)addr; 75 (void)addr;
74 (void)size; 76 (void)size;
75} 77}
76 78
77void pcm_set_frequency(unsigned int frequency) 79void pcm_play_dma_stop(void)
78{
79 (void)frequency;
80}
81
82void pcm_play_stop(void)
83{ 80{
84} 81}
85 82
86size_t pcm_get_bytes_waiting(void) 83void pcm_play_pause_pause(void)
87{ 84{
88 return 0;
89} 85}
90#else
91#ifdef CPU_COLDFIRE
92 86
93#ifdef HAVE_SPDIF_OUT 87void pcm_play_pause_unpause(void)
94#define EBU_DEFPARM ((7 << 12) | (3 << 8) | (1 << 5) | (5 << 2))
95#endif
96#define IIS_DEFPARM(freq) ((freq << 12) | 0x300 | 4 << 2)
97#define IIS_RESET 0x800
98
99#ifdef IAUDIO_X5
100#define SET_IIS_CONFIG(x) IIS1CONFIG = (x);
101#else
102#define SET_IIS_CONFIG(x) IIS2CONFIG = (x);
103#endif
104
105static int pcm_freq = 0x6; /* 44.1 is default */
106
107int peak_left = 0, peak_right = 0;
108
109/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
110static void dma_start(const void *addr, size_t size)
111{ 88{
112 pcm_playing = true;
113
114 addr = (void *)((unsigned long)addr & ~3); /* Align data */
115 size &= ~3; /* Size must be multiple of 4 */
116
117 /* Reset the audio FIFO */
118#ifdef HAVE_SPDIF_OUT
119 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
120#endif
121
122 /* Set up DMA transfer */
123 SAR0 = (unsigned long)addr; /* Source address */
124 DAR0 = (unsigned long)&PDOR3; /* Destination address */
125 BCR0 = size; /* Bytes to transfer */
126
127 /* Enable the FIFO and force one write to it */
128 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq));
129 /* Also send the audio to S/PDIF */
130#ifdef HAVE_SPDIF_OUT
131 EBU1CONFIG = EBU_DEFPARM;
132#endif
133 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_SINC | (3 << 20) | DMA_START;
134} 89}
135 90
136/* Stops the DMA transfer and interrupt */
137static void dma_stop(void)
138{
139 pcm_playing = false;
140
141 DCR0 = 0;
142 DSR0 = 1;
143 /* Reset the FIFO */
144 SET_IIS_CONFIG(IIS_RESET | IIS_DEFPARM(pcm_freq));
145#ifdef HAVE_SPDIF_OUT
146 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
147#endif
148}
149
150/* sets frequency of input to DAC */
151void pcm_set_frequency(unsigned int frequency) 91void pcm_set_frequency(unsigned int frequency)
152{ 92{
153 switch(frequency) 93 (void)frequency;
154 {
155 case 11025:
156 pcm_freq = 0x2;
157#ifdef HAVE_UDA1380
158 uda1380_set_nsorder(3);
159#endif
160 break;
161 case 22050:
162 pcm_freq = 0x4;
163#ifdef HAVE_UDA1380
164 uda1380_set_nsorder(3);
165#endif
166 break;
167 case 44100:
168 default:
169 pcm_freq = 0x6;
170#ifdef HAVE_UDA1380
171 uda1380_set_nsorder(5);
172#endif
173 break;
174 }
175} 94}
176 95
177size_t pcm_get_bytes_waiting(void) 96size_t pcm_get_bytes_waiting(void)
178{ 97{
179 return (BCR0 & 0xffffff); 98 return 0;
180}
181
182/* DMA0 Interrupt is called when the DMA has finished transfering a chunk */
183void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
184void DMA0(void)
185{
186 int res = DSR0;
187
188 DSR0 = 1; /* Clear interrupt */
189 DCR0 &= ~DMA_EEXT;
190
191 /* Stop on error */
192 if(res & 0x70)
193 {
194 dma_stop();
195 logf("DMA Error:0x%04x", res);
196 }
197 else
198 {
199 size_t next_size;
200 unsigned char *next_start;
201 {
202 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
203 if (get_more)
204 get_more(&next_start, &next_size);
205 else
206 {
207 next_size = 0;
208 next_start = NULL;
209 }
210 }
211 if(next_size)
212 {
213 SAR0 = (unsigned long)next_start; /* Source address */
214 BCR0 = next_size; /* Bytes to transfer */
215 DCR0 |= DMA_EEXT;
216 }
217 else
218 {
219 /* Finished playing */
220 dma_stop();
221 logf("DMA No Data:0x%04x", res);
222 }
223 }
224
225 IPR |= (1<<14); /* Clear pending interrupt request */
226}
227
228void pcm_init(void)
229{
230 pcm_playing = false;
231 pcm_paused = false;
232
233 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
234 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
235 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
236 DMACONFIG = 1; /* DMA0Req = PDOR3 */
237
238 /* Reset the audio FIFO */
239 SET_IIS_CONFIG(IIS_RESET);
240
241 /* Enable interrupt at level 7, priority 0 */
242 ICR6 = 0x1c;
243 IMR &= ~(1<<14); /* bit 14 is DMA0 */
244
245 pcm_set_frequency(44100);
246
247 /* Prevent pops (resets DAC to zero point) */
248 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq) | IIS_RESET);
249
250#if defined(HAVE_UDA1380)
251 /* Initialize default register values. */
252 uda1380_init();
253
254 /* Sleep a while so the power can stabilize (especially a long
255 delay is needed for the line out connector). */
256 sleep(HZ);
257
258 /* Power on FSDAC and HP amp. */
259 uda1380_enable_output(true);
260
261 /* Unmute the master channel (DAC should be at zero point now). */
262 uda1380_mute(false);
263
264#elif defined(HAVE_TLV320)
265 tlv320_init();
266 sleep(HZ/4);
267 tlv320_mute(false);
268#endif
269
270 /* Call dma_stop to initialize everything. */
271 dma_stop();
272} 99}
273 100
274#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \ 101#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
@@ -286,14 +113,14 @@ void pcm_init(void)
286#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */ 113#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */
287#endif 114#endif
288 115
289static int pcm_freq = 44100; /* 44.1 is default */ 116static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
290 117
291/* NOTE: The order of these two variables is important if you use the iPod 118/* NOTE: The order of these two variables is important if you use the iPod
292 assembler optimised fiq handler, so don't change it. */ 119 assembler optimised fiq handler, so don't change it. */
293unsigned short* p IBSS_ATTR; 120unsigned short* p IBSS_ATTR;
294size_t p_size IBSS_ATTR; 121size_t p_size IBSS_ATTR;
295 122
296static void dma_start(const void *addr, size_t size) 123void pcm_play_dma_start(const void *addr, size_t size)
297{ 124{
298 p=(unsigned short*)addr; 125 p=(unsigned short*)addr;
299 p_size=size; 126 p_size=size;
@@ -341,7 +168,7 @@ static void dma_start(const void *addr, size_t size)
341} 168}
342 169
343/* Stops the DMA transfer and interrupt */ 170/* Stops the DMA transfer and interrupt */
344static void dma_stop(void) 171void pcm_play_dma_stop(void)
345{ 172{
346 pcm_playing = false; 173 pcm_playing = false;
347 174
@@ -365,9 +192,58 @@ static void dma_stop(void)
365 disable_fiq(); 192 disable_fiq();
366} 193}
367 194
195void pcm_play_pause_pause(void)
196{
197#if CONFIG_CPU == PP5020
198 /* Disable the interrupt */
199 IISCONFIG &= ~0x2;
200 /* Disable playback FIFO */
201 IISCONFIG &= ~0x20000000;
202#elif CONFIG_CPU == PP5002
203 /* Disable the interrupt */
204 IISFIFO_CFG &= ~(1<<9);
205 /* Disable playback FIFO */
206 IISCONFIG &= ~0x4;
207#endif
208 disable_fiq();
209}
210
211void pcm_play_pause_unpause(void)
212{
213 /* Enable the FIFO and fill it */
214
215 enable_fiq();
216
217 /* Enable playback FIFO */
218#if CONFIG_CPU == PP5020
219 IISCONFIG |= 0x20000000;
220#elif CONFIG_CPU == PP5002
221 IISCONFIG |= 0x4;
222#endif
223
224 /* Fill the FIFO - we assume there are enough bytes in the
225 pcm buffer to fill the 32-byte FIFO. */
226 while (p_size > 0) {
227 if (FIFO_FREE_COUNT < 2) {
228 /* Enable interrupt */
229#if CONFIG_CPU == PP5020
230 IISCONFIG |= 0x2;
231#elif CONFIG_CPU == PP5002
232 IISFIFO_CFG |= (1<<9);
233#endif
234 return;
235 }
236
237 IISFIFO_WR = (*(p++))<<16;
238 IISFIFO_WR = (*(p++))<<16;
239 p_size-=4;
240 }
241}
242
368void pcm_set_frequency(unsigned int frequency) 243void pcm_set_frequency(unsigned int frequency)
369{ 244{
370 pcm_freq=frequency; 245 (void)frequency;
246 pcm_freq = HW_SAMPR_DEFAULT;
371} 247}
372 248
373size_t pcm_get_bytes_waiting(void) 249size_t pcm_get_bytes_waiting(void)
@@ -378,8 +254,8 @@ size_t pcm_get_bytes_waiting(void)
378/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode 254/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode
379 has registers r8-r14 banked, and so does not need to be saved. This routine 255 has registers r8-r14 banked, and so does not need to be saved. This routine
380 uses only these registers, and so will never touch the stack unless it 256 uses only these registers, and so will never touch the stack unless it
381 actually needs to do so when calling callback_for_more. C version is still 257 actually needs to do so when calling pcm_callback_for_more. C version is
382 included below for reference. 258 still included below for reference.
383 */ 259 */
384#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 260#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
385void fiq(void) ICODE_ATTR __attribute__((naked)); 261void fiq(void) ICODE_ATTR __attribute__((naked));
@@ -433,10 +309,10 @@ void fiq(void)
433 "add r1, r11, #4 \n\t" /* r1 = &p_size */ 309 "add r1, r11, #4 \n\t" /* r1 = &p_size */
434 "str r9, [r0] \n\t" /* save internal copies of variables back */ 310 "str r9, [r0] \n\t" /* save internal copies of variables back */
435 "str r8, [r1] \n\t" 311 "str r8, [r1] \n\t"
436 "ldr r2, =callback_for_more\n\t" 312 "ldr r2, =pcm_callback_for_more\n\t"
437 "ldr r2, [r2] \n\t" /* get callback address */ 313 "ldr r2, [r2] \n\t" /* get callback address */
438 "cmp r2, #0 \n\t" /* check for null pointer */ 314 "cmp r2, #0 \n\t" /* check for null pointer */
439 "movne lr, pc \n\t" /* call callback_for_more */ 315 "movne lr, pc \n\t" /* call pcm_callback_for_more */
440 "bxne r2 \n\t" 316 "bxne r2 \n\t"
441 "ldmia sp!, { r0-r3, r12, lr}\n\t" 317 "ldmia sp!, { r0-r3, r12, lr}\n\t"
442 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */ 318 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */
@@ -477,7 +353,7 @@ void fiq(void)
477 "b .exit \n\t" 353 "b .exit \n\t"
478 ); 354 );
479} 355}
480#else 356#else /* !(CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002) */
481void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); 357void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
482void fiq(void) 358void fiq(void)
483{ 359{
@@ -507,20 +383,21 @@ void fiq(void)
507 } 383 }
508 384
509 /* p is empty, get some more data */ 385 /* p is empty, get some more data */
510 if (callback_for_more) { 386 if (pcm_callback_for_more) {
511 callback_for_more((unsigned char**)&p,&p_size); 387 pcm_callback_for_more((unsigned char**)&p,&p_size);
512 } 388 }
513 } while (p_size); 389 } while (p_size);
514 390
515 /* No more data, so disable the FIFO/FIQ */ 391 /* No more data, so disable the FIFO/FIQ */
516 dma_stop(); 392 pcm_play_dma_stop();
517} 393}
518#endif 394#endif /* CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 */
519 395
520void pcm_init(void) 396void pcm_init(void)
521{ 397{
522 pcm_playing = false; 398 pcm_playing = false;
523 pcm_paused = false; 399 pcm_paused = false;
400 pcm_callback_for_more = NULL;
524 401
525 /* Initialize default register values. */ 402 /* Initialize default register values. */
526 wmcodec_init(); 403 wmcodec_init();
@@ -531,8 +408,8 @@ void pcm_init(void)
531 /* Unmute the master channel (DAC should be at zero point now). */ 408 /* Unmute the master channel (DAC should be at zero point now). */
532 wmcodec_mute(false); 409 wmcodec_mute(false);
533 410
534 /* Call dma_stop to initialize everything. */ 411 /* Call pcm_play_dma_stop to initialize everything. */
535 dma_stop(); 412 pcm_play_dma_stop();
536} 413}
537 414
538#elif (CONFIG_CPU == PNX0101) 415#elif (CONFIG_CPU == PNX0101)
@@ -542,12 +419,16 @@ void pcm_init(void)
542short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES]; 419short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES];
543short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES]; 420short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES];
544 421
545static int pcm_freq = 44100; /* 44.1 is default */ 422static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
546 423
547unsigned short* p IBSS_ATTR; 424unsigned short* p IBSS_ATTR;
548size_t p_size IBSS_ATTR; 425size_t p_size IBSS_ATTR;
549 426
550static void dma_start(const void *addr, size_t size) 427void pcm_init(void)
428{
429}
430
431void pcm_play_dma_start(const void *addr, size_t size)
551{ 432{
552 p = (unsigned short*)addr; 433 p = (unsigned short*)addr;
553 p_size = size; 434 p_size = size;
@@ -555,11 +436,19 @@ static void dma_start(const void *addr, size_t size)
555 pcm_playing = true; 436 pcm_playing = true;
556} 437}
557 438
558static void dma_stop(void) 439void pcm_play_dma_stop(void)
559{ 440{
560 pcm_playing = false; 441 pcm_playing = false;
561} 442}
562 443
444void pcm_play_pause_pause(void)
445{
446}
447
448void pcm_play_pause_unpause(void)
449{
450}
451
563static inline void fill_dma_buf(int offset) 452static inline void fill_dma_buf(int offset)
564{ 453{
565 short *l, *r, *lend; 454 short *l, *r, *lend;
@@ -611,8 +500,8 @@ static inline void fill_dma_buf(int offset)
611 p = tmp_p; 500 p = tmp_p;
612 if (l >= lend) 501 if (l >= lend)
613 return; 502 return;
614 else if (callback_for_more) 503 else if (pcm_callback_for_more)
615 callback_for_more((unsigned char**)&p, 504 pcm_callback_for_more((unsigned char**)&p,
616 &p_size); 505 &p_size);
617 } 506 }
618 while (p_size); 507 while (p_size);
@@ -647,9 +536,10 @@ unsigned long physical_address(void *p)
647void pcm_init(void) 536void pcm_init(void)
648{ 537{
649 int i; 538 int i;
650 callback_for_more = NULL; 539
651 pcm_playing = false; 540 pcm_playing = false;
652 pcm_paused = false; 541 pcm_paused = false;
542 pcm_callback_for_more = NULL;
653 543
654 memset(dma_buf_left, 0, sizeof(dma_buf_left)); 544 memset(dma_buf_left, 0, sizeof(dma_buf_left));
655 memset(dma_buf_right, 0, sizeof(dma_buf_right)); 545 memset(dma_buf_right, 0, sizeof(dma_buf_right));
@@ -691,271 +581,37 @@ void pcm_init(void)
691 581
692void pcm_set_frequency(unsigned int frequency) 582void pcm_set_frequency(unsigned int frequency)
693{ 583{
694 pcm_freq=frequency; 584 (void)frequency;
585 pcm_freq = HW_SAMPR_DEFAULT;
695} 586}
696size_t pcm_get_bytes_waiting(void) 587size_t pcm_get_bytes_waiting(void)
697{ 588{
698 return p_size; 589 return p_size;
699} 590}
700#endif 591#endif /* CONFIG_CPU == */
701 592
702void pcm_play_stop(void) 593/* dummy functions for those not actually supporting all this yet */
594void pcm_apply_settings(bool reset)
703{ 595{
704 if (pcm_playing) { 596 (void)reset;
705 dma_stop();
706 }
707} 597}
708 598
709#endif 599void pcm_set_monitor(int monitor)
710
711void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
712 unsigned char* start, size_t size)
713{ 600{
714 callback_for_more = get_more; 601 (void)monitor;
715
716 if (!(start && size))
717 {
718 if (get_more)
719 get_more(&start, &size);
720 else
721 return;
722 }
723 if (start && size)
724 {
725 dma_start(start, size);
726 if (pcm_paused) {
727 pcm_paused = false;
728 pcm_play_pause(false);
729 }
730 }
731} 602}
603/** **/
732 604
733void pcm_mute(bool mute) 605void pcm_mute(bool mute)
734{ 606{
735#ifdef HAVE_UDA1380 607#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
736 uda1380_mute(mute);
737#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
738 || defined(HAVE_WM8731) || defined(HAVE_WM8721) 608 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
739 wmcodec_mute(mute); 609 wmcodec_mute(mute);
740#elif defined(HAVE_TLV320)
741 tlv320_mute(mute);
742#endif 610#endif
743 if (mute) 611 if (mute)
744 sleep(HZ/16); 612 sleep(HZ/16);
745} 613}
746 614
747void pcm_play_pause(bool play)
748{
749 bool needs_change = pcm_paused == play;
750
751 /* This needs to be done ahead of the rest to prevent infinite
752 * recursion from dma_start */
753 pcm_paused = !play;
754 if (pcm_playing && needs_change) {
755 if(play) {
756 if (pcm_get_bytes_waiting()) {
757 logf("unpause");
758
759#ifdef CPU_COLDFIRE
760 /* Enable the FIFO and force one write to it */
761 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq));
762#ifdef HAVE_SPDIF_OUT
763 EBU1CONFIG = EBU_DEFPARM;
764#endif
765 DCR0 |= DMA_EEXT | DMA_START;
766#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
767 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
768 /* Enable the FIFO and fill it */
769
770 enable_fiq();
771
772 /* Enable playback FIFO */
773#if CONFIG_CPU == PP5020
774 IISCONFIG |= 0x20000000;
775#elif CONFIG_CPU == PP5002
776 IISCONFIG |= 0x4;
777#endif
778
779 /* Fill the FIFO - we assume there are enough bytes in the
780 pcm buffer to fill the 32-byte FIFO. */
781 while (p_size > 0) {
782 if (FIFO_FREE_COUNT < 2) {
783 /* Enable interrupt */
784#if CONFIG_CPU == PP5020
785 IISCONFIG |= 0x2;
786#elif CONFIG_CPU == PP5002
787 IISFIFO_CFG |= (1<<9);
788#endif
789 return;
790 }
791
792 IISFIFO_WR = (*(p++))<<16;
793 IISFIFO_WR = (*(p++))<<16;
794 p_size-=4;
795 }
796#elif (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) /* End wmcodecs */
797 /* nothing yet */
798#endif
799 } else {
800#if (CONFIG_CPU != PNX0101 && CONFIG_CPU != S3C2440)
801 size_t next_size;
802 unsigned char *next_start;
803 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
804 logf("unpause, no data waiting");
805 if (get_more)
806 get_more(&next_start, &next_size);
807 if (next_start && next_size)
808 dma_start(next_start, next_size);
809 else
810 {
811 dma_stop();
812 logf("unpause attempted, no data");
813 }
814#endif
815 }
816 } else {
817 logf("pause");
818
819#ifdef CPU_COLDFIRE
820 /* Disable DMA peripheral request. */
821 DCR0 &= ~DMA_EEXT;
822 SET_IIS_CONFIG(IIS_RESET | IIS_DEFPARM(pcm_freq));
823#ifdef HAVE_SPDIF_OUT
824 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
825#endif
826#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
827 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
828#if CONFIG_CPU == PP5020
829 /* Disable the interrupt */
830 IISCONFIG &= ~0x2;
831 /* Disable playback FIFO */
832 IISCONFIG &= ~0x20000000;
833#elif CONFIG_CPU == PP5002
834 /* Disable the interrupt */
835 IISFIFO_CFG &= ~(1<<9);
836 /* Disable playback FIFO */
837 IISCONFIG &= ~0x4;
838#endif
839
840 disable_fiq();
841#elif (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) /* End wmcodecs */
842 /* nothing yet */
843#endif
844 }
845 } /* pcm_playing && needs_change */
846}
847
848bool pcm_is_playing(void) {
849 return pcm_playing;
850}
851
852bool pcm_is_paused(void) {
853 return pcm_paused;
854}
855
856
857#if defined(CPU_COLDFIRE)
858/* Peaks ahead in the DMA buffer based upon the calling period to
859 attempt to compensate for the delay. Keeps a moving average of
860 length four. */
861void pcm_calculate_peaks(int *left, int *right)
862{
863 unsigned long samples;
864 unsigned long *addr, *end;
865 long peak_p, peak_n;
866
867 static unsigned long last_peak_tick = 0;
868 static unsigned long frame_period = 0;
869
870 /* Throttled peak ahead based on calling period */
871 unsigned long period = current_tick - last_peak_tick;
872
873 /* Keep reasonable limits on period */
874 if (period < 1)
875 period = 1;
876 else if (period > HZ/5)
877 period = HZ/5;
878
879 frame_period = (3*frame_period + period) >> 2;
880
881 last_peak_tick = current_tick;
882
883 if (!pcm_playing || pcm_paused)
884 {
885 peak_left = peak_right = 0;
886 goto peak_done;
887 }
888
889 samples = (BCR0 & 0xffffff) >> 2;
890 addr = (long *)(SAR0 & ~3);
891 samples = MIN(frame_period*44100/HZ, samples);
892 end = addr + samples;
893 peak_p = peak_n = 0;
894
895 if (left && right)
896 {
897 if (samples > 0)
898 {
899 long peak_rp = 0, peak_rn = 0;
900
901 do
902 {
903 long value = *addr;
904 long ch;
905
906 ch = value >> 16;
907 if (ch > peak_p) peak_p = ch;
908 else if (ch < peak_n) peak_n = ch;
909
910 ch = (short)value;
911 if (ch > peak_rp) peak_rp = ch;
912 else if (ch < peak_rn) peak_rn = ch;
913
914 addr += 4;
915 }
916 while (addr < end);
917
918 peak_left = MAX(peak_p, -peak_n);
919 peak_right = MAX(peak_rp, -peak_rn);
920 }
921 }
922 else if (left || right)
923 {
924 if (samples > 0)
925 {
926 if (left)
927 {
928 /* Put left channel in low word */
929 addr = (long *)((short *)addr - 1);
930 end = (long *)((short *)end - 1);
931 }
932
933 do
934 {
935 long value = *(short *)addr;
936
937 if (value > peak_p) peak_p = value;
938 else if (value < peak_n) peak_n = value;
939
940 addr += 4;
941 }
942 while (addr < end);
943
944 if (left)
945 peak_left = MAX(peak_p, -peak_n);
946 else
947 peak_right = MAX(peak_p, -peak_n);
948 }
949 }
950
951peak_done:
952 if (left)
953 *left = peak_left;
954
955 if (right)
956 *right = peak_right;
957}
958#else
959/* 615/*
960 * This function goes directly into the DMA buffer to calculate the left and 616 * This function goes directly into the DMA buffer to calculate the left and
961 * right peak values. To avoid missing peaks it tries to look forward two full 617 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -1037,4 +693,94 @@ void pcm_calculate_peaks(int *left, int *right)
1037 } 693 }
1038#endif 694#endif
1039} 695}
696
1040#endif /* CPU_COLDFIRE */ 697#endif /* CPU_COLDFIRE */
698
699/****************************************************************************
700 * Functions that do not require targeted implementation but only a targeted
701 * interface
702 */
703
704/* Common code to pcm_play_data and pcm_play_pause
705 Returns true if DMA playback was started, else false. */
706bool pcm_play_data_start(pcm_more_callback_type get_more,
707 unsigned char *start, size_t size)
708{
709 if (!(start && size))
710 {
711 size = 0;
712 if (get_more)
713 get_more(&start, &size);
714 }
715
716 if (start && size)
717 {
718 pcm_play_dma_start(start, size);
719 return true;
720 }
721
722 return false;
723}
724
725void pcm_play_data(pcm_more_callback_type get_more,
726 unsigned char *start, size_t size)
727{
728 pcm_callback_for_more = get_more;
729
730 if (pcm_play_data_start(get_more, start, size) && pcm_paused)
731 {
732 pcm_paused = false;
733 pcm_play_pause(false);
734 }
735}
736
737void pcm_play_pause(bool play)
738{
739 bool needs_change = pcm_paused == play;
740
741 /* This needs to be done ahead of the rest to prevent infinite
742 recursion from pcm_play_data */
743 pcm_paused = !play;
744
745 if (pcm_playing && needs_change)
746 {
747 if (play)
748 {
749 if (pcm_get_bytes_waiting())
750 {
751 logf("unpause");
752 pcm_play_pause_unpause();
753 }
754 else
755 {
756 logf("unpause, no data waiting");
757 if (!pcm_play_data_start(pcm_callback_for_more, NULL, 0))
758 {
759 pcm_play_dma_stop();
760 logf("unpause attempted, no data");
761 }
762 }
763 }
764 else
765 {
766 logf("pause");
767 pcm_play_pause_pause();
768 }
769 } /* pcm_playing && needs_change */
770}
771
772void pcm_play_stop(void)
773{
774 if (pcm_playing)
775 pcm_play_dma_stop();
776}
777
778bool pcm_is_playing(void)
779{
780 return pcm_playing;
781}
782
783bool pcm_is_paused(void)
784{
785 return pcm_paused;
786}
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 2785d4b1b1..25f1f1ef64 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -16,199 +16,238 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19 19#include "system.h"
20#include "config.h" 20#include "kernel.h"
21#include "debug.h" 21#include "logf.h"
22#include "panic.h" 22#include "panic.h"
23#include "thread.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> 24#include <string.h>
30 25#include "ata.h"
31#include "cpu.h" 26#include "usb.h"
32#include "i2c.h" 27#if defined(HAVE_UDA1380)
33#include "power.h"
34#ifdef HAVE_UDA1380
35#include "uda1380.h" 28#include "uda1380.h"
36#endif 29#include "general.h"
37#ifdef HAVE_TLV320 30#elif defined(HAVE_TLV320)
38#include "tlv320.h" 31#include "tlv320.h"
39#endif 32#endif
40#include "system.h"
41#include "usb.h"
42
43#include "buffer.h" 33#include "buffer.h"
44#include "audio.h" 34#include "audio.h"
45#include "button.h"
46#include "file.h"
47#include "sprintf.h"
48#include "logf.h"
49#include "button.h"
50#include "lcd.h"
51#include "lcd-remote.h"
52#include "pcm_playback.h"
53#include "sound.h" 35#include "sound.h"
54#include "id3.h" 36#include "id3.h"
55#include "pcm_record.h"
56
57extern int boost_counter; /* used for boost check */
58 37
59/***************************************************************************/ 38/***************************************************************************/
60 39
40/**
41 * APIs implemented in the target tree portion:
42 * Public -
43 * pcm_init_recording
44 * pcm_close_recording
45 * pcm_rec_mux
46 * Semi-private -
47 * pcm_rec_dma_start
48 * pcm_rec_dma_stop
49 */
50
51/** These items may be implemented target specifically or need to
52 be shared semi-privately **/
53
54/* the registered callback function for when more data is available */
55pcm_more_callback_type pcm_callback_more_ready = NULL;
56/* DMA transfer in is currently active */
57bool pcm_recording = false;
58
59/* APIs implemented in the target-specific portion */
60void pcm_rec_dma_start(const void *addr, size_t size);
61void pcm_rec_dma_stop(void);
62
63/** General recording state **/
61static bool is_recording; /* We are recording */ 64static bool is_recording; /* We are recording */
62static bool is_paused; /* We have paused */ 65static bool is_paused; /* We have paused */
66static bool is_stopping; /* We are currently stopping */
63static bool is_error; /* An error has occured */ 67static bool is_error; /* An error has occured */
64 68
65static unsigned long num_rec_bytes; /* Num bytes recorded */ 69/** Stats on encoded data for current file **/
66static unsigned long num_file_bytes; /* Num bytes written to current file */ 70static size_t num_rec_bytes; /* Num bytes recorded */
67static int error_count; /* Number of DMA errors */ 71static unsigned long num_rec_samples; /* Number of PCM samples recorded */
68static unsigned long num_pcm_samples; /* Num pcm samples written to current file */
69
70static long record_start_time; /* current_tick when recording was started */
71static long pause_start_time; /* current_tick when pause was started */
72static unsigned int sample_rate; /* Sample rate at time of recording start */
73static int rec_source; /* Current recording source */
74 72
75static int wav_file; 73/** Stats on encoded data for all files from start to stop **/
76static char recording_filename[MAX_PATH]; 74static unsigned long long accum_rec_bytes; /* total size written to chunks */
75static unsigned long long accum_pcm_samples; /* total pcm count processed */
77 76
78static volatile bool init_done, close_done, record_done; 77/* Keeps data about current file and is sent as event data for codec */
79static volatile bool stop_done, pause_done, resume_done, new_file_done; 78static struct enc_file_event_data rec_fdata IDATA_ATTR =
80 79{
81static int peak_left, peak_right; 80 .chunk = NULL,
81 .new_enc_size = 0,
82 .new_num_pcm = 0,
83 .rec_file = -1,
84 .num_pcm_samples = 0
85};
82 86
83#ifdef IAUDIO_X5 87/** These apply to current settings **/
84#define SET_IIS_PLAY(x) IIS1CONFIG = (x); 88static int rec_source; /* current rec_source setting */
85#define SET_IIS_REC(x) IIS1CONFIG = (x); 89static int rec_frequency; /* current frequency setting */
86#else 90static unsigned long sample_rate; /* Sample rate in HZ */
87#define SET_IIS_PLAY(x) IIS2CONFIG = (x); 91static int num_channels; /* Current number of channels */
88#define SET_IIS_REC(x) IIS1CONFIG = (x); 92static struct encoder_config enc_config; /* Current encoder configuration */
89#endif
90 93
91/**************************************************************************** 94/****************************************************************************
92 use 2 circular buffers of same size: 95 use 2 circular buffers:
93 rec_buffer=DMA output buffer: chunks (8192 Bytes) of raw pcm audio data 96 pcm_buffer=DMA output buffer: chunks (8192 Bytes) of raw pcm audio data
94 enc_buffer=encoded audio buffer: storage for encoder output data 97 enc_buffer=encoded audio buffer: storage for encoder output data
95 98
96 Flow: 99 Flow:
97 1. when entering recording_screen DMA feeds the ringbuffer rec_buffer 100 1. when entering recording_screen DMA feeds the ringbuffer pcm_buffer
98 2. if enough pcm data are available the encoder codec does encoding of pcm 101 2. if enough pcm data are available the encoder codec does encoding of pcm
99 chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread 102 chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread
100 3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk 103 3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk
101 104
102 Functions calls: 105 Functions calls (basic encoder steps):
103 1.main: codec_load_encoder(); start the encoder 106 1.main: audio_load_encoder(); start the encoder
104 2.encoder: enc_get_inputs(); get encoder buffsize, mono/stereo, quality 107 2.encoder: enc_get_inputs(); get encoder recording settings
105 3.encoder: enc_set_parameters(); set the encoder parameters (max.chunksize) 108 3.encoder: enc_set_parameters(); set the encoder parameters
106 4.encoder: enc_get_wav_data(); get n bytes of unprocessed pcm data 109 4.encoder: enc_get_pcm_data(); get n bytes of unprocessed pcm data
107 5.encoder: enc_wavbuf_near_empty();if true: reduce cpu_boost 110 5.encoder: enc_pcm_buf_near_empty(); if 1: reduce cpu_boost
108 6.encoder: enc_alloc_chunk(); get a ptr to next enc chunk 111 6.encoder: enc_alloc_chunk(); get a ptr to next enc chunk
109 7.encoder: <process enc chunk> compress and store data to enc chunk 112 7.encoder: <process enc chunk> compress and store data to enc chunk
110 8.encoder: enc_free_chunk(); inform main about chunk process finished 113 8.encoder: enc_free_chunk(); inform main about chunk process finished
111 9.encoder: repeat 4. to 8. 114 9.encoder: repeat 4. to 8.
112 A.main: enc_set_header_callback(); create the current format header (file) 115 A.pcmrec: enc_events_callback(); called for certain events
113****************************************************************************/ 116****************************************************************************/
114#define NUM_CHUNKS 256 /* Power of 2 */ 117
115#define CHUNK_SIZE 8192 /* Power of 2 */ 118/** buffer parameters where incoming PCM data is placed **/
116#define MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */ 119#define PCM_NUM_CHUNKS 256 /* Power of 2 */
117#define CHUNK_MASK (NUM_CHUNKS * CHUNK_SIZE - 1) 120#define PCM_CHUNK_SIZE 8192 /* Power of 2 */
118#define WRITE_THRESHOLD (44100 * 5 / enc_samp_per_chunk) /* 5sec */ 121#define PCM_CHUNK_MASK (PCM_NUM_CHUNKS*PCM_CHUNK_SIZE - 1)
119#define GET_CHUNK(x) (long*)(&rec_buffer[x]) 122
120#define GET_ENC_CHUNK(x) (long*)(&enc_buffer[enc_chunk_size*(x)]) 123#define GET_PCM_CHUNK(offset) ((long *)(pcm_buffer + (offset)))
121 124#define GET_ENC_CHUNK(index) ENC_CHUNK_HDR(enc_buffer + enc_chunk_size*(index))
122static int audio_enc_id; /* current encoder id */ 125
123static unsigned char *rec_buffer; /* Circular recording buffer */ 126#define INC_ENC_INDEX(index) \
124static unsigned char *enc_buffer; /* Circular encoding buffer */ 127 { if (++index >= enc_num_chunks) index = 0; }
125static unsigned char *enc_head_buffer; /* encoder header buffer */ 128#define DEC_ENC_INDEX(index) \
126static int enc_head_size; /* used size in header buffer */ 129 { if (--index < 0) index = enc_num_chunks - 1; }
127static int write_pos; /* Current chunk pos for DMA writing */ 130
128static int read_pos; /* Current chunk pos for encoding */ 131static size_t rec_buffer_size; /* size of available buffer */
129static long pre_record_ticks;/* pre-record time expressed in ticks */ 132static unsigned char *pcm_buffer; /* circular recording buffer */
130static int enc_wr_index; /* Current encoding chunk write index */ 133static unsigned char *enc_buffer; /* circular encoding buffer */
131static int enc_rd_index; /* Current encoding chunk read index */ 134static volatile int dma_wr_pos; /* current DMA write pos */
132static int enc_chunk_size; /* maximum encoder chunk size */ 135static int pcm_rd_pos; /* current PCM read pos */
136static volatile bool dma_lock; /* lock DMA write position */
137static unsigned long pre_record_ticks;/* pre-record time in ticks */
138static int enc_wr_index; /* encoder chunk write index */
139static int enc_rd_index; /* encoder chunk read index */
133static int enc_num_chunks; /* number of chunks in ringbuffer */ 140static int enc_num_chunks; /* number of chunks in ringbuffer */
134static int enc_buffer_size; /* encode buffer size */ 141static size_t enc_chunk_size; /* maximum encoder chunk size */
135static int enc_channels; /* 1=mono 2=stereo */ 142static size_t enc_data_size; /* maximum data size for encoder */
136static int enc_quality; /* mp3: 64,96,128,160,192,320 kBit */ 143static unsigned long enc_sample_rate; /* sample rate used by encoder */
137static int enc_samp_per_chunk;/* pcm samples per encoder chunk */
138static bool wav_queue_empty; /* all wav chunks processed? */ 144static bool wav_queue_empty; /* all wav chunks processed? */
139static unsigned long avrg_bit_rate; /* average bit rates from chunks */
140static unsigned long curr_bit_rate; /* cumulated bit rates from chunks */
141static unsigned long curr_chunk_cnt; /* number of processed chunks */
142 145
143void (*enc_set_header_callback)(void *head_buffer, int head_size, 146/** file flushing **/
144 int num_pcm_samples, bool is_file_header); 147static int write_threshold; /* max chunk limit for data flush */
148static int panic_threshold; /* boost thread prio when here */
149static int spinup_time = -1;/* last ata_spinup_time */
150
151/** encoder events **/
152static void (*enc_events_callback)(enum enc_events event, void *data);
153
154/** Path queue for files to write **/
155#define FNQ_MIN_NUM_PATHS 16 /* minimum number of paths to hold */
156static unsigned char *fn_queue; /* pointer to first filename */
157static ssize_t fnq_size; /* capacity of queue in bytes */
158static int fnq_rd_pos; /* current read position */
159static int fnq_wr_pos; /* current write position */
145 160
146/***************************************************************************/ 161/***************************************************************************/
147 162
148static struct event_queue pcmrec_queue; 163static struct event_queue pcmrec_queue;
149static long pcmrec_stack[2*DEFAULT_STACK_SIZE/sizeof(long)]; 164static long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)];
150static const char pcmrec_thread_name[] = "pcmrec"; 165static const char pcmrec_thread_name[] = "pcmrec";
151 166
152static void pcmrec_thread(void); 167static void pcmrec_thread(void);
153static void pcmrec_dma_start(void);
154static void pcmrec_dma_stop(void);
155static void close_wave(void);
156 168
157/* Event IDs */ 169/* Event values which are also single-bit flags */
158#define PCMREC_INIT 1 /* Enable recording */ 170#define PCMREC_INIT 0x00000001 /* enable recording */
159#define PCMREC_CLOSE 2 171#define PCMREC_CLOSE 0x00000002
160 172
161#define PCMREC_START 3 /* Start a new recording */ 173#define PCMREC_START 0x00000004 /* start recording (when stopped) */
162#define PCMREC_STOP 4 /* Stop the current recording */ 174#define PCMREC_STOP 0x00000008 /* stop the current recording */
163#define PCMREC_PAUSE 10 175#define PCMREC_PAUSE 0x00000010 /* pause the current recording */
164#define PCMREC_RESUME 11 176#define PCMREC_RESUME 0x00000020 /* resume the current recording */
165#define PCMREC_NEW_FILE 12 177#define PCMREC_NEW_FILE 0x00000040 /* start new file (when recording) */
166#define PCMREC_SET_GAIN 13 178#define PCMREC_SET_GAIN 0x00000080
179#define PCMREC_FLUSH_NUM 0x00000100 /* flush a number of files out */
180#define PCMREC_FINISH_STOP 0x00000200 /* finish the stopping recording */
167 181
168/*******************************************************************/ 182/* mask for signaling events */
169/* Functions that are not executing in the pcmrec_thread first */ 183static volatile long pcm_thread_event_mask;
170/*******************************************************************/
171 184
172/* Creates pcmrec_thread */ 185static void pcm_thread_sync_post(long event, void *data)
173void pcm_rec_init(void)
174{ 186{
175 queue_init(&pcmrec_queue, true); 187 pcm_thread_event_mask &= ~event;
176 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), 188 queue_post(&pcmrec_queue, event, data);
177 pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING)); 189 while(!(event & pcm_thread_event_mask))
178} 190 yield();
191} /* pcm_thread_sync_post */
179 192
193static inline void pcm_thread_signal_event(long event)
194{
195 pcm_thread_event_mask |= event;
196} /* pcm_thread_signal_event */
180 197
181int audio_get_encoder_id(void) 198static inline void pcm_thread_unsignal_event(long event)
182{ 199{
183 return audio_enc_id; 200 pcm_thread_event_mask &= ~event;
184} 201} /* pcm_thread_unsignal_event */
185 202
186/* Initializes recording: 203static inline bool pcm_thread_event_state(long signaled, long unsignaled)
187 * - Set up the UDA1380/TLV320 for recording 204{
188 * - Prepare for DMA transfers 205 return ((signaled | unsignaled) & pcm_thread_event_mask) == signaled;
189 */ 206} /* pcm_thread_event_state */
190 207
191void audio_init_recording(unsigned int buffer_offset) 208static void pcm_thread_wait_for_stop(void)
192{ 209{
193 (void)buffer_offset; 210 if (is_stopping)
211 {
212 logf("waiting for stop to finish");
213 while (is_stopping)
214 yield();
215 }
216} /* pcm_thread_wait_for_stop */
194 217
195 init_done = false; 218/*******************************************************************/
196 queue_post(&pcmrec_queue, PCMREC_INIT, 0); 219/* Functions that are not executing in the pcmrec_thread first */
220/*******************************************************************/
197 221
198 while(!init_done) 222/* Callback for when more data is ready */
199 sleep_thread(1); 223static void pcm_rec_have_more(unsigned char **data, size_t *size)
200}
201
202void audio_close_recording(void)
203{ 224{
204 close_done = false; 225 if (*size != 0)
205 queue_post(&pcmrec_queue, PCMREC_CLOSE, 0); 226 {
227 /* some error condition */
228 if (*size == DMA_REC_ERROR_DMA)
229 {
230 /* Flush recorded data to disk and stop recording */
231 queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
232 return;
233 }
234 /* else try again next transmission */
235 }
236 else if (!dma_lock)
237 {
238 /* advance write position */
239 dma_wr_pos = (dma_wr_pos + PCM_CHUNK_SIZE) & PCM_CHUNK_MASK;
240 }
206 241
207 while(!close_done) 242 *data = (unsigned char *)GET_PCM_CHUNK(dma_wr_pos);
208 sleep_thread(1); 243 *size = PCM_CHUNK_SIZE;
244} /* pcm_rec_have_more */
209 245
210 audio_remove_encoder(); 246/** pcm_rec_* group **/
211} 247void pcm_rec_error_clear(void)
248{
249 is_error = false;
250} /* pcm_rec_error_clear */
212 251
213unsigned long pcm_rec_status(void) 252unsigned long pcm_rec_status(void)
214{ 253{
@@ -216,165 +255,223 @@ unsigned long pcm_rec_status(void)
216 255
217 if (is_recording) 256 if (is_recording)
218 ret |= AUDIO_STATUS_RECORD; 257 ret |= AUDIO_STATUS_RECORD;
258
219 if (is_paused) 259 if (is_paused)
220 ret |= AUDIO_STATUS_PAUSE; 260 ret |= AUDIO_STATUS_PAUSE;
261
221 if (is_error) 262 if (is_error)
222 ret |= AUDIO_STATUS_ERROR; 263 ret |= AUDIO_STATUS_ERROR;
223 if (!is_recording && pre_record_ticks && init_done && !close_done) 264
265 if (!is_recording && pre_record_ticks &&
266 pcm_thread_event_state(PCMREC_INIT, PCMREC_CLOSE))
224 ret |= AUDIO_STATUS_PRERECORD; 267 ret |= AUDIO_STATUS_PRERECORD;
225 268
226 return ret; 269 return ret;
227} 270} /* pcm_rec_status */
228 271
229int pcm_rec_current_bitrate(void) 272int pcm_rec_current_bitrate(void)
230{ 273{
231 return avrg_bit_rate; 274 if (accum_pcm_samples == 0)
232} 275 return 0;
233 276
234unsigned long audio_recorded_time(void) 277 return (int)(8*accum_rec_bytes*enc_sample_rate / (1000*accum_pcm_samples));
278} /* pcm_rec_current_bitrate */
279
280int pcm_rec_encoder_afmt(void)
235{ 281{
236 if (is_recording) 282 return enc_config.afmt;
283} /* pcm_rec_encoder_afmt */
284
285int pcm_rec_rec_format(void)
237 { 286 {
238 if (is_paused) 287 return afmt_rec_format[enc_config.afmt];
239 return pause_start_time - record_start_time; 288} /* pcm_rec_rec_format */
240 else
241 return current_tick - record_start_time;
242 }
243 289
244 return 0; 290unsigned long pcm_rec_sample_rate(void)
245} 291{
292 /* Which is better ?? */
293#if 0
294 return enc_sample_rate;
295#endif
296 return sample_rate;
297} /* audio_get_sample_rate */
246 298
247unsigned long audio_num_recorded_bytes(void) 299/**
300 * Creates pcmrec_thread
301 */
302void pcm_rec_init(void)
248{ 303{
249 if (is_recording) 304 queue_init(&pcmrec_queue, true);
250 return num_rec_bytes; 305 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
306 pcmrec_thread_name, PRIORITY_RECORDING);
307} /* pcm_rec_init */
251 308
309/** audio_* group **/
310
311void audio_init_recording(unsigned int buffer_offset)
312{
313 (void)buffer_offset;
314 pcm_thread_wait_for_stop();
315 pcm_thread_sync_post(PCMREC_INIT, NULL);
316} /* audio_init_recording */
317
318void audio_close_recording(void)
319{
320 pcm_thread_wait_for_stop();
321 pcm_thread_sync_post(PCMREC_CLOSE, NULL);
322 /* reset pcm to defaults (playback only) */
323 pcm_set_frequency(-1);
324 pcm_set_monitor(-1);
325 pcm_set_rec_source(-1);
326#ifdef HAVE_TLV320
327 /* tlv320 screeches if left at 88.2 with no inputs */
328 pcm_apply_settings(true);
329#endif
330 audio_remove_encoder();
331} /* audio_close_recording */
332
333unsigned long audio_recorded_time(void)
334{
335 if (!is_recording || enc_sample_rate == 0)
252 return 0; 336 return 0;
253}
254 337
255#ifdef HAVE_SPDIF_IN 338 /* return actual recorded time a la encoded data even if encoder rate
256/* Only the last six of these are standard rates, but all sample rates are 339 doesn't match the pcm rate */
257 * possible, so we support some other common ones as well. 340 return (long)(HZ*(unsigned long long)num_rec_samples / enc_sample_rate);
258 */ 341} /* audio_recorded_time */
259static unsigned long spdif_sample_rates[] = {
260 8000, 11025, 12000, 16000, 22050, 24000,
261 32000, 44100, 48000, 64000, 88200, 96000
262};
263 342
264/* Return SPDIF sample rate. Since we base our reading on the actual SPDIF 343unsigned long audio_num_recorded_bytes(void)
265 * sample rate (which might be a bit inaccurate), we round off to the closest
266 * sample rate that is supported by SPDIF.
267 */
268unsigned long audio_get_spdif_sample_rate(void)
269{ 344{
270 int i = 0; 345 if (!is_recording)
271 unsigned long measured_rate; 346 return 0;
272 const int upper_bound = sizeof(spdif_sample_rates)/sizeof(long) - 1; 347
348 return num_rec_bytes;
349} /* audio_num_recorded_bytes */
273 350
351#ifdef HAVE_SPDIF_IN
352/* Return current SPDIF sample rate */
353static unsigned long measure_spdif_sample_rate(void)
354{
274 /* The following formula is specified in MCF5249 user's manual section 355 /* The following formula is specified in MCF5249 user's manual section
275 * 17.6.1. The 3*(1 << 13) part will need changing if the setup of the 356 * 17.6.1. The 128 divide is because of the fact that the SPDIF clock is
276 * PHASECONFIG register is ever changed. The 128 divide is because of the 357 * the sample rate times 128. Keep "3*(1 << 13)" part in sync with
277 * fact that the SPDIF clock is the sample rate times 128. 358 * PHASECONFIG setup in pcm_init_recording in pcm-coldfire.c.
278 */ 359 */
279 measured_rate = (unsigned long)((unsigned long long)FREQMEAS*CPU_FREQ/ 360 return (unsigned long)((unsigned long long)FREQMEAS*CPU_FREQ /
280 ((1 << 15)*3*(1 << 13))/128); 361 ((1 << 15)*3*(1 << 13))/128);
281 /* Find which SPDIF sample rate we're closest to. */ 362} /* measure_spdif_sample_rate */
282 while (spdif_sample_rates[i] < measured_rate && i < upper_bound) ++i;
283 if (i > 0 && i < upper_bound)
284 {
285 long diff1 = measured_rate - spdif_sample_rates[i - 1];
286 long diff2 = spdif_sample_rates[i] - measured_rate;
287 363
288 if (diff2 > diff1) --i; 364/**
289 } 365 * Return SPDIF sample rate index in audio_master_sampr_list. Since we base
290 return i; 366 * our reading on the actual SPDIF sample rate (which might be a bit
291} 367 * inaccurate), we round off to the closest sample rate that is supported by
292#endif 368 * SPDIF.
369 */
370int audio_get_spdif_sample_rate(void)
371{
372 unsigned long measured_rate = measure_spdif_sample_rate();
373 /* Find which SPDIF sample rate we're closest to. */
374 return round_value_to_list32(measured_rate, audio_master_sampr_list,
375 SAMPR_NUM_FREQ, false);
376} /* audio_get_spdif_sample_rate */
293 377
294#if 0
295/* not needed atm */
296#ifdef HAVE_SPDIF_POWER 378#ifdef HAVE_SPDIF_POWER
297static bool spdif_power_setting; 379static bool spdif_power_setting;
298 380
299void audio_set_spdif_power_setting(bool on) 381void audio_set_spdif_power_setting(bool on)
300{ 382{
301 spdif_power_setting = on; 383 spdif_power_setting = on;
302} 384} /* audio_set_spdif_power_setting */
385
386bool audio_get_spdif_power_setting(void)
387{
388 return spdif_power_setting;
389} /* audio_get_spdif_power_setting */
303#endif 390#endif
391
392void audio_spdif_set_monitor(int monitor_spdif)
393{
394 EBU1CONFIG = 0x800; /* Reset before reprogram */
395
396 if (monitor_spdif > 0)
397 {
398#ifdef HAVE_SPDIF_POWER
399 EBU1CONFIG = spdif_power_setting ? (1 << 2) : 0;
400 /* Input source is EBUin1, Feed-through monitoring if desired */
401#else
402 EBU1CONFIG = (1 << 2);
403 /* Input source is EBUin1, Feed-through monitoring */
304#endif 404#endif
405 }
406 else if (monitor_spdif == 0)
407 {
408 /* SCLK2, TXSRC = IIS1recv, validity, normal operation */
409 EBU1CONFIG = (7 << 12) | (4 << 8) | (1 << 5) | (5 << 2);
410 }
411} /* audio_spdif_set_monitor */
412
413#endif /* HAVE_SPDIF_IN */
305 414
306/** 415/**
307 * Sets recording parameters 416 * Sets recording parameters
308 *
309 * This functions starts feeding the CPU with audio data over the I2S bus
310 */ 417 */
311void audio_set_recording_options(int frequency, int quality, 418void audio_set_recording_options(struct audio_recording_options *options)
312 int source, int channel_mode,
313 bool editable, int prerecord_time)
314{ 419{
315 /* TODO: */ 420 pcm_thread_wait_for_stop();
316 (void)editable;
317 421
318 /* NOTE: Coldfire UDA based recording does not yet support anything other 422 /* stop DMA transfer */
319 * than 44.1kHz sampling rate, so we limit it to that case here now. SPDIF 423 dma_lock = true;
320 * based recording will overwrite this value with the proper sample rate in 424 pcm_stop_recording();
321 * audio_record(), and will not be affected by this.
322 */
323 frequency = 44100;
324 enc_quality = quality;
325 rec_source = source;
326 enc_channels = channel_mode == CHN_MODE_MONO ? 1 : 2;
327 pre_record_ticks = prerecord_time * HZ;
328 425
329 switch (source) 426 rec_frequency = options->rec_frequency;
330 { 427 rec_source = options->rec_source;
331 case AUDIO_SRC_MIC: 428 num_channels = options->rec_channels == 1 ? 1 : 2;
332 case AUDIO_SRC_LINEIN: 429 pre_record_ticks = options->rec_prerecord_time * HZ;
333#ifdef HAVE_FMRADIO_IN 430 enc_config = options->enc_config;
334 case AUDIO_SRC_FMRADIO: 431 enc_config.afmt = rec_format_afmt[enc_config.rec_format];
335#endif
336 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
337 DATAINCONTROL = 0xc020;
338 break;
339 432
340#ifdef HAVE_SPDIF_IN 433#ifdef HAVE_SPDIF_IN
341 case AUDIO_SRC_SPDIF: 434 if (rec_source == AUDIO_SRC_SPDIF)
342 /* Int. when 6 samples in FIFO. PDIR2 source = ebu1RcvData */ 435 {
343 DATAINCONTROL = 0xc038; 436 /* must measure SPDIF sample rate before configuring codecs */
344 break; 437 unsigned long sr = measure_spdif_sample_rate();
345#endif /* HAVE_SPDIF_IN */ 438 /* round to master list for SPDIF rate */
439 int index = round_value_to_list32(sr, audio_master_sampr_list,
440 SAMPR_NUM_FREQ, false);
441 sample_rate = audio_master_sampr_list[index];
442 /* round to HW playback rates for monitoring */
443 index = round_value_to_list32(sr, hw_freq_sampr,
444 HW_NUM_FREQ, false);
445 pcm_set_frequency(hw_freq_sampr[index]);
446 /* encoders with a limited number of rates do their own rounding */
447 }
448 else
449#endif
450 {
451 /* set sample rate from frequency selection */
452 sample_rate = rec_freq_sampr[rec_frequency];
453 pcm_set_frequency(sample_rate);
346 } 454 }
347 455
348 sample_rate = frequency; 456 pcm_set_monitor(rec_source);
349 457 pcm_set_rec_source(rec_source);
350 /* Monitoring: route the signals through the coldfire audio interface. */
351 458
352 SET_IIS_PLAY(0x800); /* Reset before reprogram */ 459 /* apply pcm settings to hardware */
460 pcm_apply_settings(true);
353 461
354#ifdef HAVE_SPDIF_IN 462 if (audio_load_encoder(enc_config.afmt))
355 if (source == AUDIO_SRC_SPDIF)
356 { 463 {
357 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */ 464 /* start DMA transfer */
358 IIS2CONFIG = (6 << 12) | (7 << 8) | (4 << 2); 465 pcm_record_data(pcm_rec_have_more, NULL, 0);
359 /* S/PDIF feed-through already configured */ 466 /* do unlock after starting to prevent preincrement of dma_wr_pos */
467 dma_lock = pre_record_ticks == 0;
360 } 468 }
361 else 469 else
362 { 470 {
363 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */ 471 logf("set rec opt: enc load failed");
364 IIS2CONFIG = (8 << 12) | (4 << 8) | (4 << 2); 472 is_error = true;
365
366 EBU1CONFIG = 0x800; /* Reset before reprogram */
367 /* SCLK2, TXSRC = IIS1recv, validity, normal operation */
368 EBU1CONFIG = (7 << 12) | (4 << 8) | (1 << 5) | (5 << 2);
369 }
370#else
371 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */
372 SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) );
373#endif
374
375 audio_load_encoder(rec_quality_info_afmt[quality]);
376} 473}
377 474} /* audio_set_recording_options */
378 475
379/** 476/**
380 * Note that microphone is mono, only left value is used 477 * Note that microphone is mono, only left value is used
@@ -391,8 +488,7 @@ void audio_set_recording_gain(int left, int right, int type)
391#elif defined (HAVE_TLV320) 488#elif defined (HAVE_TLV320)
392 tlv320_set_recvol(left, right, type); 489 tlv320_set_recvol(left, right, type);
393#endif 490#endif
394} 491} /* audio_set_recording_gain */
395
396 492
397/** 493/**
398 * Start recording 494 * Start recording
@@ -401,585 +497,882 @@ void audio_set_recording_gain(int left, int right, int type)
401 */ 497 */
402void audio_record(const char *filename) 498void audio_record(const char *filename)
403{ 499{
500 logf("audio_record: %s", filename);
501
502 pcm_thread_wait_for_stop();
503 pcm_thread_sync_post(PCMREC_START, (void *)filename);
504
505 logf("audio_record_done");
506} /* audio_record */
507
508void audio_new_file(const char *filename)
509{
510 logf("audio_new_file: %s", filename);
511
512 pcm_thread_wait_for_stop();
513 pcm_thread_sync_post(PCMREC_NEW_FILE, (void *)filename);
514
515 logf("audio_new_file done");
516} /* audio_new_file */
517
518void audio_stop_recording(void)
519{
520 logf("audio_stop_recording");
521
522 pcm_thread_wait_for_stop();
523
404 if (is_recording) 524 if (is_recording)
405 { 525 dma_lock = true; /* fix DMA write ptr at current position */
406 logf("record while recording"); 526
407 return; 527 pcm_thread_sync_post(PCMREC_STOP, NULL);
408 } 528
529 logf("audio_stop_recording done");
530} /* audio_stop_recording */
531
532void audio_pause_recording(void)
533{
534 logf("audio_pause_recording");
409 535
410 strncpy(recording_filename, filename, MAX_PATH - 1); 536 pcm_thread_wait_for_stop();
411 recording_filename[MAX_PATH - 1] = 0;
412 537
413#ifdef HAVE_SPDIF_IN 538 if (is_recording)
414 if (rec_source == AUDIO_SRC_SPDIF) 539 dma_lock = true; /* fix DMA write ptr at current position */
415 sample_rate = audio_get_spdif_sample_rate();
416#endif
417 540
418 record_done = false; 541 pcm_thread_sync_post(PCMREC_PAUSE, NULL);
419 queue_post(&pcmrec_queue, PCMREC_START, 0); 542 logf("audio_pause_recording done");
543} /* audio_pause_recording */
420 544
421 while(!record_done) 545void audio_resume_recording(void)
422 sleep_thread(1); 546{
423} 547 logf("audio_resume_recording");
424 548
549 pcm_thread_wait_for_stop();
550 pcm_thread_sync_post(PCMREC_RESUME, NULL);
425 551
426void audio_new_file(const char *filename) 552 logf("audio_resume_recording done");
553} /* audio_resume_recording */
554
555/***************************************************************************/
556/* */
557/* Functions that execute in the context of pcmrec_thread */
558/* */
559/***************************************************************************/
560
561/** Filename Queue **/
562
563/* returns true if the queue is empty */
564static inline bool pcmrec_fnq_is_empty(void)
427{ 565{
428 logf("pcm_new_file"); 566 return fnq_rd_pos == fnq_wr_pos;
567} /* pcmrec_fnq_is_empty */
568
569/* empties the filename queue */
570static inline void pcmrec_fnq_set_empty(void)
571{
572 fnq_rd_pos = fnq_wr_pos;
573} /* pcmrec_fnq_set_empty */
429 574
430 new_file_done = false; 575/* returns true if the queue is full */
576static bool pcmrec_fnq_is_full(void)
577{
578 ssize_t size = fnq_wr_pos - fnq_rd_pos;
579 if (size < 0)
580 size += fnq_size;
431 581
432 strncpy(recording_filename, filename, MAX_PATH - 1); 582 return size >= fnq_size - MAX_PATH;
433 recording_filename[MAX_PATH - 1] = 0; 583} /* pcmrec_fnq_is_full */
434 584
435 queue_post(&pcmrec_queue, PCMREC_NEW_FILE, 0); 585/* queue another filename - will overwrite oldest one if full */
586static bool pcmrec_fnq_add_filename(const char *filename)
587{
588 strncpy(fn_queue + fnq_wr_pos, filename, MAX_PATH);
436 589
437 while(!new_file_done) 590 if ((fnq_wr_pos += MAX_PATH) >= fnq_size)
438 sleep_thread(1); 591 fnq_wr_pos = 0;
439 592
440 logf("pcm_new_file done"); 593 if (fnq_rd_pos != fnq_wr_pos)
441} 594 return true;
442 595
443/** 596 /* queue full */
444 * 597 if ((fnq_rd_pos += MAX_PATH) >= fnq_size)
445 */ 598 fnq_rd_pos = 0;
446void audio_stop_recording(void) 599
600 return true;
601} /* pcmrec_fnq_add_filename */
602
603/* replace the last filename added */
604static bool pcmrec_fnq_replace_tail(const char *filename)
447{ 605{
448 if (!is_recording) 606 int pos;
449 return; 607
608 if (pcmrec_fnq_is_empty())
609 return false;
610
611 pos = fnq_wr_pos - MAX_PATH;
612 if (pos < 0)
613 pos = fnq_size - MAX_PATH;
614
615 strncpy(fn_queue + pos, filename, MAX_PATH);
616
617 return true;
618} /* pcmrec_fnq_replace_tail */
450 619
451 logf("pcm_stop"); 620/* pulls the next filename from the queue */
621static bool pcmrec_fnq_get_filename(char *filename)
622{
623 if (pcmrec_fnq_is_empty())
624 return false;
625
626 if (filename)
627 strncpy(filename, fn_queue + fnq_rd_pos, MAX_PATH);
452 628
453 is_paused = true; /* fix pcm write ptr at current position */ 629 if ((fnq_rd_pos += MAX_PATH) >= fnq_size)
454 stop_done = false; 630 fnq_rd_pos = 0;
455 queue_post(&pcmrec_queue, PCMREC_STOP, 0);
456 631
457 while(!stop_done) 632 return true;
458 sleep_thread(1); 633} /* pcmrec_fnq_get_filename */
459 634
460 logf("pcm_stop done"); 635/* close the file number pointed to by fd_p */
461} 636static void pcmrec_close_file(int *fd_p)
637{
638 if (*fd_p < 0)
639 return; /* preserve error */
462 640
463void audio_pause_recording(void) 641 close(*fd_p);
642 *fd_p = -1;
643} /* pcmrec_close_file */
644
645/** Data Flushing **/
646
647/**
648 * called after callback to update sizes if codec changed the amount of data
649 * a chunk represents
650 */
651static inline void pcmrec_update_sizes_inl(size_t prev_enc_size,
652 unsigned long prev_num_pcm)
464{ 653{
465 if (!is_recording) 654 if (rec_fdata.new_enc_size != prev_enc_size)
466 { 655 {
467 logf("pause when not recording"); 656 ssize_t size_diff = rec_fdata.new_enc_size - prev_enc_size;
468 return; 657 num_rec_bytes += size_diff;
658 accum_rec_bytes += size_diff;
469 } 659 }
470 if (is_paused) 660
661 if (rec_fdata.new_num_pcm != prev_num_pcm)
471 { 662 {
472 logf("pause when paused"); 663 unsigned long pcm_diff = rec_fdata.new_num_pcm - prev_num_pcm;
473 return; 664 num_rec_samples += pcm_diff;
665 accum_pcm_samples += pcm_diff;
474 } 666 }
475 667} /* pcmrec_update_sizes_inl */
476 pause_done = false;
477 queue_post(&pcmrec_queue, PCMREC_PAUSE, 0);
478 668
479 while(!pause_done) 669/* don't need to inline every instance */
480 sleep_thread(1); 670static void pcmrec_update_sizes(size_t prev_enc_size,
481} 671 unsigned long prev_num_pcm)
672{
673 pcmrec_update_sizes_inl(prev_enc_size, prev_num_pcm);
674} /* pcmrec_update_sizes */
482 675
483void audio_resume_recording(void) 676static void pcmrec_start_file(void)
484{ 677{
485 if (!is_paused) 678 size_t enc_size = rec_fdata.new_enc_size;
679 unsigned long num_pcm = rec_fdata.new_num_pcm;
680 int curr_rec_file = rec_fdata.rec_file;
681 char filename[MAX_PATH];
682
683 /* must always pull the filename that matches with this queue */
684 if (!pcmrec_fnq_get_filename(filename))
486 { 685 {
487 logf("resume when not paused"); 686 logf("start file: fnq empty");
488 return; 687 *filename = '\0';
688 is_error = true;
689 }
690 else if (is_error)
691 {
692 logf("start file: is_error already");
693 }
694 else if (curr_rec_file >= 0)
695 {
696 /* Any previous file should have been closed */
697 logf("start file: file already open");
698 is_error = true;
489 } 699 }
490 700
491 resume_done = false; 701 if (is_error)
492 queue_post(&pcmrec_queue, PCMREC_RESUME, 0); 702 rec_fdata.chunk->flags |= CHUNKF_ERROR;
493 703
494 while(!resume_done) 704 /* encoder can set error flag here and should increase
495 sleep_thread(1); 705 enc_new_size and pcm_new_size to reflect additional
496} 706 data written if any */
707 rec_fdata.filename = filename;
708 enc_events_callback(ENC_START_FILE, &rec_fdata);
709
710 if (!is_error && (rec_fdata.chunk->flags & CHUNKF_ERROR))
711 {
712 logf("start file: enc error");
713 is_error = true;
714 }
497 715
498/* return peaks as int, so convert from short first 716 if (is_error)
499 note that peak values are always positive */ 717 {
500void pcm_rec_get_peaks(int *left, int *right) 718 pcmrec_close_file(&curr_rec_file);
719 /* Write no more to this file */
720 rec_fdata.chunk->flags |= CHUNKF_END_FILE;
721 }
722 else
723 {
724 pcmrec_update_sizes(enc_size, num_pcm);
725 }
726
727 rec_fdata.chunk->flags &= ~CHUNKF_START_FILE;
728} /* pcmrec_start_file */
729
730static inline void pcmrec_write_chunk(void)
501{ 731{
502 if (left) 732 size_t enc_size = rec_fdata.new_enc_size;
503 *left = peak_left; 733 unsigned long num_pcm = rec_fdata.new_num_pcm;
504 if (right)
505 *right = peak_right;
506 peak_left = 0;
507 peak_right = 0;
508}
509 734
510/***************************************************************************/ 735 if (is_error)
511/* Functions that executes in the context of pcmrec_thread */ 736 rec_fdata.chunk->flags |= CHUNKF_ERROR;
512/***************************************************************************/ 737
738 enc_events_callback(ENC_WRITE_CHUNK, &rec_fdata);
739
740 if ((long)rec_fdata.chunk->flags >= 0)
741 {
742 pcmrec_update_sizes_inl(enc_size, num_pcm);
743 }
744 else if (!is_error)
745 {
746 logf("wr chk enc error %d %d",
747 rec_fdata.chunk->enc_size, rec_fdata.chunk->num_pcm);
748 is_error = true;
749 }
750} /* pcmrec_write_chunk */
751
752static void pcmrec_end_file(void)
753{
754 /* all data in output buffer for current file will have been
755 written and encoder can now do any nescessary steps to
756 finalize the written file */
757 size_t enc_size = rec_fdata.new_enc_size;
758 unsigned long num_pcm = rec_fdata.new_num_pcm;
759
760 enc_events_callback(ENC_END_FILE, &rec_fdata);
761
762 if (!is_error)
763 {
764 if (rec_fdata.chunk->flags & CHUNKF_ERROR)
765 {
766 logf("end file: enc error");
767 is_error = true;
768 }
769 else
770 {
771 pcmrec_update_sizes(enc_size, num_pcm);
772 }
773 }
774
775 /* Force file close if error */
776 if (is_error)
777 pcmrec_close_file(&rec_fdata.rec_file);
778
779 rec_fdata.chunk->flags &= ~CHUNKF_END_FILE;
780} /* pcmrec_end_file */
513 781
514/** 782/**
515 * Process the chunks 783 * Process the chunks
516 * 784 *
517 * This function is called when queue_get_w_tmo times out. 785 * This function is called when queue_get_w_tmo times out.
518 * 786 *
519 * Other functions can also call this function with flush = true when 787 * Set flush_num to the number of files to flush to disk.
520 * they want to save everything in the buffers to disk. 788 * flush_num = -1 to flush all available chunks to disk.
789 * flush_num = 0 normal write thresholding
790 * flush_num = 1 or greater - all available chunks of current file plus
791 * flush_num file starts if first chunk has been processed.
521 * 792 *
522 */ 793 */
523static void pcmrec_callback(bool flush) 794static void pcmrec_flush(unsigned flush_num)
524{ 795{
525 int i, num_ready, size_yield; 796 static unsigned long last_flush_tick = 0;
526 long *enc_chunk, chunk_size; 797 unsigned long start_tick;
527 798 int num_ready, num;
528 if (!is_recording && !flush) 799 int prio;
529 return; 800 int i;
530 801
531 num_ready = enc_wr_index - enc_rd_index; 802 num_ready = enc_wr_index - enc_rd_index;
532 if (num_ready < 0) 803 if (num_ready < 0)
533 num_ready += enc_num_chunks; 804 num_ready += enc_num_chunks;
534 805
535 /* calculate an estimate of recorded bytes */ 806 num = num_ready;
536 num_rec_bytes = num_file_bytes + num_ready * /* enc_chunk_size */
537 ((avrg_bit_rate * 1000 / 8 * enc_samp_per_chunk + 22050) / 44100);
538 807
539 /* near full state reached: less than 5sec remaining space */ 808 if (flush_num == 0)
540 if (enc_num_chunks - num_ready < WRITE_THRESHOLD || flush)
541 { 809 {
542 logf("writing: %d (%d)", num_ready, flush); 810 if (!is_recording)
543 811 return;
544 cpu_boost_id(true, CPUBOOSTID_PCMRECORD);
545 812
546 size_yield = 0; 813 if (ata_spinup_time != spinup_time)
547 for (i=0; i<num_ready; i++)
548 { 814 {
549 enc_chunk = GET_ENC_CHUNK(enc_rd_index); 815 /* spinup time has changed, calculate new write threshold */
550 chunk_size = *enc_chunk++; 816 logf("new t spinup : %d", ata_spinup_time);
551 817 unsigned long st = spinup_time = ata_spinup_time;
552 /* safety net: if size entry got corrupted => limit */ 818
553 if (chunk_size > (long)(enc_chunk_size - sizeof(long))) 819 /* write at 5s + st remaining in enc_buffer */
554 chunk_size = enc_chunk_size - sizeof(long); 820 if (st < 2*HZ)
821 st = 2*HZ; /* my drive is usually < 250 ticks :) */
822 else if (st > 10*HZ)
823 st = 10*HZ;
824
825 write_threshold = enc_num_chunks -
826 (int)(((5ull*HZ + st)*4ull*sample_rate + (enc_chunk_size-1)) /
827 (enc_chunk_size*HZ));
828
829 if (write_threshold < 0)
830 write_threshold = 0;
831 else if (write_threshold > panic_threshold)
832 write_threshold = panic_threshold;
833
834 logf("new wr thresh: %d", write_threshold);
835 }
555 836
556 if (enc_set_header_callback != NULL) 837 if (num_ready < write_threshold)
557 enc_set_header_callback(enc_chunk, enc_chunk_size, 838 return;
558 num_pcm_samples, false);
559 839
560 if (write(wav_file, enc_chunk, chunk_size) != chunk_size) 840 /* if we're getting called too much and this isn't forced,
561 { 841 boost stat */
562 close_wave(); 842 if (current_tick - last_flush_tick < HZ/2)
563 logf("pcmrec: write err"); 843 num = panic_threshold;
564 is_error = true; 844 }
565 break;
566 }
567 845
568 num_file_bytes += chunk_size; 846 start_tick = current_tick;
569 num_pcm_samples += enc_samp_per_chunk; 847 prio = -1;
570 size_yield += chunk_size;
571 848
572 if (size_yield >= 32768) 849 logf("writing: %d (%d)", num_ready, flush_num);
573 { /* yield when 32kB written */ 850
574 size_yield = 0; 851 cpu_boost_id(true, CPUBOOSTID_PCMRECORD);
575 yield();
576 }
577 852
578 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks; 853 for (i=0; i<num_ready; i++)
854 {
855 if (prio == -1 && (num >= panic_threshold ||
856 current_tick - start_tick > 10*HZ))
857 {
858 /* losing ground - boost priority until finished */
859 logf("pcmrec: boost priority");
860 prio = thread_set_priority(NULL, thread_get_priority(NULL)-1);
579 } 861 }
580 862
581 /* sync file */ 863 rec_fdata.chunk = GET_ENC_CHUNK(enc_rd_index);
582 fsync(wav_file); 864 rec_fdata.new_enc_size = rec_fdata.chunk->enc_size;
865 rec_fdata.new_num_pcm = rec_fdata.chunk->num_pcm;
583 866
584 cpu_boost_id(false, CPUBOOSTID_PCMRECORD); 867 if (rec_fdata.chunk->flags & CHUNKF_START_FILE)
868 {
869 pcmrec_start_file();
870 if (--flush_num == 0)
871 i = num_ready; /* stop on next loop - must write this
872 chunk if it has data */
873 }
585 874
586 logf("done"); 875 pcmrec_write_chunk();
587 }
588}
589 876
590/* Abort dma transfer */ 877 if (rec_fdata.chunk->flags & CHUNKF_END_FILE)
591static void pcmrec_dma_stop(void) 878 pcmrec_end_file();
592{
593 DCR1 = 0;
594 879
595 error_count++; 880 INC_ENC_INDEX(enc_rd_index);
596 881
597 DSR1 = 1; /* Clear interrupt */ 882 if (is_error)
598 IPR |= (1<<15); /* Clear pending interrupt request */ 883 break;
599 884
600 logf("dma1 stopped"); 885 if (prio == -1)
601} 886 {
887 num = enc_wr_index - enc_rd_index;
888 if (num < 0)
889 num += enc_num_chunks;
890 }
602 891
603static void pcmrec_dma_start(void) 892 /* no yielding, the file apis called in the codecs do that */
604{ 893 } /* end for */
605 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
606 SAR1 = (unsigned long)&PDIR2; /* Source address */
607 BCR1 = CHUNK_SIZE; /* Bytes to transfer */
608 894
609 /* Start the DMA transfer.. */ 895 /* sync file */
610#ifdef HAVE_SPDIF_IN 896 if (rec_fdata.rec_file >= 0)
611 INTERRUPTCLEAR = 0x03c00000; 897 fsync(rec_fdata.rec_file);
612#endif 898
899 cpu_boost_id(false, CPUBOOSTID_PCMRECORD);
613 900
614 /* 16Byte transfers prevents from sporadic errors during cpu_boost() */ 901 if (prio != -1)
615 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_DSIZE(3) | DMA_START; 902 {
903 /* return to original priority */
904 logf("pcmrec: unboost priority");
905 thread_set_priority(NULL, prio);
906 }
616 907
617 logf("dma1 started"); 908 last_flush_tick = current_tick; /* save tick when we left */
618} 909 logf("done");
910} /* pcmrec_flush */
619 911
620/* DMA1 Interrupt is called when the DMA has finished transfering a chunk */ 912/**
621void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); 913 * Marks a new stream in the buffer and gives the encoder a chance for special
622void DMA1(void) 914 * handling of transition from one to the next. The encoder may change the
915 * chunk that ends the old stream by requesting more chunks and similiarly for
916 * the new but must always advance the position though the interface. It can
917 * later reject any data it cares to when writing the file but should mark the
918 * chunk so it can recognize this. ENC_WRITE_CHUNK event must be able to accept
919 * a NULL data pointer without error as well.
920 */
921static void pcmrec_new_stream(const char *filename, /* next file name */
922 unsigned long flags, /* CHUNKF_* flags */
923 int pre_index) /* index for prerecorded data */
623{ 924{
624 int res = DSR1; 925 logf("pcmrec_new_stream");
625 926
626 DSR1 = 1; /* Clear interrupt */ 927 struct enc_buffer_event_data data;
928 bool (*fnq_add_fn)(const char *) = NULL;
929 struct enc_chunk_hdr *start = NULL;
627 930
628 if (res & 0x70) 931 int get_chunk_index(struct enc_chunk_hdr *chunk)
629 { 932 {
630 DCR1 = 0; /* Stop DMA transfer */ 933 return ((char *)chunk - (char *)enc_buffer) / enc_chunk_size;
631 error_count++; 934 }
632
633 logf("dma1 err: 0x%x", res);
634
635 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
636 BCR1 = CHUNK_SIZE;
637 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
638 935
639 /* Flush recorded data to disk and stop recording */ 936 struct enc_chunk_hdr * get_prev_chunk(int index)
640 queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
641 }
642#ifdef HAVE_SPDIF_IN
643 else if ((rec_source == AUDIO_SRC_SPDIF) &&
644 (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
645 { 937 {
646 INTERRUPTCLEAR = 0x03c00000; 938 DEC_ENC_INDEX(index);
647 error_count++; 939 return GET_ENC_CHUNK(index);
940 }
648 941
649 logf("spdif err"); 942 data.pre_chunk = NULL;
943 data.chunk = GET_ENC_CHUNK(enc_wr_index);
650 944
651 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */ 945 /* end chunk */
652 BCR1 = CHUNK_SIZE; 946 if (flags & CHUNKF_END_FILE)
653 }
654#endif
655 else
656 { 947 {
657 long peak_l, peak_r; 948 data.chunk->flags &= CHUNKF_START_FILE | CHUNKF_END_FILE;
658 long *ptr, j;
659
660 ptr = GET_CHUNK(write_pos);
661 949
662 if (!is_paused) /* advance write position */ 950 if (data.chunk->flags & CHUNKF_START_FILE)
663 write_pos = (write_pos + CHUNK_SIZE) & CHUNK_MASK; 951 {
952 /* cannot start and end on same unprocessed chunk */
953 logf("file end on start");
954 flags &= ~CHUNKF_END_FILE;
955 }
956 else if (enc_rd_index == enc_wr_index)
957 {
958 /* all data flushed but file not ended - chunk will be left
959 empty */
960 logf("end on dead end");
961 data.chunk->flags = 0;
962 data.chunk->enc_size = 0;
963 data.chunk->num_pcm = 0;
964 data.chunk->enc_data = NULL;
965 INC_ENC_INDEX(enc_wr_index);
966 data.chunk = GET_ENC_CHUNK(enc_wr_index);
967 }
968 else
969 {
970 struct enc_chunk_hdr *last = get_prev_chunk(enc_wr_index);
664 971
665 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */ 972 if (last->flags & CHUNKF_END_FILE)
666 BCR1 = CHUNK_SIZE; 973 {
974 /* end already processed and marked - can't end twice */
975 logf("file end again");
976 flags &= ~CHUNKF_END_FILE;
977 }
978 }
979 }
667 980
668 peak_l = peak_r = 0; 981 /* start chunk */
982 if (flags & CHUNKF_START_FILE)
983 {
984 bool pre = flags & CHUNKF_PRERECORD;
669 985
670 /* only peak every 4th sample */ 986 if (pre)
671 for (j=0; j<CHUNK_SIZE/4; j+=4)
672 { 987 {
673 long value = ptr[j]; 988 logf("stream prerecord start");
674#ifdef ROCKBOX_BIG_ENDIAN 989 start = data.pre_chunk = GET_ENC_CHUNK(pre_index);
675 if (value > peak_l) peak_l = value; 990 start->flags &= CHUNKF_START_FILE | CHUNKF_PRERECORD;
676 else if (-value > peak_l) peak_l = -value; 991 }
677 992 else
678 value <<= 16; 993 {
679 if (value > peak_r) peak_r = value; 994 logf("stream normal start");
680 else if (-value > peak_r) peak_r = -value; 995 start = data.chunk;
681#else 996 start->flags &= CHUNKF_START_FILE;
682 if (value > peak_r) peak_r = value;
683 else if (-value > peak_r) peak_r = -value;
684
685 value <<= 16;
686 if (value > peak_l) peak_l = value;
687 else if (-value > peak_l) peak_l = -value;
688#endif
689 } 997 }
690 998
691 peak_left = (int)(peak_l >> 16); 999 /* if encoder hasn't yet processed the last start - abort the start
692 peak_right = (int)(peak_r >> 16); 1000 of the previous file queued or else it will be empty and invalid */
1001 if (start->flags & CHUNKF_START_FILE)
1002 {
1003 logf("replacing fnq tail: %s", filename);
1004 fnq_add_fn = pcmrec_fnq_replace_tail;
1005 }
1006 else
1007 {
1008 logf("adding filename: %s", filename);
1009 fnq_add_fn = pcmrec_fnq_add_filename;
1010 }
693 } 1011 }
694 1012
695 IPR |= (1<<15); /* Clear pending interrupt request */ 1013 data.flags = flags;
696} 1014 enc_events_callback(ENC_REC_NEW_STREAM, &data);
697
698/* Create WAVE file and write header */
699/* Sets returns 0 if success, -1 on failure */
700static int start_wave(void)
701{
702 wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
703 1015
704 if (wav_file < 0) 1016 if (flags & CHUNKF_END_FILE)
705 { 1017 {
706 wav_file = -1; 1018 int i = get_chunk_index(data.chunk);
707 logf("rec: create failed: %d", wav_file); 1019 get_prev_chunk(i)->flags |= CHUNKF_END_FILE;
708 is_error = true;
709 return -1;
710 } 1020 }
711 1021
712 /* add main file header (enc_head_size=0 for encoders without) */ 1022 if (start)
713 if (enc_head_size != write(wav_file, enc_head_buffer, enc_head_size))
714 { 1023 {
715 close(wav_file); 1024 if (!(flags & CHUNKF_PRERECORD))
716 wav_file = -1; 1025 {
717 logf("rec: write failed"); 1026 /* get stats on data added to start - sort of a prerecord operation */
718 is_error = true; 1027 int i = get_chunk_index(data.chunk);
719 return -1; 1028 struct enc_chunk_hdr *chunk = data.chunk;
720 }
721 1029
722 return 0; 1030 logf("start data: %d %d", i, enc_wr_index);
723}
724 1031
725/* Update header and set correct length values */ 1032 num_rec_bytes = 0;
726static void close_wave(void) 1033 num_rec_samples = 0;
727{
728 unsigned char head[100]; /* assume maximum 100 bytes for file header */
729 int size_read;
730 1034
731 if (wav_file != -1) 1035 while (i != enc_wr_index)
732 { 1036 {
733 /* update header before closing the file (wav+wv encoder will do) */ 1037 num_rec_bytes += chunk->enc_size;
734 if (enc_set_header_callback != NULL) 1038 num_rec_samples += chunk->num_pcm;
735 { 1039 INC_ENC_INDEX(i);
736 lseek(wav_file, 0, SEEK_SET); 1040 chunk = GET_ENC_CHUNK(i);
737 /* try to read the head size (but we'll accept less) */ 1041 }
738 size_read = read(wav_file, head, sizeof(head)); 1042
1043 start->flags &= ~CHUNKF_START_FILE;
1044 start = data.chunk;
1045 }
1046
1047 start->flags |= CHUNKF_START_FILE;
739 1048
740 enc_set_header_callback(head, size_read, num_pcm_samples, true); 1049 /* flush one file out if full and adding */
741 lseek(wav_file, 0, SEEK_SET); 1050 if (fnq_add_fn == pcmrec_fnq_add_filename && pcmrec_fnq_is_full())
742 write(wav_file, head, size_read); 1051 {
1052 logf("fnq full: flushing 1");
1053 pcmrec_flush(1);
743 } 1054 }
744 close(wav_file); 1055
745 wav_file = -1; 1056 fnq_add_fn(filename);
746 } 1057 }
747} 1058} /* pcmrec_new_stream */
748 1059
749static void pcmrec_start(void) 1060/** event handlers for pcmrec thread */
1061
1062/* PCMREC_INIT */
1063static void pcmrec_init(void)
750{ 1064{
751 long max_pre_chunks, pre_ticks, max_pre_ticks; 1065 rec_fdata.rec_file = -1;
1066
1067 /* pcm FIFO */
1068 dma_lock = true;
1069 pcm_rd_pos = 0;
1070 dma_wr_pos = 0;
1071
1072 /* encoder FIFO */
1073 enc_wr_index = 0;
1074 enc_rd_index = 0;
1075
1076 /* filename queue */
1077 fnq_rd_pos = 0;
1078 fnq_wr_pos = 0;
1079
1080 /* stats */
1081 num_rec_bytes = 0;
1082 num_rec_samples = 0;
1083 accum_rec_bytes = 0;
1084 accum_pcm_samples = 0;
1085
1086 pcm_thread_unsignal_event(PCMREC_CLOSE);
1087 is_recording = false;
1088 is_paused = false;
1089 is_stopping = false;
1090 is_error = false;
1091
1092 pcm_buffer = audio_get_recording_buffer(&rec_buffer_size);
1093 /* Line align pcm_buffer 2^4=16 bytes */
1094 pcm_buffer = (unsigned char *)ALIGN_UP_P2((unsigned)pcm_buffer, 4);
1095 enc_buffer = pcm_buffer + ALIGN_UP_P2(PCM_NUM_CHUNKS*PCM_CHUNK_SIZE +
1096 PCM_MAX_FEED_SIZE, 2);
1097
1098 pcm_init_recording();
1099 pcm_thread_signal_event(PCMREC_INIT);
1100} /* pcmrec_init */
1101
1102/* PCMREC_CLOSE */
1103static void pcmrec_close(void)
1104{
1105 dma_lock = true;
1106 pcm_close_recording();
1107 pcm_thread_unsignal_event(PCMREC_INIT);
1108 pcm_thread_signal_event(PCMREC_CLOSE);
1109} /* pcmrec_close */
1110
1111/* PCMREC_START */
1112static void pcmrec_start(const char *filename)
1113{
1114 unsigned long pre_sample_ticks;
1115 int rd_start;
752 1116
753 logf("pcmrec_start"); 1117 logf("pcmrec_start: %s", filename);
754 1118
755 if (is_recording) 1119 if (is_recording)
756 { 1120 {
757 logf("already recording"); 1121 logf("already recording");
758 record_done = true; 1122 goto already_recording;
759 return;
760 } 1123 }
761 1124
762 if (wav_file != -1) 1125 /* reset stats */
763 close_wave(); 1126 num_rec_bytes = 0;
1127 num_rec_samples = 0;
1128 accum_rec_bytes = 0;
1129 accum_pcm_samples = 0;
1130 spinup_time = -1;
1131
1132 rd_start = enc_wr_index;
1133 pre_sample_ticks = 0;
764 1134
765 if (start_wave() != 0) 1135 if (pre_record_ticks)
766 { 1136 {
767 /* failed to create the file */ 1137 int i;
768 record_done = true;
769 return;
770 }
771 1138
772 /* calculate maximum available chunks & resulting ticks */ 1139 /* calculate number of available chunks */
773 max_pre_chunks = (enc_wr_index - enc_rd_index + 1140 unsigned long avail_pre_chunks = (enc_wr_index - enc_rd_index +
774 enc_num_chunks) % enc_num_chunks;
775 if (max_pre_chunks > enc_num_chunks - WRITE_THRESHOLD)
776 max_pre_chunks = enc_num_chunks - WRITE_THRESHOLD;
777 max_pre_ticks = max_pre_chunks * HZ * enc_samp_per_chunk / 44100;
778
779 /* limit prerecord if not enough data available */
780 pre_ticks = pre_record_ticks > max_pre_ticks ?
781 max_pre_ticks : pre_record_ticks;
782 max_pre_chunks = 44100 * pre_ticks / HZ / enc_samp_per_chunk;
783 enc_rd_index = (enc_wr_index - max_pre_chunks +
784 enc_num_chunks) % enc_num_chunks; 1141 enc_num_chunks) % enc_num_chunks;
1142 /* overflow at 974 seconds of prerecording at 44.1kHz */
1143 unsigned long pre_record_sample_ticks = enc_sample_rate*pre_record_ticks;
1144
1145 /* Get exact measure of recorded data as number of samples aren't
1146 nescessarily going to be the max for each chunk */
1147 for (i = rd_start; avail_pre_chunks-- > 0;)
1148 {
1149 struct enc_chunk_hdr *chunk;
1150 unsigned long chunk_sample_ticks;
1151
1152 DEC_ENC_INDEX(i);
1153
1154 chunk = GET_ENC_CHUNK(i);
1155
1156 /* must have data to be counted */
1157 if (chunk->enc_data == NULL)
1158 continue;
785 1159
786 record_start_time = current_tick - pre_ticks; 1160 chunk_sample_ticks = chunk->num_pcm*HZ;
787 1161
788 num_rec_bytes = enc_num_chunks * CHUNK_SIZE; 1162 rd_start = i;
789 num_file_bytes = 0; 1163 pre_sample_ticks += chunk_sample_ticks;
790 num_pcm_samples = 0; 1164 num_rec_bytes += chunk->enc_size;
791 pause_start_time = 0; 1165 num_rec_samples += chunk->num_pcm;
1166
1167 /* stop here if enough already */
1168 if (pre_sample_ticks >= pre_record_sample_ticks)
1169 break;
1170 }
1171
1172 accum_rec_bytes = num_rec_bytes;
1173 accum_pcm_samples = num_rec_samples;
1174 }
1175
1176 enc_rd_index = rd_start;
1177
1178 /* filename queue should be empty */
1179 if (!pcmrec_fnq_is_empty())
1180 {
1181 logf("fnq: not empty!");
1182 pcmrec_fnq_set_empty();
1183 }
792 1184
1185 dma_lock = false;
793 is_paused = false; 1186 is_paused = false;
794 is_recording = true; 1187 is_recording = true;
795 record_done = true;
796}
797 1188
1189 pcmrec_new_stream(filename,
1190 CHUNKF_START_FILE |
1191 (pre_sample_ticks > 0 ? CHUNKF_PRERECORD : 0),
1192 enc_rd_index);
1193
1194already_recording:
1195 pcm_thread_signal_event(PCMREC_START);
1196 logf("pcmrec_start done");
1197} /* pcmrec_start */
1198
1199/* PCMREC_STOP */
798static void pcmrec_stop(void) 1200static void pcmrec_stop(void)
799{ 1201{
800 logf("pcmrec_stop"); 1202 logf("pcmrec_stop");
801 1203
802 if (is_recording) 1204 if (!is_recording)
803 { 1205 {
804 /* wait for encoding finish */ 1206 logf("not recording");
805 is_paused = true; 1207 goto not_recording_or_stopping;
806 while(!wav_queue_empty) 1208 }
807 sleep_thread(1); 1209 else if (is_stopping)
808 1210 {
809 is_recording = false; 1211 logf("already stopping");
810 1212 goto not_recording_or_stopping;
811 /* Flush buffers to file */
812 pcmrec_callback(true);
813 close_wave();
814 } 1213 }
815 1214
816 is_paused = false; 1215 is_stopping = true;
817 stop_done = true; 1216 dma_lock = true; /* lock dma write position */
1217 queue_post(&pcmrec_queue, PCMREC_FINISH_STOP, NULL);
818 1218
1219not_recording_or_stopping:
1220 pcm_thread_signal_event(PCMREC_STOP);
819 logf("pcmrec_stop done"); 1221 logf("pcmrec_stop done");
820} 1222} /* pcmrec_stop */
821 1223
822static void pcmrec_new_file(void) 1224/* PCMREC_FINISH_STOP */
1225static void pcmrec_finish_stop(void)
823{ 1226{
824 logf("pcmrec_new_file"); 1227 logf("pcmrec_finish_stop");
825 1228
826 if (!is_recording) 1229 if (!is_stopping)
827 { 1230 {
828 logf("not recording"); 1231 logf("not stopping");
829 new_file_done = true; 1232 goto not_stopping;
830 return;
831 } 1233 }
832 1234
833 /* Since pcmrec_callback() blocks until the data has been written, 1235 /* flush all available data first to avoid overflow while waiting
834 here is a good approximation when recording to the new file starts 1236 for encoding to finish */
835 */ 1237 pcmrec_flush(-1);
836 record_start_time = current_tick;
837 1238
838 if (is_paused) 1239 /* wait for encoder to finish remaining data */
839 pause_start_time = record_start_time; 1240 if (!is_error)
1241 {
1242 while (!wav_queue_empty)
1243 yield();
1244 }
840 1245
841 /* Flush what we got in buffers to file */ 1246 /* end stream at last data */
842 pcmrec_callback(true); 1247 pcmrec_new_stream(NULL, CHUNKF_END_FILE, 0);
843 1248
844 close_wave(); 1249 /* flush anything else encoder added */
845 1250 pcmrec_flush(-1);
846 num_rec_bytes = 0; 1251
847 num_file_bytes = 0; 1252 /* remove any pending file start not yet processed - should be at
848 num_pcm_samples = 0; 1253 most one at enc_wr_index */
1254 pcmrec_fnq_get_filename(NULL);
1255 /* encoder should abort any chunk it was in midst of processing */
1256 GET_ENC_CHUNK(enc_wr_index)->flags = CHUNKF_ABORT;
849 1257
850 /* start the new file */ 1258 /* filename queue should be empty */
851 if (start_wave() != 0) 1259 if (!pcmrec_fnq_is_empty())
852 { 1260 {
853 logf("new_file failed"); 1261 logf("fnq: not empty!");
854 pcmrec_stop(); 1262 pcmrec_fnq_set_empty();
855 } 1263 }
856 1264
857 new_file_done = true; 1265 /* be absolutely sure the file is closed */
858 logf("pcmrec_new_file done"); 1266 if (is_error)
859} 1267 pcmrec_close_file(&rec_fdata.rec_file);
1268 rec_fdata.rec_file = -1;
1269
1270 is_recording = false;
1271 is_paused = false;
1272 is_stopping = false;
1273 dma_lock = pre_record_ticks == 0;
1274
1275not_stopping:
1276 logf("pcmrec_finish_stop done");
1277} /* pcmrec_finish_stop */
860 1278
1279/* PCMREC_PAUSE */
861static void pcmrec_pause(void) 1280static void pcmrec_pause(void)
862{ 1281{
863 logf("pcmrec_pause"); 1282 logf("pcmrec_pause");
864 1283
865 if (!is_recording) 1284 if (!is_recording)
866 { 1285 {
867 logf("pause: not recording"); 1286 logf("not recording");
868 pause_done = true; 1287 goto not_recording_or_paused;
869 return; 1288 }
1289 else if (is_paused)
1290 {
1291 logf("already paused");
1292 goto not_recording_or_paused;
870 } 1293 }
871 1294
872 pause_start_time = current_tick; 1295 dma_lock = true; /* fix DMA write pointer at current position */
873 is_paused = true; 1296 is_paused = true;
874 pause_done = true;
875 1297
1298not_recording_or_paused:
1299 pcm_thread_signal_event(PCMREC_PAUSE);
876 logf("pcmrec_pause done"); 1300 logf("pcmrec_pause done");
877} 1301} /* pcmrec_pause */
878
879 1302
1303/* PCMREC_RESUME */
880static void pcmrec_resume(void) 1304static void pcmrec_resume(void)
881{ 1305{
882 logf("pcmrec_resume"); 1306 logf("pcmrec_resume");
883 1307
884 if (!is_paused) 1308 if (!is_recording)
885 { 1309 {
886 logf("resume: not paused"); 1310 logf("not recording");
887 resume_done = true; 1311 goto not_recording_or_not_paused;
888 return; 1312 }
1313 else if (!is_paused)
1314 {
1315 logf("not paused");
1316 goto not_recording_or_not_paused;
889 } 1317 }
890 1318
891 is_paused = false; 1319 is_paused = false;
892 is_recording = true; 1320 is_recording = true;
1321 dma_lock = false;
893 1322
894 /* Compensate for the time we have been paused */ 1323not_recording_or_not_paused:
895 if (pause_start_time) 1324 pcm_thread_signal_event(PCMREC_RESUME);
896 {
897 record_start_time += current_tick - pause_start_time;
898 pause_start_time = 0;
899 }
900
901 resume_done = true;
902 logf("pcmrec_resume done"); 1325 logf("pcmrec_resume done");
903} 1326} /* pcmrec_resume */
904 1327
905/** 1328/* PCMREC_NEW_FILE */
906 * audio_init_recording calls this function using PCMREC_INIT 1329static void pcmrec_new_file(const char *filename)
907 *
908 */
909static void pcmrec_init(void)
910{ 1330{
911 wav_file = -1; 1331 logf("pcmrec_new_file: %s", filename);
912 read_pos = 0;
913 write_pos = 0;
914 enc_wr_index = 0;
915 enc_rd_index = 0;
916 1332
917 avrg_bit_rate = 0; 1333 if (!is_recording)
918 curr_bit_rate = 0; 1334 {
919 curr_chunk_cnt = 0; 1335 logf("not recording");
920 1336 goto not_recording;
921 peak_left = 0; 1337 }
922 peak_right = 0;
923 1338
924 num_rec_bytes = 0; 1339 num_rec_bytes = 0;
925 num_file_bytes = 0; 1340 num_rec_samples = 0;
926 num_pcm_samples = 0;
927 record_start_time = 0;
928 pause_start_time = 0;
929
930 close_done = false;
931 is_recording = false;
932 is_paused = false;
933 is_error = false;
934
935 rec_buffer = (unsigned char*)(((long)audiobuf + 15) & ~15);
936 enc_buffer = rec_buffer + NUM_CHUNKS * CHUNK_SIZE + MAX_FEED_SIZE;
937 /* 8000Bytes at audiobufend */
938 enc_buffer_size = audiobufend - enc_buffer - 8000;
939
940 SET_IIS_PLAY(0x800); /* Stop any playback */
941 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
942 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */
943
944 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
945 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
946 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
947 ICR7 = 0x1c; /* Enable interrupt at level 7, priority 0 */
948 IMR &= ~(1<<15); /* bit 15 is DMA1 */
949
950#ifdef HAVE_SPDIF_IN
951 PHASECONFIG = 0x34; /* Gain = 3*2^13, source = EBUIN */
952#endif
953 pcmrec_dma_start();
954
955 init_done = 1;
956}
957 1341
958static void pcmrec_close(void) 1342 pcmrec_new_stream(filename,
959{ 1343 CHUNKF_START_FILE | CHUNKF_END_FILE,
960 DMAROUTE = (DMAROUTE & 0xffff00ff); 1344 0);
961 ICR7 = 0x00; /* Disable interrupt */
962 IMR |= (1<<15); /* bit 15 is DMA1 */
963 1345
964 pcmrec_dma_stop(); 1346not_recording:
965 1347 pcm_thread_signal_event(PCMREC_NEW_FILE);
966 /* Reset PDIR2 data flow */ 1348 logf("pcmrec_new_file done");
967 DATAINCONTROL = 0x200; 1349} /* pcmrec_new_file */
968 close_done = true;
969 init_done = false;
970}
971 1350
1351static void pcmrec_thread(void) __attribute__((noreturn));
972static void pcmrec_thread(void) 1352static void pcmrec_thread(void)
973{ 1353{
974 struct event ev; 1354 struct event ev;
975 1355
976 logf("thread pcmrec start"); 1356 logf("thread pcmrec start");
977 1357
978 error_count = 0;
979
980 while(1) 1358 while(1)
981 { 1359 {
982 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 4); 1360 if (is_recording)
1361 {
1362 /* Poll periodically to flush data */
1363 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ/5);
1364
1365 if (ev.id == SYS_TIMEOUT)
1366 {
1367 pcmrec_flush(0); /* flush if getting full */
1368 continue;
1369 }
1370 }
1371 else
1372 {
1373 /* Not doing anything - sit and wait for commands */
1374 queue_wait(&pcmrec_queue, &ev);
1375 }
983 1376
984 switch (ev.id) 1377 switch (ev.id)
985 { 1378 {
@@ -992,13 +1385,17 @@ static void pcmrec_thread(void)
992 break; 1385 break;
993 1386
994 case PCMREC_START: 1387 case PCMREC_START:
995 pcmrec_start(); 1388 pcmrec_start((const char *)ev.data);
996 break; 1389 break;
997 1390
998 case PCMREC_STOP: 1391 case PCMREC_STOP:
999 pcmrec_stop(); 1392 pcmrec_stop();
1000 break; 1393 break;
1001 1394
1395 case PCMREC_FINISH_STOP:
1396 pcmrec_finish_stop();
1397 break;
1398
1002 case PCMREC_PAUSE: 1399 case PCMREC_PAUSE:
1003 pcmrec_pause(); 1400 pcmrec_pause();
1004 break; 1401 break;
@@ -1008,11 +1405,11 @@ static void pcmrec_thread(void)
1008 break; 1405 break;
1009 1406
1010 case PCMREC_NEW_FILE: 1407 case PCMREC_NEW_FILE:
1011 pcmrec_new_file(); 1408 pcmrec_new_file((const char *)ev.data);
1012 break; 1409 break;
1013 1410
1014 case SYS_TIMEOUT: 1411 case PCMREC_FLUSH_NUM:
1015 pcmrec_callback(false); 1412 pcmrec_flush((unsigned)ev.data);
1016 break; 1413 break;
1017 1414
1018 case SYS_USB_CONNECTED: 1415 case SYS_USB_CONNECTED:
@@ -1023,140 +1420,267 @@ static void pcmrec_thread(void)
1023 usb_wait_for_disconnect(&pcmrec_queue); 1420 usb_wait_for_disconnect(&pcmrec_queue);
1024 } 1421 }
1025 break; 1422 break;
1026 } 1423 } /* end switch */
1027 } 1424 } /* end while */
1425} /* pcmrec_thread */
1028 1426
1029 logf("thread pcmrec done"); 1427/****************************************************************************/
1030} 1428/* */
1429/* following functions will be called by the encoder codec */
1430/* */
1431/****************************************************************************/
1031 1432
1032/* Select VINL & VINR source: 0=Line-in, 1=FM Radio */ 1433/* pass the encoder settings to the encoder */
1033void pcm_rec_mux(int source) 1434void enc_get_inputs(struct enc_inputs *inputs)
1034{ 1435{
1035#ifdef IRIVER_H300_SERIES 1436 inputs->sample_rate = sample_rate;
1036 if(source == 0) 1437 inputs->num_channels = num_channels;
1037 and_l(~0x40000000, &GPIO_OUT); /* Line In */ 1438 inputs->config = &enc_config;
1038 else 1439} /* enc_get_inputs */
1039 or_l(0x40000000, &GPIO_OUT); /* FM radio */
1040 1440
1041 or_l(0x40000000, &GPIO_ENABLE); 1441/* set the encoder dimensions (called by encoder codec at initialization and
1042 or_l(0x40000000, &GPIO_FUNCTION); 1442 termination) */
1043#elif defined(IRIVER_H100_SERIES) 1443void enc_set_parameters(struct enc_parameters *params)
1044 if(source == 0) 1444{
1045 and_l(~0x00800000, &GPIO_OUT); /* Line In */ 1445 size_t bufsize, resbytes;
1046 else
1047 or_l(0x00800000, &GPIO_OUT); /* FM radio */
1048 1446
1049 or_l(0x00800000, &GPIO_ENABLE); 1447 logf("enc_set_parameters");
1050 or_l(0x00800000, &GPIO_FUNCTION);
1051 1448
1052#elif defined(IAUDIO_X5) 1449 if (!params)
1053 if(source == 0) 1450 {
1054 or_l((1<<29), &GPIO_OUT); /* Line In */ 1451 logf("reset");
1055 else 1452 /* Encoder is terminating */
1056 and_l(~(1<<29), &GPIO_OUT); /* FM radio */ 1453 memset(&enc_config, 0, sizeof (enc_config));
1454 enc_sample_rate = 0;
1455 return;
1456 }
1457
1458 enc_sample_rate = params->enc_sample_rate;
1459 logf("enc sampr:%d", enc_sample_rate);
1460
1461 pcm_rd_pos = dma_wr_pos;
1462
1463 enc_config.afmt = params->afmt;
1464 /* addition of the header is always implied - chunk size 4-byte aligned */
1465 enc_chunk_size =
1466 ALIGN_UP_P2(ENC_CHUNK_HDR_SIZE + params->chunk_size, 2);
1467 enc_data_size = enc_chunk_size - ENC_CHUNK_HDR_SIZE;
1468 enc_events_callback = params->events_callback;
1469
1470 logf("chunk size:%d", enc_chunk_size);
1471
1472 /*** Configure the buffers ***/
1473
1474 /* Layout of recording buffer:
1475 * [ax] = possible alignment x multiple
1476 * [sx] = possible size alignment of x multiple
1477 * |[a16]|[s4]:PCM Buffer+PCM Guard|[s4 each]:Encoder Chunks|->
1478 * |[[s4]:Reserved Bytes]|Filename Queue->|[space]|
1479 */
1480 resbytes = ALIGN_UP_P2(params->reserve_bytes, 2);
1481 logf("resbytes:%d", resbytes);
1482
1483 bufsize = rec_buffer_size - (enc_buffer - pcm_buffer) -
1484 resbytes - FNQ_MIN_NUM_PATHS*MAX_PATH;
1485
1486 enc_num_chunks = bufsize / enc_chunk_size;
1487 logf("num chunks:%d", enc_num_chunks);
1057 1488
1058 or_l((1<<29), &GPIO_ENABLE); 1489 /* get real amount used by encoder chunks */
1059 or_l((1<<29), &GPIO_FUNCTION); 1490 bufsize = enc_num_chunks*enc_chunk_size;
1491 logf("enc size:%d", bufsize);
1492
1493 /* panic boost thread priority at 1 second remaining */
1494 panic_threshold = enc_num_chunks -
1495 (4*sample_rate + (enc_chunk_size-1)) / enc_chunk_size;
1496 if (panic_threshold < 0)
1497 panic_threshold = 0;
1498
1499 logf("panic thr:%d", panic_threshold);
1500
1501 /** set OUT parameters **/
1502 params->enc_buffer = enc_buffer;
1503 params->buf_chunk_size = enc_chunk_size;
1504 params->num_chunks = enc_num_chunks;
1505
1506 /* calculate reserve buffer start and return pointer to encoder */
1507 params->reserve_buffer = NULL;
1508 if (resbytes > 0)
1509 {
1510 params->reserve_buffer = enc_buffer + bufsize;
1511 bufsize += resbytes;
1512 }
1060 1513
1061 /* iAudio x5 */ 1514 /* place filename queue at end of buffer using up whatever remains */
1515 fnq_rd_pos = 0; /* reset */
1516 fnq_wr_pos = 0; /* reset */
1517 fn_queue = enc_buffer + bufsize;
1518 fnq_size = pcm_buffer + rec_buffer_size - fn_queue;
1519 fnq_size = ALIGN_DOWN(fnq_size, MAX_PATH);
1520 logf("fnq files: %d", fnq_size / MAX_PATH);
1521
1522#if 0
1523 logf("ab :%08X", (unsigned long)audiobuf);
1524 logf("pcm:%08X", (unsigned long)pcm_buffer);
1525 logf("enc:%08X", (unsigned long)enc_buffer);
1526 logf("res:%08X", (unsigned long)params->reserve_buffer);
1527 logf("fnq:%08X", (unsigned long)fn_queue);
1528 logf("end:%08X", (unsigned long)fn_queue + fnq_size);
1529 logf("abe:%08X", (unsigned long)audiobufend);
1062#endif 1530#endif
1063}
1064 1531
1532 /* init all chunk headers and reset indexes */
1533 enc_rd_index = 0;
1534 for (enc_wr_index = enc_num_chunks; enc_wr_index > 0; )
1535 GET_ENC_CHUNK(--enc_wr_index)->flags = 0;
1065 1536
1066/****************************************************************************/ 1537 logf("enc_set_parameters done");
1067/* */ 1538} /* enc_set_parameters */
1068/* following functions will be called by the encoder codec */
1069/* */
1070/****************************************************************************/
1071 1539
1072/* pass the encoder buffer pointer/size, mono/stereo, quality to the encoder */ 1540/* return encoder chunk at current write position */
1073void enc_get_inputs(int *buffer_size, int *channels, int *quality) 1541struct enc_chunk_hdr * enc_get_chunk(void)
1074{ 1542{
1075 *buffer_size = enc_buffer_size; 1543 struct enc_chunk_hdr *chunk = GET_ENC_CHUNK(enc_wr_index);
1076 *channels = enc_channels; 1544 chunk->flags &= CHUNKF_START_FILE;
1077 *quality = enc_quality;
1078}
1079 1545
1080/* set the encoder dimensions (called by encoder codec at initialization) */ 1546 if (!is_recording)
1081void enc_set_parameters(int chunk_size, int num_chunks, int samp_per_chunk, 1547 chunk->flags |= CHUNKF_PRERECORD;
1082 char *head_ptr, int head_size, int enc_id)
1083{
1084 /* set read_pos just in front of current write_pos */
1085 read_pos = (write_pos - CHUNK_SIZE) & CHUNK_MASK;
1086
1087 enc_rd_index = 0; /* reset */
1088 enc_wr_index = 0; /* reset */
1089 enc_chunk_size = chunk_size; /* max chunk size */
1090 enc_num_chunks = num_chunks; /* total number of chunks */
1091 enc_samp_per_chunk = samp_per_chunk; /* pcm samples / encoderchunk */
1092 enc_head_buffer = head_ptr; /* optional file header data (wav) */
1093 enc_head_size = head_size; /* optional file header data (wav) */
1094 audio_enc_id = enc_id; /* AFMT_* id */
1095}
1096 1548
1097/* allocate encoder chunk */ 1549 return chunk;
1098unsigned int *enc_alloc_chunk(void) 1550} /* enc_get_chunk */
1099{
1100 return (unsigned int*)(enc_buffer + enc_wr_index * enc_chunk_size);
1101}
1102 1551
1103/* free previously allocated encoder chunk */ 1552/* releases the current chunk into the available chunks */
1104void enc_free_chunk(void) 1553void enc_finish_chunk(void)
1105{ 1554{
1106 unsigned long *enc_chunk; 1555 struct enc_chunk_hdr *chunk = GET_ENC_CHUNK(enc_wr_index);
1107 1556
1108 enc_chunk = GET_ENC_CHUNK(enc_wr_index); 1557 /* encoder may have set error flag or written too much data */
1109 curr_chunk_cnt++; 1558 if ((long)chunk->flags < 0 || chunk->enc_size > enc_data_size)
1110/* curr_bit_rate += *enc_chunk * 44100 * 8 / (enc_samp_per_chunk * 1000); */ 1559 {
1111 curr_bit_rate += *enc_chunk * 441 * 8 / (enc_samp_per_chunk * 10 ); 1560 is_error = true;
1112 avrg_bit_rate = (curr_bit_rate + curr_chunk_cnt / 2) / curr_chunk_cnt;
1113 1561
1114 /* advance enc_wr_index to the next chunk */ 1562#ifdef ROCKBOX_HAS_LOGF
1115 enc_wr_index = (enc_wr_index + 1) % enc_num_chunks; 1563 if (chunk->enc_size > enc_data_size)
1564 {
1565 /* illegal to scribble over next chunk */
1566 logf("finish chk ovf: %d>%d", chunk->enc_size, enc_data_size);
1567 }
1568 else
1569 {
1570 /* encoder set error flag */
1571 logf("finish chk enc error");
1572 }
1573#endif
1574 }
1575
1576 /* advance enc_wr_index to the next encoder chunk */
1577 INC_ENC_INDEX(enc_wr_index);
1116 1578
1117 /* buffer full: advance enc_rd_index (for prerecording purpose) */ 1579 if (enc_rd_index != enc_wr_index)
1118 if (enc_rd_index == enc_wr_index)
1119 { 1580 {
1120 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks; 1581 num_rec_bytes += chunk->enc_size;
1582 accum_rec_bytes += chunk->enc_size;
1583 num_rec_samples += chunk->num_pcm;
1584 accum_pcm_samples += chunk->num_pcm;
1121 } 1585 }
1122} 1586 else if (is_recording) /* buffer full */
1587 {
1588 /* keep current position */
1589 logf("enc_buffer ovf");
1590 DEC_ENC_INDEX(enc_wr_index);
1591 }
1592 else
1593 {
1594 /* advance enc_rd_index for prerecording */
1595 INC_ENC_INDEX(enc_rd_index);
1596 }
1597} /* enc_finish_chunk */
1123 1598
1124/* checks near empty state on wav input buffer */ 1599/* checks near empty state on pcm input buffer */
1125int enc_wavbuf_near_empty(void) 1600int enc_pcm_buf_near_empty(void)
1126{ 1601{
1127 /* less than 1sec raw data? => unboost encoder */ 1602 /* less than 1sec raw data? => unboost encoder */
1128 if (((write_pos - read_pos) & CHUNK_MASK) < 44100*4) 1603 size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
1129 return 1; 1604 return avail < (sample_rate << 2) ? 1 : 0;
1130 else 1605} /* enc_pcm_buf_near_empty */
1131 return 0;
1132}
1133 1606
1134/* passes a pointer to next chunk of unprocessed wav data */ 1607/* passes a pointer to next chunk of unprocessed wav data */
1135char *enc_get_wav_data(int size) 1608/* TODO: this really should give the actual size returned */
1609unsigned char * enc_get_pcm_data(size_t size)
1136{ 1610{
1137 char *ptr; 1611 size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
1138 int avail;
1139 1612
1140 /* limit the requested pcm data size */ 1613 /* limit the requested pcm data size */
1141 if(size > MAX_FEED_SIZE) 1614 if (size > PCM_MAX_FEED_SIZE)
1142 size = MAX_FEED_SIZE; 1615 size = PCM_MAX_FEED_SIZE;
1143
1144 avail = (write_pos - read_pos) & CHUNK_MASK;
1145 1616
1146 if (avail >= size) 1617 if (avail >= size)
1147 { 1618 {
1148 ptr = rec_buffer + read_pos; 1619 unsigned char *ptr = pcm_buffer + pcm_rd_pos;
1149 read_pos = (read_pos + size) & CHUNK_MASK; 1620 pcm_rd_pos = (pcm_rd_pos + size) & PCM_CHUNK_MASK;
1150 1621
1151 /* ptr must point to continous data at wraparound position */ 1622 /* ptr must point to continous data at wraparound position */
1152 if (read_pos < size) 1623 if ((size_t)pcm_rd_pos < size)
1153 memcpy(rec_buffer + NUM_CHUNKS * CHUNK_SIZE, 1624 memcpy(pcm_buffer + PCM_NUM_CHUNKS*PCM_CHUNK_SIZE,
1154 rec_buffer, read_pos); 1625 pcm_buffer, pcm_rd_pos);
1155 1626
1156 wav_queue_empty = false; 1627 wav_queue_empty = false;
1157 return ptr; 1628 return ptr;
1158 } 1629 }
1159 1630
1631 /* not enough data available - encoder should idle */
1160 wav_queue_empty = true; 1632 wav_queue_empty = true;
1161 return NULL; 1633 return NULL;
1162} 1634} /* enc_get_pcm_data */
1635
1636/* puts some pcm data back in the queue */
1637size_t enc_unget_pcm_data(size_t size)
1638{
1639 /* can't let DMA advance write position when doing this */
1640 int level = set_irq_level(HIGHEST_IRQ_LEVEL);
1641
1642 if (pcm_rd_pos != dma_wr_pos)
1643 {
1644 /* disallow backing up into current DMA write chunk */
1645 size_t old_avail = (pcm_rd_pos - dma_wr_pos - PCM_CHUNK_SIZE)
1646 & PCM_CHUNK_MASK;
1647
1648 /* limit size to amount of old data remaining */
1649 if (size > old_avail)
1650 size = old_avail;
1651
1652 pcm_rd_pos = (pcm_rd_pos - size) & PCM_CHUNK_MASK;
1653 }
1654
1655 set_irq_level(level);
1656
1657 return size;
1658} /* enc_unget_pcm_data */
1659
1660/** Low level pcm recording apis **/
1661
1662/****************************************************************************
1663 * Functions that do not require targeted implementation but only a targeted
1664 * interface
1665 */
1666void pcm_record_data(pcm_more_callback_type more_ready,
1667 unsigned char *start, size_t size)
1668{
1669 pcm_callback_more_ready = more_ready;
1670
1671 if (!(start && size))
1672 {
1673 size = 0;
1674 if (more_ready)
1675 more_ready(&start, &size);
1676 }
1677
1678 if (start && size)
1679 pcm_rec_dma_start(start, size);
1680} /* pcm_record_data */
1681
1682void pcm_stop_recording(void)
1683{
1684 if (pcm_recording)
1685 pcm_rec_dma_stop();
1686} /* pcm_stop_recording */
diff --git a/firmware/system.c b/firmware/system.c
index 242d84d16c..96d5f96602 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -390,8 +390,7 @@ int system_memory_guard(int newmode)
390 (void)newmode; 390 (void)newmode;
391 return 0; 391 return 0;
392} 392}
393#elif defined(CPU_COLDFIRE) 393
394/* system code is in target tree for all coldfire targets */
395#elif CONFIG_CPU == SH7034 394#elif CONFIG_CPU == SH7034
396#include "led.h" 395#include "led.h"
397#include "system.h" 396#include "system.h"
diff --git a/firmware/target/coldfire/iaudio/x5/system-x5.c b/firmware/target/coldfire/iaudio/x5/system-x5.c
index 6be6d25ce0..30a4f6e71b 100644
--- a/firmware/target/coldfire/iaudio/x5/system-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/system-x5.c
@@ -42,7 +42,7 @@ void set_cpu_frequency(long frequency)
42 PLLCR &= ~1; /* Bypass mode */ 42 PLLCR &= ~1; /* Bypass mode */
43 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 43 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
44 RECALC_DELAYS(CPUFREQ_MAX); 44 RECALC_DELAYS(CPUFREQ_MAX);
45 PLLCR = 0x13442045; 45 PLLCR = 0x03042045 | (PLLCR & 0x70C00000);
46 CSCR0 = 0x00001180; /* Flash: 4 wait states */ 46 CSCR0 = 0x00001180; /* Flash: 4 wait states */
47 CSCR1 = 0x00000980; /* LCD: 2 wait states */ 47 CSCR1 = 0x00000980; /* LCD: 2 wait states */
48 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 48 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
@@ -60,7 +60,7 @@ void set_cpu_frequency(long frequency)
60 PLLCR &= ~1; /* Bypass mode */ 60 PLLCR &= ~1; /* Bypass mode */
61 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 61 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
62 RECALC_DELAYS(CPUFREQ_NORMAL); 62 RECALC_DELAYS(CPUFREQ_NORMAL);
63 PLLCR = 0x16430045; 63 PLLCR = 0x06030045 | (PLLCR & 0x70C00000);
64 CSCR0 = 0x00000580; /* Flash: 1 wait state */ 64 CSCR0 = 0x00000580; /* Flash: 1 wait state */
65 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 65 CSCR1 = 0x00000180; /* LCD: 0 wait states */
66 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 66 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
@@ -77,7 +77,8 @@ void set_cpu_frequency(long frequency)
77 PLLCR &= ~1; /* Bypass mode */ 77 PLLCR &= ~1; /* Bypass mode */
78 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true); 78 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
79 RECALC_DELAYS(CPUFREQ_DEFAULT); 79 RECALC_DELAYS(CPUFREQ_DEFAULT);
80 PLLCR = 0x10400200; /* Power down PLL, but keep CLSEL and CRSEL */ 80 /* Power down PLL, but keep CLSEL and CRSEL */
81 PLLCR = 0x00000200 | (PLLCR & 0x70C00000);
81 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 82 CSCR0 = 0x00000180; /* Flash: 0 wait states */
82 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 83 CSCR1 = 0x00000180; /* LCD: 0 wait states */
83 DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */ 84 DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */
diff --git a/firmware/target/coldfire/iriver/system-iriver.c b/firmware/target/coldfire/iriver/system-iriver.c
index 3517788641..43ba4eeed4 100644
--- a/firmware/target/coldfire/iriver/system-iriver.c
+++ b/firmware/target/coldfire/iriver/system-iriver.c
@@ -81,7 +81,7 @@ void set_cpu_frequency(long frequency)
81 PLLCR &= ~1; /* Bypass mode */ 81 PLLCR &= ~1; /* Bypass mode */
82 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 82 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
83 RECALC_DELAYS(CPUFREQ_MAX); 83 RECALC_DELAYS(CPUFREQ_MAX);
84 PLLCR = 0x11c56005; 84 PLLCR = 0x01056005 | (PLLCR & 0x70c00000);
85 CSCR0 = 0x00001180; /* Flash: 4 wait states */ 85 CSCR0 = 0x00001180; /* Flash: 4 wait states */
86 CSCR1 = 0x00001580; /* LCD: 5 wait states */ 86 CSCR1 = 0x00001580; /* LCD: 5 wait states */
87#if CONFIG_USBOTG == USBOTG_ISP1362 87#if CONFIG_USBOTG == USBOTG_ISP1362
@@ -108,7 +108,7 @@ void set_cpu_frequency(long frequency)
108 PLLCR &= ~1; /* Bypass mode */ 108 PLLCR &= ~1; /* Bypass mode */
109 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 109 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
110 RECALC_DELAYS(CPUFREQ_NORMAL); 110 RECALC_DELAYS(CPUFREQ_NORMAL);
111 PLLCR = 0x13c5e005; 111 PLLCR = 0x0305e005 | (PLLCR & 0x70c00000);
112 CSCR0 = 0x00000580; /* Flash: 1 wait state */ 112 CSCR0 = 0x00000580; /* Flash: 1 wait state */
113 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 113 CSCR1 = 0x00000180; /* LCD: 0 wait states */
114#if CONFIG_USBOTG == USBOTG_ISP1362 114#if CONFIG_USBOTG == USBOTG_ISP1362
@@ -134,7 +134,8 @@ void set_cpu_frequency(long frequency)
134 PLLCR &= ~1; /* Bypass mode */ 134 PLLCR &= ~1; /* Bypass mode */
135 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true); 135 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
136 RECALC_DELAYS(CPUFREQ_DEFAULT); 136 RECALC_DELAYS(CPUFREQ_DEFAULT);
137 PLLCR = 0x10c00200; /* Power down PLL, but keep CLSEL and CRSEL */ 137 /* Power down PLL, but keep CLSEL and CRSEL */
138 PLLCR = 0x00000200 | (PLLCR & 0x70c00000);
138 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 139 CSCR0 = 0x00000180; /* Flash: 0 wait states */
139 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 140 CSCR1 = 0x00000180; /* LCD: 0 wait states */
140#if CONFIG_USBOTG == USBOTG_ISP1362 141#if CONFIG_USBOTG == USBOTG_ISP1362
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index 66e4feb154..2fc81496db 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -310,3 +310,10 @@ int system_memory_guard(int newmode)
310 310
311 return oldmode; 311 return oldmode;
312} 312}
313
314/* allow setting of audio clock related bits */
315void coldfire_set_pllcr_audio_bits(long bits)
316{
317 PLLCR = (PLLCR & ~0x70c00000) | (bits & 0x70c00000);
318}
319
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 03852115ad..24e3fb8705 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -110,6 +110,28 @@ static inline unsigned long swap32(unsigned long value)
110 return value; 110 return value;
111} 111}
112 112
113static inline unsigned long swap_odd_even32(unsigned long value)
114{
115 /*
116 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
117 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
118 */
119 unsigned long mask = 0x00FF00FF;
120
121 asm ( /* val = ABCD */
122 "and.l %[val],%[mask] \n" /* mask = .B.D */
123 "eor.l %[mask],%[val] \n" /* val = A.C. */
124 "lsl.l #8,%[mask] \n" /* mask = B.D. */
125 "lsr.l #8,%[val] \n" /* val = .A.C */
126 "or.l %[mask],%[val] \n" /* val = BADC */
127 : /* outputs */
128 [val] "+d"(value),
129 [mask]"+d"(mask)
130 );
131
132 return value;
133}
134
113static inline void invalidate_icache(void) 135static inline void invalidate_icache(void)
114{ 136{
115 asm volatile ("move.l #0x01000000,%d0\n" 137 asm volatile ("move.l #0x01000000,%d0\n"
@@ -118,6 +140,13 @@ static inline void invalidate_icache(void)
118 "movec.l %d0,%cacr"); 140 "movec.l %d0,%cacr");
119} 141}
120 142
143#ifdef IAUDIO_X5
144#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000
145#else
146#define DEFAULT_PLLCR_AUDIO_BITS 0x10c00000
147#endif
148void coldfire_set_pllcr_audio_bits(long bits);
149
121/* 11.2896 MHz */ 150/* 11.2896 MHz */
122#define CPUFREQ_DEFAULT_MULT 1 151#define CPUFREQ_DEFAULT_MULT 1
123#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) 152#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)
diff --git a/firmware/thread.c b/firmware/thread.c
index 6a94a52333..4094877742 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -711,6 +711,14 @@ int thread_set_priority(struct thread_entry *thread, int priority)
711 711
712 return old_priority; 712 return old_priority;
713} 713}
714
715int thread_get_priority(struct thread_entry *thread)
716{
717 if (thread == NULL)
718 thread = cores[CURRENT_CORE].running;
719
720 return thread->priority;
721}
714#endif 722#endif
715 723
716void init_threads(void) 724void init_threads(void)