IUBio Biosequences .. Software .. Molbio soft .. Network News .. FTP

hearing aid research ideas

marzalek mikem*noSpam* at sr.hp.com
Sat Feb 14 14:25:40 EST 1998


My name is Mike Marzalek, and I have lurked in this usenet group for a
couple
years while I did hearing aid research in my spare time.  I presented two
papers at the 1995 "Hearing Aid Research and Development Conference".

I no longer have the time to pursue this interest, have documented my work
and am making it public domain.  If anyone in the group can use this work,
or know of anyone who can, then great.

As audiologists, you may find it interesting to see the direction that
hearing aids may be going in the future.

My name is Mike Marzalek and I am a Research and Development
engineer at Hewlett Packard, and have been for twenty nine
years.  I have a BSEE from UC Berkeley, an MSEE from Stanford,
and have nine patents in the electronics field.

I have built a hearing aid that achieves infinite compression
yet it does not reduce intelligibility because it uses slow gain
time constants which do not distort the temporal envelope.  This
would greatly benefit those with little residual hearing dynamic
range.

It is able to do this because it is a digital hearing aid, and
it keeps a 53 mSec circular buffer of the input speech signal
which it analyzes before outputting the processed speech to the
user.

I have ported the code from my hearing aid, to the Texas
Instruments TMS320C50 DSK development kit to make it easy to
evaluate the processing algorithms.  It is available for $99
>From most electronics distributors such as Wiley.

This aid could be self fitting.  It has the ability to create
arbitrary frequency and amplitude sine waves for hearing
threshold testing.  During a fitting, the microphone is not
needed, so the user could clap their hands to signify hearing a
tone and to go to the next frequency.  By doing hearing testing
in place with the aid, the value of real ear measurements
becomes diminished.

Another feature is limiting the max gain so that the quietest
speech intervals stay 6 dB below the target sound level.

If you have any questions, or if anyone you pass this along to
would like any assistance, please feel free to contact me.
A listing of the code follows.

          Mike Marzalek
          mikem at sr.hp.com


