{___________________________________________________________________________ DEMO.ASM This program is the top-level of the 21k EZ-lab board demo routines. ____________________________________________________________________________} #include "demo.h" {_____________________External Variables and Routines_______________________} .EXTERN spectral; {Routine that runs spectral demo} .EXTERN ispec; {Routine that does an inverse FFT} .EXTERN intffir; {Routine that an interactive FFIR} .SEGMENT/PM pm_sram; .ENDSEG; .SEGMENT/DM dm_sram; {variables for DAC output service routine} .VAR adacbuf[PNTS/2+1+2]; {Buffer for DAC A}{two extra bins } .VAR bdacbuf[PNTS/2+1+2]; {Buffer for DAC B}{ are dummies } {variables for the hip interface routine} .VAR inleft[PNTS]; {audio left channel input buffer} .VAR inright[PNTS]; {audio right channel input buffer} .VAR outleft[2*PNTS]; {audio left channel output buffer} .VAR outright[2*PNTS]; {audio right channel output buffer} .VAR inbufptr; {tracks pntr to inbuffer for intffir} .VAR aadc_dat; {ADC A current data in} .VAR badc_dat; {ADC B current data in} {variables for the cursor routine} .VAR curbuffer; .VAR nextbuffer; .VAR curbin; .VAR orgvalue; .VAR xtable[16]= -16, -8, -4, -4, -2, -1, 0, 1, 2, 2, 4, 4, 4, 8, 8, 16; .GLOBAL adacbuf; .GLOBAL bdacbuf; .GLOBAL inleft; .GLOBAL inright; .GLOBAL inbufptr; .GLOBAL outleft; .GLOBAL outright; .GLOBAL aadc_dat; {ADC A current data in} .GLOBAL badc_dat; {ADC B current data in} .GLOBAL curbuffer; .GLOBAL nextbuffer; .GLOBAL curbin; .GLOBAL orgvalue; .ENDSEG; {These are the 2111 hip port addresses} .SEGMENT/DM hip_regs; .PORT hdr0; {in left audio} .PORT hdr1; {in right audio} .PORT hdr2; {out left audio} .PORT hdr3; {out right audio} .PORT control_0; { AD1849 input source, and gain } .PORT control_1; { AD1849 sample rate } .ENDSEG; {Addrs for the AD7769 8-bit ADC/DAC} .SEGMENT/DM adc_a; .PORT adc_a; .ENDSEG; .SEGMENT/DM adc_b; .PORT adc_b; .ENDSEG; .SEGMENT/DM dac_a; .PORT dac_a; .ENDSEG; .SEGMENT/DM dac_b; .PORT dac_b; .ENDSEG; {______________________reset service routine______________________} .SEGMENT/PM rst_svc; { program starts at the reset vector } PMWAIT=0x0021; {pgsz=0,pmwtstates=0,intrn.wtstates only} DMWAIT=0xa421; {pgsz=0,dmwtstates=0,intrn.wtstates only} {except DM bank2 has 2 waitstates} bit set mode2 0x10; {cache init workaround} nop; read cache 0; bit clr mode2 0x10; call setup_1849; jump start; .ENDSEG; {_____________________DAC output service routine_____________________} .SEGMENT/PM tmzh_svc; jump dac_rnt (db); bit set mode1 SRRFH|SRD1H; {set alt DAG 4-7, R(8-15) registers} bit clr mode1 BR0; {make sure we are not bit reversing } .ENDSEG; {______________________2111 hip service routine______________________} .SEGMENT/PM irq3_svc; jump hip_rnt (db); bit set mode1 SRRFL|SRD1L; {set alternate DAG 0-3, R(0-7) registers} bit clr mode1 BR0; {make sure we are not bit reversing } .ENDSEG; {__________________Interrupt button service routine__________________} .SEGMENT/PM irq2_svc; bit tst ustat2 2; { test if AD1849 setup mode is enabled } if not tf jump skip_setup; { for AD1849 setup } bit set ustat2 1; { for AD1849 setup } skip_setup: { label for AD1849 setup } bit set ustat1 IRQED; {flag irq2 pressed} if not flag0_in rti; rti (db); bit set ustat1 FLIRQ; {also flag if flag0 at same time} nop; .ENDSEG; .SEGMENT/PM pm_sram; start: imask =IRQ3I|IRQ2I|TMZHI; {unmask irq3,irq2,timer.high} tperiod =DACPER; {period of DAC output} tcount =1000; mode1 =ALUSAT; {enable ALU saturation} mode2 =0x0007002f; {edge-sen. interrupts, enable timer, flag1-3 out} {perform init for dac_rnt} bit set mode1 SRD1H|SRRFH; {set alternate DAG 4-7, R(8-15) registers} nop; b4=dac_a; b5=dac_b; b6=adacbuf; {set up buffers} b7=bdacbuf; l4=0x0; l5=l4; l6=PNTS/2+1+2; {two extra bins as dummies} l7=PNTS/2+1+2; {two extra bins as dummies} m7=1; bit clr mode1 SRD1H|SRRFH; {back to regular DAG 4-7, R(8-15) registers} nop; {perform init for hip_rnt} bit set mode1 SRD1L|SRRFL; {set alternate DAG 0-3, R(0-7) registers} nop; {set up buffers} b0=inleft; b1=inright; b2=outleft; b3=outright; l0=PNTS; l1=l0; l2=2*PNTS; l3=l2; m0=1; m2=0; r2=PNTS/2; r3=PNTS; bit clr mode1 SRD1L|SRRFL; {back to regular DAG 0-3, R(0-7) registers} nop; do demos until forever; ustat1=0x00000000; {clears status of routines} do wait1 until not flag0_in;{wait for flag0 to be depressed} bit set astat FLG1; {signal no demo} bit set astat FLG2; wait1: bit set astat FLG3; do wait2 until flag0_in; {waits for flag0 to start demos} lcntr=0x5f5e10; do (pc,1) until lce; if flag0_in jump wait2 (la); bit tgl astat FLG1|FLG2|FLG3; wait2: if flag0_in jump espl (la); espl: IRPTL=0x0; {clear out interrupts} bit set mode1 IRPTEN; {enable interrupts} bit clr astat FLG2; {signal demo #0} bit clr astat FLG3; call spectral; bit clr astat FLG2; {signal demo #1} bit set astat FLG3; call ispec; bit set astat FLG2; {signal demo #2} bit clr astat FLG3; call intffir; nop; nop; demos: bit clr mode1 IRPTEN; {disable interrupts} {_________________________DAC output routine______________________________ Say the data in a dac buffer looks like: ||| |||| (a fourier spectrum) ||||| ||||| ||||| ||||||||||||| |||| |||| This routine will write the data to the DAC like: || || ||| || |||| || ||||| || ||||| ||||| || ||||||||||||| |||| |||| The spike at the beginning of the data is to be used as a trigger for the oscilloscope. The last two bins are dummies that are not displayed. Dag alternate reg defs: b4: addr of DAC A b5: addr of DAC B b6: addr of adacbuf b7: addr of bdacbuf i6: pointer to adacbuf i7: pointer to bdacbuf m7: 1 USTAT1 bits: 4: DAC A output enable 5: DAC B output enable ___________________________________________________________________________} dac_rnt: {if pntr at start of buf, we need to make decisions} r10=i6; r11=l6; r11=r11-1, r12=b6; r10=r10-r12, r8=dm(i6,m7); {read data from buffers and upd pntrs} comp(r10,r11), r9=dm(i7,m7); if eq jump zero; {at second dummy, output zeros} r11=r11-r10+CI-1; {CI=0} if eq jump trigger; {at first dummy, do the osc. trigger} outdac: bit tst ustat1 ENDAA; {only write to DACs if enabled in USTAT1} if tf dm(i4,0)=r8; {write to DAC A} bit tst ustat1 ENDAB; if tf dm(i5,0)=r9; {write to DAC B} pop sts; {workaround int stack pop anamoly} push sts; rti; {This also switches contexts since MODE1 pop} zero: tcount= TDLYLEN; {for delay after trigger} jump outdac (db); r8=0x00000000; {zero dac} r9=0x00000000; trigger: {since we finished forw. scan, } bit tst ustat1 LADC; if not tf jump do_b (db); bit tgl ustat1 LADC; r13=dm(adc_a); {get joystick data} do_a: jump trgcon (db); dm(aadc_dat)=r13; {store new data} dm(adc_b)=r13; {start ADC B conversion} do_b: call cursor (db); {do a call to the cursor routine now} dm(badc_dat)=r13; {store new data} dm(adc_a)=r13; {start ADC A conversion} trgcon: tcount= TRIGLEN; {for longer trigger} jump outdac (db); r8=0xff000000; {pound DAC for trigger} r9=0xff000000; {____________________________2111 hip service routine__________________________ This routine gets data from and puts data to the ADSP-2111. More specifically it: 1) grabs left/right audio data from the HDR0 and HDR1 on the 2111 2) grabs 2111 status information from HDR4 3) puts left/right proc. audio data into HDR2 and HDR3 Defined alternate DAG registers are: b0,i0: buffer and pointer to inleft b1,i1: buffer and pointer to inright b2,i2: buffer and pointer to outleft b3,i3: buffer and pointer to outright m0: 1 m2: 0 Defined alternate RF registers are: r2: half point of in buffers r3: half point of out buffers USTAT1 bits: 0,1: left, right output enable 2,3: left, right input enable 16: output buffer half filled flag 17: output buffer filled flag 18: input buffer half filled flag 19: input buffer filled flag ___________________________________________________________________________} hip_rnt: bit clr ustat1 0x0f0000; {clear buffer flags} {get data from hip} r0=dm(hdr0); r1=dm(hdr1); dm(i0,m2)=0x0; {initialize to zero first} dm(i1,m2)=0x0; bit tst ustat1 ENIAL; {if input enabled, write in the data} if tf dm(i0,0)=r0; bit tst ustat1 ENIAR; if tf dm(i1,0)=r1; modify(i0,1); {always update both pointers} modify(i1,1); dm(inbufptr)=i0; {set flags} r0=i0; r4=b0; r0=r0-r4; {find offset} if ne jump (pc,2); bit set ustat1 INBF; {zero offset =>flag buffer filled} comp(r0,r2); if ne jump (pc,2); bit set ustat1 INBH; {flag half buffer offset} {put data to the hip} r0=dm(i2,m0); r1=dm(i3,m0); bit tst ustat1 ENOAL; {if output enabled, write out to hip} if not tf jump (pc,2); dm(hdr2)=r0; bit tst ustat1 ENOAR; if not tf jump (pc,2); dm(hdr3)=r1; {set flags} r0=i2; r5=b2; r0=r0-r5; {find offset} if ne jump (pc,2); bit set ustat1 OUTBF; {zero offset =>flag buffer filled} comp(r0,r3); if ne jump (pc,2); bit set ustat1 OUTBH; {flag half buffer offset} pop sts; push sts; rti; nop; nop; {___________________________________________________________________________ cursor: This implements a cursor that can switch between two buffers via IRQ3 and permanently writes new values via FLAG0. This routine is triggered every ~1/15 second by the DAC routine. ____________________________________________________________________________} cursor: bit tst ustat1 DEMO_0; {if demo #0, ignore this routine} if tf rts; r12=b4; {save values of b4,i4,l4,i5} r13=i4; r8=r8-r8, r14=l4; {zero r8} b4=dm(curbuffer); i4=dm(curbin); l4=TAPS/2+1; {cursor range for demo #2} bit tst ustat1 DEMO_2; {if demo #2, never switch buffers} if tf jump scan_joy; demo1: {if demo #1, set range, check if buf switch} l4=PNTS/2+1; {demo #1 cursor range} dm(bdacbuf)=r8; {1st & last imaginary always zero} dm(bdacbuf+PNTS/2)=r8; {for demo #1} bit tst ustat1 IRQED; if not tf jump scan_joy; {if not IRQ3 flag, then goto scan joystick} bit clr ustat1 IRQED; {proceed to switch buffers} r8=dm(0,i4); {get current cursor y} r9=dm(orgvalue); {write back original data} dm(0,i4)=r9; r9=dm(curbuffer); r10=dm(curbin); r11=dm(nextbuffer); r10=r10-r9; {calculate offset} r10=r11+r10; {add offset to nexbuffer base addr.} dm(curbuffer)=r11; {save new values} dm(curbin)=r10; dm(nextbuffer)=r9; i4=r10; r9=dm(0,i4); dm(orgvalue)=r9; {store original value} dm(0,i4)=r8; {write new cursor position} b4=r12; {restore values of b4,i4,l4,i5} rts (db); i4=r13; l4=r14; scan_joy: i4=xtable; r8=dm(aadc_dat); {get x joystick value} r8=lshift r8 by -28; {look-up x-modifier} r15=r15-r15, m4=r8; {zero r15, load table look-up} new_y: r10=0xff; r11=0xe8; r8=dm(badc_dat); {get y joystick value} r8=lshift r8 by -24; {invert and clip value} r9=r10-r8; r8=clip r9 by r11; x_mod: r11=r15+1, r9=dm(m4,i4); {figure out modifiers} r10=abs r9, m4=r9; comp(r10,r11), m6=r15; if ne jump nodith; bit tgl ustat1 CDTH; {toggle cursor dither bit} bit tst ustat1 CDTH; {create one bit dither} jump new_x (db); if not tf m4=r15; if not tf r9=r15; nodith: r9=(r9+r15)/2; {mod=(table-value + zero)/2} r10=(r9+r15)/2, m4=r9; {cheap div 2} {m4 = full modifiers} r9=r9-r10, m6=r10; {m5 + m6 = m4, m6=m4/2 } new_x: m5=r9; i4=dm(curbin); r9=dm(orgvalue); {write back original data} r10=dm(0,i4); {get current cursor y} r10=lshift r10 by -24; if not flag0_in jump nwrt (db); {do not write to bin if not flag0} r10=(r8+r10)/2, dm(i4,0)=r9; r8=lshift r8 by 24; jump (pc,5) (db), r11=pass r8; {write to next bin (r11)} r10=lshift r10 by 24, r9=dm(i4,m5); {shift up averg., dummy read} dm(i4,m6)=r10; {if flag0, write to intermed. bin} nwrt: modify(i4,m4); {update i4 to the next bin} r11=dm(0,i4); {update orgvalue} wrtn: dm(orgvalue)=r11; update: dm(0,i4)=r8; {write new y to current cursor bin} dm(curbin)=i4; {write back curbin} l4=r14; {restore and return} rts (db); b4=r12; i4=r13; {restore value of i4} {_____________________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. ustat2 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 ustat2 2; { clear 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 ustat2 2; { set the setup flag } bit clr ustat2 1; { clear the irq2 pressed flag } bit set imask IRQ2I; { enable irq2 button } bit set mode1 IRPTEN; { enable global int.} {....Set the AD1849 input source....} input_wait: bit tst ustat2 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 ustat2 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 ustat2 1; level_wait: bit tst ustat2 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 ustat2 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 ustat2 1; sample_wait: bit tst ustat2 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 ustat2 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 ustat2 2; { clear the setup flag } bit clr ustat1 IRQED; {flag irq2 pressed} bit clr ustat1 FLIRQ; {also flag if flag0 at same time} rts; nop; nop; {___________________________________________________________________________} .ENDSEG;