{___________________________________________________________________________ DIREC.ASM Audio Directional Cue Simulator Simulates directional cues for stored samples by adding an interaural time delay (ITD). Used in conjunction with an experiment to see how well this simulation works. Demonstrates recording of speech and playback in a looped manner. Dynamic circular buffer sizing is used to set the length of the looped array. Up to 8 seconds of sound can be sampled. Playback data is also written to dac_a. Pressing IRQ2 also allows you to time reverse or to frequency mirror the recorded sample. Time reversal is accomplished by using a negative modifier in reading the circular buffer. Frequency reversal is done by inverting every other data sample. Operation: * Records speeech from left and right channel while flag0 is pressed * Plays back when flag0 is released * Press Reset to clear the buffer * Each Press of IRQ2 will switch between three states: (0) Normal Play and Record (1) Time Reverse the sample (2) Frequency Reverse the sample (mirror) To assemble this demo from scratch use the following commands: asm21k loop ld21k -a ezlab21k loop spl21k -a ezlab21k -ram -dm -pm -f B loop Author: 14-Feb-91, SLC Analog Devices Inc. DSP Division ____________________________________________________________________________} { ADSP-21020 System Register bit definitions } #include "def21020.h" {___________________________________________________________________________} .SEGMENT/DM dm_sram; .VAR buffer[10]; {do not declare all 32k so it will load faster } .ENDSEG; .SEGMENT/DM hip_regs; .PORT in_audio_l; { ADSP-2111 HDR0 = mic input } .PORT in_audio_r; { ADSP-2111 HDR1 } .PORT out_audio_l; { ADSP-2111 HDR2 = speaker output } .PORT out_audio_r; { ADSP-2111 HDR3 } .PORT control_0; { ADSP-2111 HDR4 } .PORT control_1; { ADSP-2111 HDR5 } .ENDSEG; .SEGMENT/DM dac_a; .PORT dac_a; .ENDSEG; .SEGMENT/DM dac_b; .PORT dac_b; .ENDSEG; .SEGMENT/DM adc_b; .PORT adc_b; .ENDSEG; {___________________________________________________________________________} .SEGMENT/PM rst_svc; { Reset Vector } call init_21k; call setup_1849; jump main; .ENDSEG; {___________________________________________________________________________} .SEGMENT/PM irq2_svc; { Push Button Interrupt } bit tst ustat1 2; { test if AD1849 setup mode is enabled } if not tf jump skip_setup; { for AD1849 setup } bit set ustat1 1; { for AD1849 setup } rti; { for AD1849 setup } skip_setup: { label for AD1849 setup } jump irq2_asserted; .ENDSEG; {___________________________________________________________________________} .SEGMENT/PM irq3_svc; { Audio I/O Interrupt } jump irq3_asserted (db); bit set mode1 SRD1L|SRD1H|SRRFL|SRRFH; { use all secondary registers} nop; .ENDSEG; {___________________________________________________________________________} .SEGMENT/PM tmzh_svc; { Timer Interrupt } jump timer_hi_prior; .ENDSEG; {___________________________________________________________________________} .SEGMENT/PM pm_sram; main: r0=0x00000100; { data to circulate through LEDs} ustat2 = 0; { starting state = 0 } bit set imask IRQ3I; bit set mode1 IRPTEN; { enable global int.} bit set mode2 TIMEN; { timer on! } bit set mode1 SRD1L|SRD1H|SRRFL|SRRFH; nop; b0=buffer; l0=1; bit clr mode1 SRD1L|SRD1H|SRRFL|SRRFH; nop; wait: r0 = dm(adc_b); r0 = 200; r0 = ashift r0 by -5; { scale down r0 to a value from 0-16 } i0 = buffer; { i0 is start of buffer } i1 = r0; { start of buffer + offset } jump wait; {___________________________initialize the chip___________________________} init_21k: pmwait =0x00001c21; { pmwtstates=0,sw.wtstates only} dmwait =0x0070a421; { bank2_dmwtstates=1,sw.wtstates only} tperiod =0x004c4640; { timer interrupt at 5 Hz } tcount = tperiod; irptl =0; bit set mode2 0x10; nop; read cache 0; bit clr mode2 0x10;{clr cache} {irq2&3 enable, timer enable high priority} bit set imask TMZHI|IRQ2I; {irq2&3 edge sens, flag 1&2&3 outputs} bit set mode2 IRQ2E|IRQ3E|FLG1O|FLG2O|FLG3O; bit clr astat FLG1|FLG2|FLG3; { clear flag LEDs } rts; {__________________________Timer Interrupt__________________________________} timer_hi_prior: pop sts; { get ASTAT from stack, pushed there by IRQ } bit tgl astat FLG1; push sts; { restore stack so effect happens after rti } r3=dm(adc_b); { Read last ADC-B input } dm(adc_b)=r3; { write to ADC-B to start conversion } dm(dac_b)=r3; { output DAC-B value } rti; {__________________________IRQ2 Interrupt Vector____________________________} { Switch between 3 states and display the state on Flag 2 and 3 } irq2_asserted: { Change State } r0=ustat2; { get current state } r0=r0+1; { Increment state } r1=3; comp(r0,r1); if eq r0=r0 xor r0; { clear if going back to state 0 } ustat2=r0; { Reverse state for display on LEDs} r1=lshift r0 by -1; r0=bclr r0 by 1; r1=r1 or lshift r0 by 1; pop sts; { get ASTAT from stack, pushed there by IRQ } bit clr astat FLG2|FLG3; r0=astat; r0=r0 or lshift r1 by 21; astat=r0; push sts; { restore stack so effect happens after rti } rti; nop; nop; {__________________________IRQ3 Interrupt Vector____________________________} irq3_asserted: r3=dm(in_audio_r); { get AD1849 right channel } r4=dm(in_audio_l); { get AD1849 left channel } r4=lshift r4 by -16; { zero the lower 16 bits } r4=lshift r4 by 16; r4=r4 or lshift r3 by -16; { 16 bit L & R > 32 DM } if not flag0_in jump play; { record if button pressed } record: dm(i0,1)=r4; { store one sample } r4=l0; r4=r4+1; { increment length } r5=32767; { max buffer size } r4=clip r4 by r5; { limit length to max } l0=r4; { new length for circular buffer} rti; nop; nop; play: r5 = dm(i2,1); { delayed start } r6 = dm(i3,1); { undelayed } dm(out_audio_l)=r5; { output AD1849 value } dm(out_audio_r)=r6; { output AD1849 value } pop sts; { for rev 0 silicon anomaly } push sts; rti; .ENDSEG