****************************************************************
*  MODULE NAME: HEAR.ASM    1/27/97 Marzalek
*
*  Any ideas or code in this document are public domain and
*  may be used freely.  Mike Marzalek 2/8/98
*
*  DESCRIPTION: Hearing aid processing code.  It can either run
*    on a stock Texas Instruments TMS320C50 DSK development board
*    available for $99 from most electronics distributors eg Wiley
*    or on a highly modified DSK that has been converted to a
*    hearing aid.  Setting the compile option "STOCK" determines
*    which.
*
*  OVERVIEW: The C50 DSP has a 20 MHz clock, the adc interrupts at
*    12 kHz, so 6 kHz max frequency without aliasing.
*    640 samples (53 mSec) are kept in a circular buffer and
*    "processed" before output.  This allows processing the output
*    data knowing what the next 53 mSec of input is.  As opposed to
*    reacting to the input after it has arrived, I can see the input
*    up to 53 mSec into the "future".  This permits interesting
*    processing.
*
*    As data is put into the circular buffer, the max value over
*    each group of 20 samples is determined and this is kept in a
*    peaks circular buffer.  At the conclusion of each 20 samples, the
*    peaks array is analyzed to determine at what rate to modify
*    the gain while the next 20 samples are being taken and 53 mSec
*    old data is being output.
*
*    The current implementation utilizes infinite compression.  All
*    input (averaged over 53 mSec) will be heard at the same level.
*    High compression is difficult to implement because of the
*    distortion it causes in the temporal envelope.  This design
*    does not have that problem because the gain changes slowly
*    over the 53 mSec it has before the current adc samples are output.
*    Lesser compression would be easy to implement.
*
*    The following example shows how the new algorithm compares to
*    the AGC/compression in current hearing aids.  Note that the
*    envelope on the AGC waveform exceeds the target a lot and
*    the gain then changes rapidly to recover, causing large distortion.
*
*    You'll probably need to insert spaces & tabs to line up what was
*     fixed pitch font graphics.
*
*
*   ____________                         ____
*         |            |                       |
*       __|            |_______________________|
*    Input
*             __              _______________________
*  |            |                       |
*  |____________|                       |____
*
*
*
*
*               |\                                   |\
*       __| \__________                    ____| \__
*                      |          ____-----
*                      |_____-----
* Standard AGC
*                             _____
*                      |     -----____
*       __   __________|              -----____   __
*               | /                                  | /
*               |/                                   |/
*
*
*
*   ____________         _______         __
*         |            |    __--       --__    |
*       __|            |__--               --__|
*  This design
*             __              __                   __
*  |            |  --__           __--  |
*  |____________|      --_______--\     |__
*                                               \
*                                                 \gain drops in
anticipation
*
*
*    I keep track of the quietest sound input and limit the gain to
*    keep this level 6 dB below the target level.
*
*    An external anti-alias filter should be used to limit max input
*    frequency to 6 kHz.  Though things work pretty well without it.
*
*    I apologize for the readabllity of the code.  It wasn't intended
*    to be seen in this unfinished state.
*
*    There are various debugging tools built into the code.  They
*    work well with a code developer from GO DSP in Canada.  I think
*    TI now sells it for them.  It was $69.
*
*    If compile option BIGDEBUG is set, I keep a half second circular
*    buffer where I track one variable as positive only in even
*    locations, and a different variable as negative only in odd
*    locations.  I can display this graphically to monitor opertaion.
*
*    I can generate an arbitrary frequency and amplitude sine wave
*    and inject it at the input for processing testing, or at the
*    output for an in patient hearing threshold test.  For the
*    hearing test, the input is unused, and so the patient could
*    clap their hands to indicate hearing the tone and to go to
*    the next frequency.  Since the hearing test is administered
*    by the hearing aid, the value of real ear measurements is
*    diminished.  It is left as an exercise for the student how
*    to handle requests such as reducing high frequency energy.
*
*    I can also square wave modulate the sine wave for testing
*    the processing.  Noise could be added if desired.
*
*    There is currently no patient dependent frequency shaping,
*    this is easy to add.
*
* Load/Run:
*    To run the code using the TI tools:
*     from DOS
*     >DSK5D
*     >M
*     >R
*     >ST1=1BC
*     >L
*     >D
*     >HEAR.DSK
*     >X
*     >G
*
*   To assemble the code
*     >DSK5A HEAR
*
* Conventions:
*   coeff & pgm must be in different blocks, Dn are in DARAM
*   leave PM shift bits at reset value of zero
*   overflow saturation mode on - no wrap
*   sign extension mode on
*   ldp set to 2 always - 100h thru 17Fh
*
* TLC2543 ADC (not stock):
*   must be given a hi_reset pulse initially
*   outputs a 12 bit word as a 12 bit word is entered
*   the 12 bit input word is a 16 bit word hardware truncated
*   during the truncation, the 12 MSB's are kept (+-32752)
*   output and input are MSB first
*   adc output is binary 2's complement (+- 2047 << 4=+-32752)
*   run at 12 kHz (max spec 100 kHz)
*   max data clock rate 4.1 MHz, I have to run 5 MHz - works!
*
* To go mobile, set the MOBILE define, 1st yank AC, then RS232
*
*
* Memory map:
*   00h -  60h  memory mapped reg's
*   60h -  80h  reserved by kernal
*  100h - 17Fh  daram - ldp #2 default
*  180h - 19Fh  peak array (different ldp)
*  1A0h - 4FFh  available daram (different ldp)
*  500h - 800h  reserved by kernal
*  800h - 980h  interrupt vectors & reserved by kernal
*  A00h -20FFh  user space
*   if BIGDEBUG, user A00-CFF, debug ring buf D00-23FF (size 16FF, 5887)
* 2100h -23FFh  debug ring buffer
* 2400h -2BFFh  input ring buffer
*
*
* AR's:
*   AR0 used for "only process every nth sample" (AR0=0)
*   AR1 used for ADC in circular buffer
*   AR2 used for sine gen
*   AR2 used for digital filter
*   AR2 used as flag to process ADC input
*   AR2 used to get max of peak array
*   AR3 used for debug circular buffer
*   AR4 used for peak array
*
* Time constants:
*   peak determined real time
*   everything else done @ skip rate set by AR0
*
* Labels 8 char max - will crash if not heeded

