Commit 3bd30208 authored by Erik Faye-Lund's avatar Erik Faye-Lund
Browse files

added a IRQ_SAFE flag to mixer. this allows irqs to happen while the mixer...

added a IRQ_SAFE flag to mixer. this allows irqs to happen while the mixer works, to allow tight irq-sync.

git-svn-id: https://pimpmobile.svn.sourceforge.net/svnroot/pimpmobile/trunk@124 3d5ecaf0-f903-0410-b953-c2c1a4d75763
parent f36462f3
......@@ -44,9 +44,7 @@ else
CPPFLAGS += -DRELEASE -DNDEBUG
CXXFLAGS += -O3 -fomit-frame-pointer
CFLAGS += -O3 -fomit-frame-pointer
OBJS += src/mixer_arm.iwram.o
OBJS += src/mixer_arm_asm.o
# OBJS += src/mixer_portable.iwram.o
endif
......
......@@ -61,8 +61,8 @@ void vblank()
// printf("%d.%02d\n", int(val * 100), int(val * 100 * 100));
// pimp_set_pos(0, 0);
pimp_close();
pimp_init(mod, sample_bank);
// pimp_close();
// pimp_init(mod, sample_bank);
counter = 0;
accum = 0;
......
......@@ -196,13 +196,14 @@ u32 __pimp_mixer_mix_samples(s32 *target, u32 samples, const u8 *sample_data, u3
ASSERT(target != NULL);
ASSERT(sample_data != NULL);
#if 1
u32 ime = REG_IME;
REG_IME = 0;
// u32 ime = REG_IME;
// REG_IME = 0;
sample_cursor = __pimp_mixer_mix_samples_asm(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta);
sample_cursor = __pimp_mixer_mix_samples_asm(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta);
// printf("%d\n", REG_IME);
/* restore interrupt state */
REG_IME = ime;
// REG_IME = ime;
return sample_cursor;
#endif
......
......@@ -3,22 +3,36 @@
.arm
.align 2
@ no mixing: 406517
@ no mixing: 361612
@ without bresenham:
@ inline-asm version: 1211037
@ current: 1192545
@ inline-asm version: 1211037
@ current: 1150788
@ with bresenham:
@ inline-asm version: 1163062 (718741)
@ current: 1146840 (702519)
@ inline-asm version: 1163062
@ current: 1105083
#define NO_MIXING
@irq-safe: 1121327
@irq-unsafe: 1105083
// #define IRQ_SAFE
#define USE_BRESENHAM_MIXER
// #define NO_MIXING
.stack_store:
.word 0
.jumptable:
#ifndef IRQ_SAFE
.ime_store:
.word 0
#endif
#ifdef USE_BRESENHAM_MIXER
.sample_data_store:
.word 0
#endif
.mixer_jumptable:
.word .mix0
.word .mix1
.word .mix2
......@@ -28,34 +42,33 @@
.word .mix6
.word .mix7
.global __pimp_mixer_mix_samples_asm
__pimp_mixer_mix_samples_asm:
.global __pimp_mixer_mix_samples
__pimp_mixer_mix_samples:
stmfd sp!, {r4-r12, lr} @ store all registers but parameters and stack
#ifdef NO_MIXING
ldmfd sp!, {r4-r12, lr} @ restore rest of registers
bx lr @ return to caller
#endif
str sp, .stack_store @ store stack pointer so we can use that register in our mixer (note, interrupts must be disabled for this to be safe)
#define UNROLL_RANGE r4-r11
#define TARGET r0
#define COUNTER r1
#define SAMPLE_DATA r2
#define VOLUME r3
#define SAMPLE_CURSOR lr
#define SAMPLE_CURSOR_DELTA r12
@ load rest of parameters
ldr SAMPLE_CURSOR, [sp, #40]
ldr SAMPLE_CURSOR_DELTA, [sp, #44]
@ find how many samples to fixup
and r4, COUNTER, #7
@ fixup, jump to the correct position
adr r5, .jumptable
adr r5, .mixer_jumptable
ldr pc, [r5, r4, lsl #2]
@ fixup code unrolled 7 times
......@@ -112,21 +125,30 @@ __pimp_mixer_mix_samples_asm:
movs COUNTER, COUNTER, asr #3 @ divide counter by 8
beq .ret @ if no more samples, return
// if (sample_cursor_delta > 0 && sample_cursor_delta < (1UL << 12))
// this can be done as:
// if ((sample_cursor_delta & ~((1UL << 12) - 1)) == 0)
@ check if bresenham mixer can be used or not
#ifndef IRQ_SAFE
ldr r4, =0x4000208 @ load address of REG_IME
ldr r5, [r4] @ load value of REG_IME
str r5, .ime_store @ stash for later
eor r6, r6
str r6, [r4] @ disable interrupt
#endif
#ifdef USE_BRESENHAM_MIXER
ldr r4, =0xfffff000
tst SAMPLE_CURSOR_DELTA, r4
beq .bresenham_mixer
// if ((sample_cursor_delta & ~((1UL << 12) - 1)) == 0)
@ check if bresenham mixer can be used or not
ldr r4, =0xfffff000 @ ~((1UL << 12) - 1))
tst SAMPLE_CURSOR_DELTA, r4 @ any bits set?
beq .bresenham_mixer @ no? lets go!
#endif
#ifdef IRQ_SAFE
#define TEMP r11
#define UNROLL_RANGE r4-r10
#else
#define TEMP sp
#define UNROLL_RANGE r4-r11
#endif
.simple_loop:
ldmia TARGET, {UNROLL_RANGE}
......@@ -159,15 +181,32 @@ __pimp_mixer_mix_samples_asm:
mla r10, TEMP, VOLUME, r10
add SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
#ifndef IRQ_SAFE
ldrb TEMP, [SAMPLE_DATA, SAMPLE_CURSOR, lsr #12]
mla r11, TEMP, VOLUME, r11
add SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
stmia TARGET!, {UNROLL_RANGE}
#else
stmia TARGET!, {UNROLL_RANGE}
ldr r10, [TARGET]
ldrb TEMP, [SAMPLE_DATA, SAMPLE_CURSOR, lsr #12]
mla r10, TEMP, VOLUME, r10
add SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
str r10, [TARGET], #4
#endif
subs COUNTER, COUNTER, #1
bne .simple_loop
#ifndef IRQ_SAFE
ldr r4, =0x4000208 @ load address of REG_IME
ldr r5, .ime_store @ stash for later
str r5, [r4] @ write value to REG_IME
#endif
.ret:
@ clean return
mov r0, SAMPLE_CURSOR
......@@ -179,16 +218,16 @@ __pimp_mixer_mix_samples_asm:
#ifdef USE_BRESENHAM_MIXER
.bresenham_mixer:
str SAMPLE_DATA, [sp] @ stash away SAMPLE_DATA for later use
add SAMPLE_DATA, SAMPLE_DATA, SAMPLE_CURSOR, lsr #12
str SAMPLE_DATA, .sample_data_store @ stash away SAMPLE_DATA for later use
add SAMPLE_DATA, SAMPLE_DATA, SAMPLE_CURSOR, lsr #12 @ modify pointer so it points to the fist sample in frame
mov SAMPLE_CURSOR, SAMPLE_CURSOR, asl #20
mov SAMPLE_CURSOR_DELTA, SAMPLE_CURSOR_DELTA, asl #20
ldrb TEMP, [SAMPLE_DATA], #1
mul TEMP, VOLUME, sp
mul TEMP, VOLUME, TEMP
.bresenham_loop:
ldmia TARGET, {r4-r11}
ldmia TARGET, {UNROLL_RANGE}
add r4, TEMP, r4
adds SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
......@@ -225,18 +264,37 @@ __pimp_mixer_mix_samples_asm:
ldrcsb TEMP, [SAMPLE_DATA], #1
mulcs TEMP, VOLUME, TEMP
#ifndef IRQ_SAFE
add r11, TEMP, r11
adds SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
ldrcsb TEMP, [SAMPLE_DATA], #1
mulcs TEMP, VOLUME, TEMP
stmia TARGET!, {r4-r11}
stmia TARGET!, {UNROLL_RANGE}
#else
stmia TARGET!, {UNROLL_RANGE}
ldr r10, [TARGET]
add r10, TEMP, r10
adds SAMPLE_CURSOR, SAMPLE_CURSOR, SAMPLE_CURSOR_DELTA
ldrcsb TEMP, [SAMPLE_DATA], #1
mulcs TEMP, VOLUME, TEMP
str r10, [TARGET], #4
#endif
subs COUNTER, COUNTER, #1
bne .bresenham_loop
ldr sp, .stack_store @ restore stack pointer
ldr r0, [sp] @ restore the old sample data
#ifndef IRQ_SAFE
ldr r4, =0x4000208 @ load address of REG_IME
ldr r5, .ime_store @ stash for later
str r5, [r4] @ write value to REG_IME
#endif
ldr sp, .stack_store @ restore stack pointer
ldr r0, .sample_data_store @ restore the old sample data
@ calculate how the sample cursor changed
sub r0, SAMPLE_DATA, r0
......@@ -249,3 +307,96 @@ __pimp_mixer_mix_samples_asm:
bx lr
#endif
// target, sound_mix_buffer, samples, dc_offs
.clipper_jumptable:
.word .clip0
.word .clip1
.word .clip2
.word .clip3
.global __pimp_mixer_clip_samples
__pimp_mixer_clip_samples:
stmfd sp!, {r4-r12, lr} @ store all registers but parameters and stack
@ find how many samples to fixup
and r4, r2, #3
@ fixup, jump to the correct position
adr r5, .clipper_jumptable
ldr pc, [r5, r4, lsl #2]
.clip3:
ldr r4, [r1], #4
rsb r4, r3, r4, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
.clip2:
ldr r4, [r1], #4
rsb r4, r3, r4, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
.clip1:
ldr r4, [r1], #4
rsb r4, r3, r4, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
.clip0:
movs r2, r2, asr #2
beq .ret_clip @ if no more samples, return
@ proper unrolled loop (loads data in blocks)
.clip_loop:
ldmia r1!, {r4-r7}
rsb r4, r3, r4, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
rsb r4, r3, r5, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
rsb r4, r3, r6, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
rsb r4, r3, r7, lsr #8
cmps r4, #127
movge r4, #127
cmps r4, #-128
movle r4, #-128
strb r4, [r0], #1
subs r2, r2, #1
bne .clip_loop
.ret_clip:
@ return to caller
ldmfd sp!, {r4-r12, lr} @ restore all registers but parameters and stack
bx lr
......@@ -175,7 +175,8 @@ void __pimp_mixer_mix(pimp_mixer *mixer, s8 *target, int samples)
pimp_mixer_channel_state *chan = &mixer->channels[c];
if (NULL != chan->sample_data) __pimp_mixer_mix_channel(chan, sound_mix_buffer, samples);
}
dc_offs >>= 8;
dc_offs >>= 8;
__pimp_mixer_clip_samples(target, sound_mix_buffer, samples, dc_offs);
}
......@@ -32,7 +32,7 @@ typedef struct
void __pimp_mixer_reset(pimp_mixer *mixer);
void __pimp_mixer_mix(pimp_mixer *mixer, s8 *target, int samples);
u32 __pimp_mixer_mix_samples(s32 *target, u32 samples, const u8 *sample_data, u32 vol, u32 sample_cursor, s32 sample_cursor_delta);
void __pimp_mixer_clip_samples(s8 *target, s32 *source, u32 samples, u32 dc_offs);
extern "C" u32 __pimp_mixer_mix_samples(s32 *target, u32 samples, const u8 *sample_data, u32 vol, u32 sample_cursor, s32 sample_cursor_delta);
extern "C" void __pimp_mixer_clip_samples(s8 *target, s32 *source, u32 samples, u32 dc_offs);
#endif /* PIMP_MIXER_H */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment