{___________________________________________________________________________ LOOP.ASM ADSP-21020 EZLAB Circular Buffer Demonstration 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; m1=1; r6=1; { used is frequency mirroring } bit clr mode1 SRD1L|SRD1H|SRRFL|SRRFH; nop; wait: idle; 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; {__________________________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 playback; record: dm(i0,m1)=r4; { store one sample } r4=l0; r4=r4+1; { increment length } r5=32767; { max buffer size } r4=clip r4 by r5; l0=r4; { new length for circular buffer} rti; playback: r6=-r6; { used if in state 2 } r0=1; { used if in state 1 } bit tst ustat2 1; if tf r0=-r0; { if State 1 negate modifier } m1=r0; r4=dm(i0,m1); { get L & R sample } r3=lshift r4 by 16; { get right sample } bit tst ustat2 2; { if State 2 multiply every other } if tf r4=r4*r6 (ssi); { sample by -1 } if tf r3=r3*r6 (ssi); { sample by -1 } dm(out_audio_l)=r4; { output AD1849 value } dm(out_audio_r)=r3; { output AD1849 value } r4=btgl r4 by 31; { invert the sign bit for DAC } dm(dac_a)=r4; { output DAC value } pop sts; { for rev 0 silicon anomaly } push sts; rti; {_____________________Change Setup for the AD1849____________________________ Allows one to change the AD1849s setup from the default state using the FLAG and interrupt push buttons. Attributes that can be changed are: line or microphone input source, input gain, and the sample rate. Do not press the IRQ2 button too fast when changing the sample rate. The 2111 reboots and sets up the AD1849 each time the button is pressed, and will get confused if the button is pressed when this is happening. Initialization: flag0 must be setup as an input. irq2 must be enabled. ustat1 bits 0 and 1 are reserved to tell the irq2 if in setup mode. Operation: Press and hold button Press and release button Release button to enter the setup routine Push button to toggle between Line and Microphone input Push button to go to the next state Push button to change the input gain, (8 levels) Push button to go to the next state Push button to change the sample rate, (16 frequencies) Push button to exit the setup routine Microphone Input Gain Default: level 4 => 20dB + level*2*1.5dB = 34dB Line Input Gain Default: level 0 => level*2*1.5dB = 0dB Sample Rates: ( 0) 8 ( 8) 5.5125 ( 1) 16 (default) ( 9) 11.025 ( 2) 27.42857 (10) 18.9 ( 3) 32 (11) 22.05 ( 4) N/A (12) 37.8 ( 5) N/A (13) 44.1 ( 6) 48 (14) 33.075 ( 7) 9.6 (15) 6.615 ___________________________________________________________________________} setup_1849: bit clr ustat1 2; { clear the setup flag state } if not flag0_in jump exit_setup; yes_setup: if flag0_in jump yes_setup; { wait for flag button release } bit set ustat1 2; { set the setup flag } bit clr ustat1 1; { clear the irq2 pressed flag } bit set mode1 IRPTEN; { enable global int.} {....Set the AD1849 input source....} input_wait: bit tst ustat1 1; if tf jump set_input; if flag0_in jump level_state; jump input_wait; set_input: r0=dm(control_0); { read from 2111 hip } r0=btgl r0 by 30; { toggle between line and mic } r1=0xc0ffffff; { mask line gain default } r2=0x24000000; { mask mic gain default } btst r0 by 30; if sz r0 = r0 and r1; { its line so gain is 0 } if not sz r0 = r0 or r2; { its mic so gain is 4 } dm(control_0)=r0; { write to 2111 hip } bit clr ustat1 1; { reset the irq2 pressed flag } jump input_wait; {....Set the AD1849 input level....} level_state: if flag0_in jump level_state; { wait for release of flag button } bit clr ustat1 1; level_wait: bit tst ustat1 1; if tf jump set_level; if flag0_in jump sample_state; jump level_wait; set_level: r0=dm(control_0); { read from 2111 hip } {....bump up lg....} r1=lshift r0 by -24; r1=r1+1; { increment lg } r2=0x00000007; { modulo 8 for lg } r1=r1 and r2; r2=0xf8ffffff; { clear lg field } r0=r0 and r2; r0=r0 or lshift r1 by 24; {....bump up rg....} r1=lshift r0 by -27; r1=r1+1; { increment rg } r2=0x00000007; { modulo 8 for rg } r1=r1 and r2; r2=0xc7ffffff; { clear rg field } r0=r0 and r2; r0=r0 or lshift r1 by 27; {....output to 2111 hip....} dm(control_0)=r0; bit clr ustat1 1; { reset the irq2 pressed flag } jump level_wait; {....Set the AD1849 sample rate....} sample_state:if flag0_in jump sample_state; { wait for release of flag button } bit clr ustat1 1; sample_wait: bit tst ustat1 1; if tf jump set_sample; if flag0_in jump exit_setup; jump sample_wait; set_sample: r0=dm(control_1); { read from 2111 hip } r0=lshift r0 by -16; r0=r0+1; { increment sample rate } r0=lshift r0 by 16; r1=0x000f0000; { modulo 16 } r0=r0 and r1; dm(control_1)=r0; { output sample rate to 2111 hip } bit clr ustat1 1; { reset the irq2 pressed flag } jump sample_wait; exit_setup: if flag0_in jump exit_setup; { wait for release of flag button } bit clr ustat1 2; { clear the setup flag } rts; nop; nop; {___________________________________________________________________________} .ENDSEG;