*
*   There are 1667 total clocks (20 MHz/12 kHz)
****************************************************************
         .mmregs

CWMIC    .set 0
CWRCVR  .set 0
DISPVAR  .set 1
BIGDEBUG .set 1
SAFETY   .set 1
SQMOD    .set 1 ; square wave AM modulate sin gen
BGLIMIT  .set 1 ; limit gain for background level
MOBILE   .set 0
STOCK    .set 1 ; stock DSK development board with AIC
FIXDGAIN .set 0

CBUFSIZE .set 640 ; 53 mSec @ 12 kHz
SKIP_CNT .set 20 ; 1.67 mSec (300 Hz has pos or neg peak)
MIN_PKS  .set 15 ; new min pk only after num peak intvls
MIN_SHFT .set 1 ; max gain @ minInPk << MIN_SHFT
OUTLIMT  .set 32700 ; positive limit if SAFETY set
OUTLIMTN  .set -32700 ; negative limit if SAFETY set
GAINSHFT .set 10 ; sets max gain allowed (16 max)
    ; 0x7FFF is max outMult
    ; outTgt/0x7FFF << 16-GAIN_SHIFT is min input

 .ds 0100h  ; DARAM
DO_lp  .word 0 ; input 1750 lowpass
D1_lp  .word 0
D2_lp  .word 0
D3_lp  .word 0
D4_lp  .word 0

dummy1   .word 0 ; gets zapped by MACD
spareCnt .word 0 ; # of spare clocks per cycle
minSpare .word 0 ; min # of spare clocks per cycle

outRight  .word 01800h
outLeft  .word 0E800h
adcData  .word 0

inReg  .word 0FFFFh
inMux  .word 2200h

phase    .word 0 ; for sin gen
dPhase     .word 7 ; for sin gen 1 -> 47 Hz, 7 -> 328 Hz
amShift  .word 0 ; for square AM modulation of sin gen
LTavgInh  .word   0  ; DC term 32 bits
LTavgInl   .word   0
LTavgIn  .word   0 ; DC term 16 bits
peakIn  .word   1
outTgt  .word 20000
outMult  .word 0
dOutMult .word 0

minInPk  .word 0
inTgt  .word 7FFFh
minCtr  .word 0
newMinPk .word 0
pkSave   .word 0
lastPk  .word 0
noInptLP .word 0
deBounce .word 0
debugOut .word 0


****************************************************************
*   Set up the ISR vector
****************************************************************
 .if STOCK
 .ps 080Ah
rint: B TIMERSTK ; 0x80A rcvr interrupt  -  stock
xint: B XMITINT  ; 0x80C xmit interrupt  -  stock
 .else
 .ps 0808h
tint: B TIMER  ; 0x808 timer interrupt - !stock
 .endif
*
******************************************************************
* TMS32C05X INITIALIZATION
*
******************************************************************
 .ps 0a00h
 .entry
START: SETC INTM  ; Disable interrupts
 LDP #0  ; Set data page pointer
 OPL #08B7h,PMST ;
 B CONT1

NC4  .word 4096 ; numerator 1750 lowpass
NC3  .word 16384
NC2  .word 24576
NC1  .word 16384
NC0  .word 4096

DC4  .word -3402 ; denominator 1750 lowpass
DC3  .word 13311
DC2  .word -22616
DC1  .word 19704

SINTAB0  .word  402  ; sin table - stores 64 values over 90 deg
SINTAB1  .word  1206
SINTAB2  .word  2009
SINTAB3  .word  2811
SINTAB4  .word  3612
SINTAB5  .word  4410
SINTAB6  .word  5205
SINTAB7  .word  5998
SINTAB8  .word  6786
SINTAB9  .word  7571
SINTAB10 .word  8351
SINTAB11 .word  9126
SINTAB12 .word  9896
SINTAB13 .word  10659
SINTAB14 .word  11417
SINTAB15 .word  12167
SINTAB16 .word  12910
SINTAB17 .word  13645
SINTAB18 .word  14372
SINTAB19 .word  15090
SINTAB20 .word  15800
SINTAB21 .word  16499
SINTAB22 .word  17189
SINTAB23 .word  17869
SINTAB24 .word  18537
SINTAB25 .word  19195
SINTAB26 .word  19841
SINTAB27 .word  20475
SINTAB28 .word  21096
SINTAB29 .word  21705
SINTAB30 .word  22301
SINTAB31 .word  22884
SINTAB32 .word  23452
SINTAB33 .word  24007
SINTAB34 .word  24547
SINTAB35 .word  25072
SINTAB36 .word  25582
SINTAB37 .word  26077
SINTAB38 .word  26556
SINTAB39 .word  27019
SINTAB40 .word  27466
SINTAB41 .word  27896
SINTAB42 .word  28310
SINTAB43 .word  28706
SINTAB44 .word  29085
SINTAB45 .word  29447
SINTAB46 .word  29791
SINTAB47 .word  30117
SINTAB48 .word  30424
SINTAB49 .word  30714
SINTAB50 .word  30985
SINTAB51 .word  31237
SINTAB52 .word  31470
SINTAB53 .word  31685
SINTAB54 .word  31880
SINTAB55 .word  32057
SINTAB56 .word  32213
SINTAB57 .word  32351
SINTAB58 .word  32469
SINTAB59 .word  32567
SINTAB60 .word  32646
SINTAB61 .word  32705
SINTAB62 .word  32745
SINTAB63 .word  32765


***************** Timer Interrupt Service Routine ***************

 .if STOCK
 .else
TIMER:
 SACL spareCnt,0
 SUB minSpare
 LACC spareCnt
 XC 1,LT
 SACL minSpare,0
 LACC outLeft
 SAMM 50h
 LAMM 50h  ; read switches - takes 2 reads to settle
 LAMM 50h
 SACL inReg
 LACC outRight
 SAMM 50h

 LAMM DRR  ; get last adc conversion
 SACL adcData

  LACC inMux  ; select user's mux choice
*  LACC inMux  ; select user's mux choice
* LACC #0200h  ; select A0 (8 bit value << 9 - loses msb)
*  LACC #2200h  ; select A1 (8 bit value << 9 - loses msb)
*  LACC #4200h  ; select A2 (8 bit value << 9 - loses msb)
*  LACC #6200h  ; select A3 (8 bit value << 9 - loses msb)
*   LACC #8200h  ; select A4 (8 bit value << 9 - loses msb)
 SAMM DXR  ; start next ADC conversion

 LAR AR2,#1  ; flag to process ADC input
 RETE


*
******************************************************************
*  DESCRIPTION: This routine initializes the ADC
******************************************************************
*
ADCINIT:
 SPLK #20h,TCR ; To generate 12 kHz for
 SPLK #1667,PRD ; sample clock
 MAR *,AR0
 LACC #0038h  ; Non continuous mode
 SACL SPC  ; FSX as input
 LACC #00F8h  ; 16 bit words
 SACL SPC

 OPL #0837h,PMST ; make address lines visible
 LDP #1FFh  ; set adc reset hi by writing to big adrs
 RPT #10000  ; and taking it low after 10000 cycles
 LACC dummy1  ; (.5ms at 50ns)
 OPL #08B7h,PMST ; make address lines invisible
 RET   ;
 .endif
******************* continue setup **********************************

CONT1:
 SETC OVM  ; overflow saturation set - no wrap
 SETC SXM  ; sign extension mode on

 ZAP   ; set up 7 I/O wait states for DAC's
 SAMM PDWSR
 LACC #0FFFFh
 SAMM IOWSR
 LACC #4
 SAMM CWSR

 LACC #2400h  ; setup input circ buffer
 SAMM CBSR1
 SAMM AR1
 SAMM ARCR
 ADD #CBUFSIZE,0
 SAMM CBER1
 SPLK #9,CBCR  ; circ #1, AR1 - circ2 off

 .if BIGDEBUG
 LACC #0D00h
 .else
 LACC #2100h  ; setup test circ buffer
 .endif
 SAMM CBSR2
 SAMM AR3
 .if BIGDEBUG
 ADD #16FFh,0
 .else
 ADD #CBUFSIZE,0
 .endif
 SAMM CBER2


 SPLK #0B9h,CBCR ; circ #1, AR1 - circ2 on, AR3

 SPLK #180h,AR4 ; peak array pointer

 .if STOCK
 LACC #22h
 SAMM IMR  ; need xmit int + rs232 intrpt
 CALL ADCINSTK ; initialize ADC and enable interrupts
 .else
 LACC #2
 SAMM IMR  ; only rs232 intrpt
 CALL ADCINIT  ; initialize ADC and enable interrupts
 .endif
 LAR AR0,#0


 CLRC OVM  ; OVM = 0
 SPM 0  ; PM = 0
 LACC #0Ah  ; timer & rs232 ints only
 .if STOCK
 LACC #12h  ; rcvr & rs232 ints only
 .endif
 SAMM IMR

 LDP #spareCnt  ; Set data page pointer
 MAR *,AR2

 .if MOBILE
 LACC #8h
 SAMM IMR  ; timer intrpt only - kill the kernal
 CLRC XF
 .endif
 CLRC INTM  ; enable intrpts

 B       WAIT
;------- end of setup ----------;

;
; PROCESS ADC INPUT ********************************************
;
PROCESS:
 LACC adcData  ; get ADC data

 .if CWMIC
 CALL sinGen
 BSAR 4
 SACL adcData
 .endif

 B NOLP

 LACC noInptLP ; locks up at 4 kHz
 BCNDD NOLP,NEQ
 LACC adcData

 SACL dummy1
 LACC dummy1,10

 MAR *,AR2
 ZPR   ; 1750 lowpass**************************
 LAR AR2,#D4_lp
 RPT #3  ; do denom
 MAC DC4,*-
 APAC   ; final accum
 SACH *,3  ; save D[0], denom coeff are mult by 8192
    ; so divide D[0] by 8192(=acc*8/2^16)


 ADRK #4  ; now do the numerator
 RPTZ 4  ; assembler bug, no # allowed
 MACD NC4,*-
 LTA *,AR1

 BSAR 15  ; divide by 65536
 BSAR 1
 SACL adcData  ; end low pass****************************

NOLP:

 SUB LTavgIn  ; subtract off DC
 SACB
 LACC #7FFFh
 CRLT
 LACC #8001h
 CRGT


 MAR *,AR1  ; store ADC to circ buf
 SACL *+,0,AR0

 .if DISPVAR ;***********************************************************
 SACL dummy1  ; save off ADC
 MAR *,AR3

 LAMM AR3  ; odd or even?
 AND #1
 BCND EVEN,EQ
 LACC dummy1
 SACL pkSave
 LACC outMult
 B CONT3

EVEN: LACC debugOut
 ABS
 NEG

CONT3:
 SACL *+,0,AR0
 LACC dummy1
 .endif ;************************************************************

 ABS   ; test for new peak
 SACB
 LACC peakIn
 CRGT
 SACL peakIn

 BANZ  DOOUTPUT,*-,AR1  ; skip counter > 0?


NORMSKP:;******************begin skip = 0******************************

 LACC LTavgInh,16 ; compute DC
    ; compute 64 * long term avg (defined as LTav)
    ;  = LTav+#-LTav/64
    ;   approx by  LTav+# - (LTav+#)/64
    ; get 32 bit long term average
 OR   LTavgInl
 ADD adcData
 SACB
 BSAR 6
 EXAR
 SBB
 SACH LTavgInh
 SACL LTavgInl
 BSAR 6
 SACL LTavgIn


 LAR AR0,#SKIP_CNT ; load skip counter

 LACL inReg  ; handle buttons
 AND #0C000h,0
 XOR #0C000h,0

 SACB
 LACC deBounce
 SUB #1
 XC 1,GT
 SACL deBounce
 BCND CONT2,GT
 LACB

 BCND CONT2,EQ ; is a switch down?

 AND #4000h,0 ; which switch?
 BCND SWITCH2,NEQ

 LACC #500
 SACL deBounce

 LACC inMux
 ADD #2000h,0
 SACL inMux
 SUB #6200h,0  ; max allowed
 LACC #200h
 XC 1,C
 SACL inMux

 LACC #10000
 SACL peakIn

 B CONT2

SWITCH2:
 LACC #500
 SACL deBounce

 LACC noInptLP
 XOR #1
 SACL noInptLP


CONT2:

SKIPZN:;***********begin skip ctr = 0, peak<hiTgt**********************

    ; make slow tweak to inTgt

 LACC minInPk  ; take care of min peak stuff
 ADD #1
 SACL minInPk

 SACB
 LACC peakIn
 CRLT
 BCND NONEWMIN,NC

 LACC newMinPk
 CRGT
 SACL newMinPk

 LACC minCtr
 SUB #1
 SACL minCtr
 BCND SKIPZN1,GT

 LACC newMinPk
 SACL minInPk

NONEWMIN:;***********************no new min**************************
 ZAP
 SACL newMinPk
 LACL #MIN_PKS
 SACL minCtr

SKIPZN1:
 LACC peakIn
 MAR *,AR4  ; store peak to peak array
 SACL *+,0,AR2
 LAMM AR4
 AND #19Fh  ; 180H + 31 (enforce circular buf)
 SAMM AR4


 LACC #180h  ; get max of peak array
 SAMM AR2
 NOP
 NOP
 LACC *+
 SACB   ; got 1st point

 LACC #30  ; loop 31 times
 SAMM BRCR
 RPTB ENDBLOCK -1
 LACC *+
 CRGT
 NOP   ; need a 3 instruction loop
ENDBLOCK:

 SUB inTgt  ; determine amount to modify inTgt

 BSAR 5  ; change by 1/32 (32 mini blocks)
 ADD inTgt

 SACB  ; take max of inTgt, minInPk << MIN_SHFT
 .if BGLIMIT
 LACC minInPk,MIN_SHFT
 CRGT
 .endif
 LACC #07FFFh  ; limit to max
 CRLT
    ; min inTgt is 0x272(or outMult o'flo)
 LACC #0x272
 CRGT
 SACL inTgt

 ZAP   ; zero out the peak
 SACL peakIn

    ; calc new outMult
    ; acc_lo = (outTgt << GAIN_SHIFT)/inTgt
 LACC outTgt,GAINSHFT
 RPT #15
 SUBC inTgt
 SACL dummy1  ; clean off MS bits
 LACC dummy1

 SUB outMult  ; calc delta outMult (dOutMult)
    ; = (newOutMult-outMult)/20
    ; = (newOutMult-outMult)/16 -
    ;   (newOutMult-outMult)/64
 BSAR 4
 SACB
 BSAR 2
 EXAR
 SBB
 SACL dOutMult

* B DOOUTPUT



DOOUTPUT:;****************do output**************************************
 MAR *,AR1

 .if FIXDGAIN
 LACC #750
 SACL outMult
 .else
 LACC outMult  ; update outMult
 ADD dOutMult
 SACL outMult
 .endif

 LACC *,0  ; get oldest value

 LT *  ; mult by outMult
 MPY outMult
 PAC
 BSAR GAINSHFT
 SACL debugOut

 .if SAFETY
 SACL dummy1
 SACB
 LACC #OUTLIMT,0 ; limit positive numbers to max
 CRLT
 BCND LOCKUP,C
 LACC #OUTLIMTN,0
 CRGT
 BCND LOCKUP,C
 .endif

UNLOCK:

 .if CWRCVR
 CALL sinGen
 BSAR 1
 .endif

 SACL dummy1  ; save in a temp for right output

*************************** process left output ********************

 .if STOCK
 AND #0FFFCh  ; mask off DAC lsb's or else lockup
 SAMM DXR
 .else
 BSAR 4  ; max of +-2k for full width pulse
 ADD #2048,0  ; unipolar dac
 AND  #0FFFh
 OR #0E000h  ; switch precharge & chip select
 SACL outLeft


*************************** process right output ********************

 LACC dummy1   ; get oldest value for output
 BSAR 4  ; max of +-2k for full width pulse
 ADD #2048,0  ; unipolar dac
 AND  #0FFFh
 OR #01000h  ; chip select
 SACL outRight
 .endif

 ZAC   ; zero acc - counts idle time
 LAR AR2,#0  ; done processing flag
 MAR *,AR2  ; can eliminate later?

WAIT:
 .if MOBILE
 IDLE
 BANZ PROCESS  ; AR2 is flag
 B WAIT
 .else
 BANZD PROCESS  ; AR2 is flag
 ADD #2
 ADD #2
 BD WAIT
 ADD #2
 ADD #2
 .endif

LOCKUP: B UNLOCK

*****************************************************************
* gen a sin wave, 90 deg stored in SINTAB - saves MAR

sinGen:
 SST #0,BMAR  ; save MAR (bits of ST0) in BMAR

 LACL phase
 ADD dPhase   ; add delta phase
 AND #255  ; max phase is 255
 SACL phase

 AND #127  ; confine to 180 degrees
 SACB
 SUB #64  ; if phase > 90 deg, C=1
 LACB
 XC 2,C  ; if phase > 90 deg, phase = 127 - phase
 NEG
 ADD #127

 ADD #SINTAB0,0 ; get the correct value from SINTAB
 SAMM AR2
 MAR *,AR2
 NOP   ; need 2 cycles after SAMM AR2 before LACL
 LACL *

 SACB   ; if phase > 180 deg, value = - value
 LACL phase
 SUB #128
 LACB
 XC 1,C
 NEG

 .if SQMOD   ; square wave AM modulate
 SACB

 LACL phase  ; on phase = 0, increment amShift
 BCND AMOK,NEQ
 LACL amShift
 ADD #1
 SACL amShift
AMOK:
 LACL amShift
 AND #8
 BCND FULLAMP,NEQ
 EXAR
 BSAR 1
 EXAR
FULLAMP:
 EXAR
 .endif
 LDP #0  ; restore MAR
 LST #0,BMAR
 RET

 .if STOCK
******************************************************************
*  DESCRIPTION: This routine initializes the TLC320C40 for       *
*  a 12 kHz sample rate with a gain setting of 1  *
******************************************************************
* aic initialization data
*
ADCINSTK: SPLK    #20h,TCR           ; To generate 10 MHz from Tout
         SPLK    #01h,PRD           ; for AIC master clock
         MAR     *,AR0
         LACC    #0008h             ; Non continuous mode
         SACL    SPC                ; FSX as input
         LACC    #00c8h             ; 16 bit words
         SACL    SPC

  OPL  #0837h,PMST   ; make address lines visible
         LACC    #080h            ; Pulse AIC reset by setting it low
         SACH    DXR
         SACL    GREG
         LAR     AR0,#0FFFFh
         RPT     #10000           ; and taking it high after 10000 cycles
         LACC    *,0,AR0          ; (.5ms at 50ns)
         SACH    GREG
         ;------------------------  dig filter clock = 10 MHz/(2*TA)
         SETC    SXM              ;                  = 416.7 kHz
         LACC    #12,9            ; TA
         ADD     #24,2            ; RA - unused
         CALL    AIC_2ND          ;
         ;------------------------ ADC rate = dig filter clock / TB
                                  ;         = 11905 kHz
         LACC    #35,9            ; TB
         ADD     #18,2            ; RB - unused
         ADD     #02h             ;
         CALL    AIC_2ND          ;
         ;------------------------
         LACC    #28h,2           ; AIC control, max gain(4), synchronous
         ADD     #03h             ;
         CALL    AIC_2ND          ;
  OPL  #08B7h,PMST   ; make address lines invisible
         RET                      ;

AIC_2ND:
         LDP     #0
         SACH    DXR              ;
         CLRC    INTM
         IDLE
         ADD     #6h,15           ; 0000 0000 0000 0011 XXXX XXXX XXXX XXXX
b
         SACH    DXR              ;
         IDLE
         SACL    DXR              ;
         IDLE
         LACL    #0               ;
         SACL    DXR              ; make sure the word got sent
         IDLE
         SETC    INTM
         RET                      ;

XMITINT:
 RETE

TIMERSTK:
 SACL spareCnt,0
 SUB minSpare
 LACC spareCnt
 XC 1,LT
 SACL minSpare,0
 LAMM DRR
 SACL adcData
 LAR AR2,#1  ; flag to process ADC input
ENDO:;******************end of program*****************************
	RETE
 .endif

	.end







More information about the Audiolog mailing list

Send comments to us at biosci-help [At] net.bio.net