home *** CD-ROM | disk | FTP | other *** search
- *******************************************************************************
- *
- * Math -- Version 3.0
- *
- * (C) Copyright Apple Computer, Inc. 1988-1990
- * All rights reserved.
- *
- * Developer Technical Support Apple II Sample Code
- *
- * by Jim Mensch
- *
- * Sample to show how to use the Integer math and SANE tools. This program shows
- * 2 basic operations performed both with the integer math tools and SANE. The
- * first is the calculation and display of a simple SINE curve. The second is
- * a more complex Fast Fourier Transform.
- *
- *******************************************************************************
- eject
-
- **********************************************************************
- * *
- * Apple IIGS Source Code Sampler, Volume I *
- * *
- * Copyright (c) Apple Computer, Inc. 1988-1990 *
- * All Rights Reserved *
- * *
- * Written by Apple II Developer Tech Support *
- * *
- * *
- * *
- * ---------------------------------------------------------------- *
- * *
- * This program and its derivatives are licensed only for *
- * use on Apple computers. *
- * *
- * Works based on this program must contain and *
- * conspicuously display this notice. *
- * *
- * This software is provided for your evaluation and to *
- * assist you in developing software for the Apple IIGS *
- * computer. *
- * *
- * DISCLAIMER OF WARRANTY *
- * *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT *
- * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, *
- * WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS *
- * FOR ANY PARTICULAR PURPOSE. THE ENTIRE RISK AS TO *
- * THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH *
- * YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND *
- * NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE) *
- * ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, *
- * REPAIR OR CORRECTION. *
- * *
- * Apple does not warrant that the functions *
- * contained in the Software will meet your requirements *
- * or that the operation of the Software will be *
- * uninterrupted or error free or that defects in the *
- * Software will be corrected. *
- * *
- * SOME STATES DO NOT ALLOW THE EXCLUSION *
- * OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY *
- * NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC *
- * LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS *
- * WHICH VARY FROM STATE TO STATE. *
- * *
- * *
- **********************************************************************
- eject
-
- case on
-
- copy 2/ainclude/E16.Quickdraw
- copy 2/ainclude/E16.Memory
- copy 2/ainclude/E16.Window
- copy 2/ainclude/E16.Dialog
- copy 2/ainclude/E16.SANE
- mcopy macros/math.mac1
-
- DPHandle gequ 0
- DPPointer gequ DPHandle+4
- DeRef gequ DPPointer+4
-
- ScreenWidth gequ 640
- ScreenMode gequ $80
-
- EJECT
- *******************************************************************************
- *
- Math start
- *
- * Description: This main routine calls the other major routines in the
- * correct order.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import QuitParms
- * Import InitTools
- * Import InitApp
- * Import EventLoop
- * Import CloseTools
- * Import CloseApp
- *
- * Entry Points: None
- *
- *******************************************************************************
-
- jsr InitTools
- jsr InitApp
-
- _ShowCursor
-
- jsr EventLoop
- jsr CloseApp
- jsr CloseTools
-
- _Quit QuitParms
-
- end
-
- EJECT
- *******************************************************************************
- *
- Globals data
- *
- * Description: Global data for use in all routines of this demo. This area
- * also contains the data used by StandardLib.aii
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import displayCache
- *
- * Entry Points:
- * Export QuitParms ; used by Main
- *
- *******************************************************************************
- *
- * Standard global data
- *
- *******************************************************************************
-
- TitleString str 'Apple IIgs Integer Math/Sane demo'
- AutString str 'By Jim Mensch Apple DTS -- Version: 3.0'
- VersString str 'Copyright (c) 1988-1990 Apple Computer'
-
-
- MenuHeight ds 2 ; Stored height of menu bar
- MyID ds 2 ; Application ID
- MyDP ds 2 ; My direct page storage
-
- QuitFlag ds 2
- QuitParms dc i4'0' ; Pathname of next app
- dc i2'$00' ; flags
-
- EventRecord ANOP
- EventWhat ds 2
- EventMessage ds 4
- EventWhen ds 4
- EventWhere ds 4
- EventModifiers ds 2
- TaskData ds 4
- TaskMask dc i4'$0000FFFF'
-
- portCacheInfo ds 4
- ds 4
- ds 4
- ds 4
- dc i2'$C000'
- dc i2'0,0,175,599'
- dc i2'0,0,175,599'
-
- EJECT
- *******************************************************************************
- *
- * Application specific global data
- *
- *******************************************************************************
-
- ; This is a list of pointers to the text that is used to create our menus. It
- ; is used by InitApp to find all of the menu templates and use them to create
- ; our menubar. This loop loads MenuPtrLen-4 into an index, gets the
- ; corresponding menu template pointer in this table, and uses that in a
- ; NewMenu call. It then decrements the index by 4, and repeats the procees
- ; until the index is negative.
-
- MenuPtr dc i4'AppMenu'
- dc i4'FileMenu'
- MenuPtrLen equ *-MenuPtr
-
-
- ; Menu list: menu items should be numbered consecutivly starting from 250.
- ; As a convention, use 256 as about and 257 as Quit.
-
-
-
- AppMenu dc c'$$@\XN1',i1'$0D'
- dc c'--About Math...\N256V',i1'$00'
- dc c'.'
- FileMenu dc c'$$ File \N2',i1'$0D'
- dc c'--SANE Fast Fourier transform\N260',i1'$00'
- dc c'--Integer Fast Fourier transform\N261',i1'0'
- dc c'--Integer Sine wave\N258*Ii',i1'$00'
- dc c'--SANE Sine wave\N259*SsV',i1'$00'
- dc c'--Quit\N257*Qq',i1'$00'
- dc c'.'
-
- ; Paramater block used to create the main window for display. All the
- ; graphing routines will use this window to draw into.
-
- MyWindow dc i2'WindEnd-*' ; size of paramBlock
- dc i2'%0010000000100000' ; frame bits : alert, vis
- dc i4'0' ; no title bar, no title...
- dc i4'0' ; ref con 0
- dc i2'0,0,0,0' ; zoomed rect
- dc i4'0' ; color table = default
- dc i2'0,0' ; scroll bar XY origin
- dc i2'0,0' ; no scroll no max...
- dc i2'0,0' ; No zooming...
- dc i2'0,0' ; no scrolling
- dc i2'0,0' ; no paging....
- dc i4'0' ; no info bar, no ref con
- dc i2'0' ; info bar height ( none...)
- dc i4'0' ; Frame defproc, NIL=standard
- dc i4'0' ; no info bar def proc
- dc i4'displayCache' ; update procedure to display cache
- dc i2'20,20,195,619' ; bounds rect...
- dc i4'$FFFFFFFF' ; plane= on top...
- dc i4'0' ; NIL storage pointer
- WindEnd equ *
- ContRect dc i2'0,0,180,599' ; content rectangle
-
- WindPointer ds 4
-
- ; Constants used thru the program both represent PI*2
-
- TwoPi dc i1'$1D,$72,$33,$DC,$80,$CF,$0F,$C9,$01,$40'
- TwoPiFix dc i2'$487E,$0006'
-
- ; Titles for the bottom of the window
-
- IntSineTitle str 'Integer Math Demo: plotting Y=SIN(X)'
- SANESineTitle str 'SANE Demo: plotting Y=SIN(X)'
- IntHarmTitle str 'Integer Math Demo: plotting complex waveform'
- SANEHarmTitle str 'SANE Demo: plotting complex waveform'
- end
-
- EJECT
- *******************************************************************************
- *
- InitApp start
- *
- * Description: This routine creates our window and zeros out the quitflag
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import newPort
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
-
- Stz QuitFlag ; zero out quit flag
-
- PushLong #0
- PushLong #MyWindow
- _NewWindow ; create a window to graph in
- PullLong WindPointer
-
- PushLong WindPointer
- _SetPort ; make the new window the current port
-
- pha
- pha
- pea portCacheInfo|-16
- pea portCacheInfo
- jsl newPort
- pla ; The result is also stored in portCacheInfo.
- pla
-
- rts
- end
-
- EJECT
- *******************************************************************************
- *
- CloseApp start
- *
- * Description: This routine will be called at program end to dispose of
- * the window.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import killPort
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
-
- PushLong WindPointer
- _CloseWindow
-
- pea portCacheInfo|-16
- pea portCacheInfo
- jsl killPort
-
- rts
- end
-
- EJECT
- *******************************************************************************
- *
- EventLoop start
- *
- * Description: Main loop. Handles events until the user selects quit
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import Ignore
- * Import MenuSelect
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
-
-
- pha ; Push on space for TaskMaster result
- PushWord #$FFFF ; GetNextEvent mask
- PushLong #EventRecord ; Pointer to Event Record
- _TaskMaster
-
- pla ; Get TaskMaster result
- beq EventLoop ; Remove if you want to use null events
- asl A ; Turn it into an index
- tax
- jsr (TaskTable,x) ; Call appropriate event handler
-
- lda QuitFlag ; Quit selected?
- beq EventLoop ; no - keep looping
-
- rts ; yes- leave the program
-
-
- TaskTable dc i2'Ignore' ; 0 Null
- dc i2'Ignore' ; 1 MouseDown
- dc i2'Ignore' ; 2 Mouse Up
- dc i2'Ignore' ; 3 KeyDown
- dc i2'Ignore' ; 4 Undefined
- dc i2'Ignore' ; 5 AutoKey
- dc i2'Ignore' ; 6 Update
- dc i2'Ignore' ; 7 undefined
- dc i2'Ignore' ; 8 activate
- dc i2'Ignore' ; 9 Switch
- dc i2'Ignore' ; 10 desk acc
- dc i2'Ignore' ; 11 device driver
- dc i2'Ignore' ; 12 ap
- dc i2'Ignore' ; 13 ap
- dc i2'Ignore' ; 14 ap
- dc i2'Ignore' ; 15 ap
- dc i2'Ignore' ; TASK 0 indesk
- dc i2'MenuSelect' ; TASK 1 in menuBar
- dc i2'Ignore' ; TASK 2 in system window
- dc i2'Ignore' ; TASK 3 in content
- dc i2'Ignore' ; TASK 4 in Drag
- dc i2'Ignore' ; TASK 5 in grow
- dc i2'Ignore' ; TASK 6 in goaway
- dc i2'Ignore' ; TASK 7 in zoom
- dc i2'Ignore' ; TASK 8 in info bar
- dc i2'Ignore' ; TASK 9 in special menu
- dc i2'Ignore' ; TASK 10 in NDA
- dc i2'Ignore' ; TASK 11 in frame
- dc i2'Ignore' ; TASK 12 in drop
-
- end
-
- EJECT
- *******************************************************************************
- *
- MenuSelect start
- *
- * Description: This routine is called when taskmaster returns a code
- * indicating that the user selected one of our menu options.
- * This routine will call whatever routine is indicated for
- * each menu action
- *
- *
- * Inputs: TaskData - menu selected by the user
- *
- * Outputs: None
- *
- * External Refs:
- * Import Ignore
- * Import doAbout
- * Import doQuit
- * Import IntSineCurve
- * Import SANESineCurve
- * Import IntHarmWave
- * Import SANEHarmWave
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
-
- lda TaskData ; get the ID of the menu item selected
- sec ; adjust it to be between 0 and 5
- sbc #256
- asl a ; multiply it by 2
- tax ; and use it as an index into our jump
- jsr (MenuTable,x) ; table.
-
- MSDone ANOP
- PushWord #0 ; menu action complete, unhilite the
- PushWord TaskData+2 ; selected menu to show we are done
- _HiliteMenu
-
- rts ; and quit
-
- MenuTable dc i2'doAbout' ; about shell...
- dc i2'doQuit' ; quit selected
- dc i2'IntSineCurve' ; draw integer math sine wave
- dc i2'SANESineCurve' ; draw sane sine wave
- dc i2'SANEHarmWave'
- dc i2'IntHarmWave'
- end
-
- EJECT
- *******************************************************************************
- *
- doQuit start
- *
- * Description: Sets the quit flag to inform the event loop that the user
- * wants to stop the program
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
-
- lda #$FFFF
- sta QuitFlag
- rts
- end
-
- *******************************************************************************
- *
- Ignore start
- *
- * Description: Called when the program gets an event or menu selection that
- * it does not want to handle
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
- rts
- end
-
- EJECT
- *******************************************************************************
- *
- setCachePort start
- * Export setViewPort, displayCache
- using Globals
-
- plx ;Clone enough of the stack.
- tsc
- sta keepStackPtr
- ldy #10
- aa lda 10*2-1,s
- pha
- dey
- bne aa
- phx
-
- lda portCacheInfo+2 ;Switch to cache port.
- pha
- lda portCacheInfo
- pha
- _SetPort
-
- rts
-
- setViewPort entry
- plx ;Set the stack back to before cloning.
- lda keepStackPtr
- tcs
- phx
-
- lda WindPointer+2
- pha
- lda WindPointer
- pha
- _SetPort
-
- rts
-
- keepStackPtr dc i2'0'
-
- displayCache entry
- pha
- pha
- _GetPort
-
- lda portCacheInfo+2
- pha
- lda portCacheInfo
- pha
- _SetPort
-
- pea cacheLocInfo|-16
- pea cacheLocInfo
- _GetPortLoc
-
- pea cachePortRect|-16
- pea cachePortRect
- _GetPortRect
-
- _SetPort
-
- pea cacheLocInfo|-16
- pea cacheLocInfo
- pea cacheBoundsRect|-16
- pea cacheBoundsRect
- lda #0
- pha
- pha
- pha
- _PPToPort
- rtl
-
- cacheLocInfo ds 8
- cacheBoundsRect ds 8
- cachePortRect ds 8
-
- END
- *
- *******************************************************************************
-
-
-
- *******************************************************************************
- *
- IntSineCurve start
- *
- * Description: This routine will calculate a simple Sine curve and display
- * it graphically on the screen.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
-
- _WaitCursor
-
- PushLong #ContRect ; first, start with a clean screen
- jsr setCachePort ; by erasing the old screen
- _EraseRect
- jsr setViewPort
- _EraseRect
-
- PushWord #10 ; label the bottom of the window
- PushWord #170 ; to show what we are doing
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- PushLong #IntSineTitle
- jsr setCachePort
- _DrawString
- jsr setViewPort
- _DrawString
-
- stzL LoopCount ; zero the counter to start this thing
-
- PushWord #0 ; start this drawing off
- PushWord #80
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
-
- DIMLoop ANOP
- LongResult ; space for results here for all the
- LongResult ; following calculations. by pushing
- LongResult ; the space here, we do not need to
- LongResult ; adjust the stack between int math calls
- LongResult ; and we save time and space
-
- PushLong LoopCount ; Calc: LoopCount/180
- PushLong One80 ;
- _FixDiv ; leave result on stack for next calc
-
- PushLong RFixPi ; Calc (LoopCount/180)*PI
- _FixMul ; to convert LoopCount to radians
-
- _FracSin ; take the sine of the counter
-
- _Frac2Fix ; convert it back to fixed #
-
- PushLong Eighty ; multiply it by 80 to scale
- _FixMul ; we have our number!
- PullLong YCord ; and its the y coordinate
-
- PushWord LoopCount+2 ; X coordinate (HiWord of Fixed)
- lda YCord+2 ; Y coordinate + 80
- clc ; to scale the number between
- adc #80 ; 0 and 160
- pha
- jsr setCachePort
- _LineTo ; draw the linesegment for this point
- jsr setViewPort
- _LineTo
-
- inc LoopCount+2 ; bump the loopcounter
- lda LoopCount+2 ; and see if we have reached 360
- cmp #360 ; for a full SINE curve
- bge DIMDone ; if so, then finish the loop
- brl DIMLoop ; if not do the next iteration
-
- DIMDone _InitCursor
- rts ; finish the routine
-
- LoopCount ds 4 ; Fixed number to store degrees
- One80 dc i2'0,180' ; a fixed number representing 180
- Eighty dc i2'0,80' ; a FIxed number represenging 80
- YCord ds 4 ; temp storage for the y coordinate
- RFixPi dc i4'$0003243F' ; 3.14159 (PI in fixed format)
- end
-
- EJECT
- *******************************************************************************
- *
- SANESineCurve start
- *
- * Description: This routine will use the SANE toolset to calculate
- * a Sine curve. It will then plot the points on the screen.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
-
- _WaitCursor
-
- PushLong #ContRect ; first, start with a clean screen
- jsr setCachePort ; by erasing the old screen
- _EraseRect
- jsr setViewPort
- _EraseRect
-
- PushWord #10 ; label the bottom of the window
- PushWord #170 ; to show what we are doing
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- PushLong #SANESineTitle
- jsr setCachePort
- _DrawString
- jsr setViewPort
- _DrawString
-
- PushWord #0 ; start this drawing off
- PushWord #80 ; in the middle of the screen
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- stz LoopCount
-
- DSaneLoop ANOP
- ExtendEq SanePi,TempResult ; move pi/180 into the result
-
- PushLong #LoopCount ; convert LoopCount to Radians
- PushLong #TempResult
- FMULI ; by multiplying by pi/180
-
- PushLong #TempResult
- FSINX ; now get the SINE of it
-
- PushLong #Eighty ; multiply by 80
- PushLong #TempResult
- FMULI
-
- PushLong #TempResult
- PushLong #YCord ; convert to an Integer
- FX2I
-
- PushWord LoopCount ; X coordinate
- lda YCord ; Y coordinate + 80
- clc ; to get a number between
- adc #80 ; 0 and 160
- pha
- jsr setCachePort ; draw the line segement
- _LineTo
- jsr setViewPort
- _LineTo
-
- inc LoopCount ; bump the counter
- lda LoopCount
- cmp #360 ; and see if we have done all 360 degrees
- bge DSaneDone ; if so then end
- brl DSaneLoop ; if not, get next value
-
- DSaneDone _InitCursor
- rts
-
- LoopCount ds 4
- SanePi dc i1'$AE,$C8,$E9,$94,$12,$35,$FA,$8E,$F9,$3F' ; pi/180 ...
- TempResult ds 10
- Eighty dc i4'80'
- YCord ds 4
- end
-
-
- EJECT
- *******************************************************************************
- *
- FFTransData data
- *
- * Description: Data used by both FFT calculation routines
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
-
- FixCount dc i2'0' ; fractional portsion of our
- Count ds 2 ; fixed point counter
- LoopCount ds 2
- FixSamp dc i2'0' ; fractional portion of the sample var
- Sample ds 2 ; sample to figure for
- FixMaxSamp dc i2'0' ; fractional portion of Max Sample
- MaxSample dc i2'256' ; maximum number of samples
- MaxHarm dc i2'6' ; maximum number of harmonics
- MaxValue ds 10 ; maximum vaule of the FFT
- AmpTbl dc i2'0,10,8,6,4,2,1' ; amplitudes of each harmonic
- PhaseTbl dc i2'0,1,2,4,6,8,10' ; high word of each fixed phase
- PhaseTblF dc i4'0,6554,13107,26214,39321,52428,$FFFF'
- TempValue ds 10 ; intermediate result storage
- TempFactor ds 10
- Temp1 ds 10
- Temp2 ds 10
- FFTWave ds 2560 ; table to hold intermediate values
- MyDecForm dc i2'1'
- dc i2'8' ; 8 digits after the decimal place
- TempI ds 2
- TempF ds 4
- Const127 dc i2'79'
- Const80Fix dc i4'$004F000'
- Const10 dc i2'10'
- end
-
-
- EJECT
- *******************************************************************************
- *
- SANEHarmWave start
- *
- * Description: Create a complex harmonic wave using SANE
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import SaneFFTIteration
- * Import doNormIter
- *
- * Entry Points:
- *
- *******************************************************************************
-
- using Globals
- using FFTransData
-
- _WaitCursor
-
- PushLong #ContRect ; first, start with a clean screen
- jsr setCachePort ; by erasing the old screen
- _EraseRect
- jsr setViewPort
- _EraseRect
-
- PushWord #10 ; label the bottom of the window
- PushWord #170 ; to show what we are doing
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- PushLong #SANEHarmTitle
- jsr setCachePort
- _DrawString
- jsr setViewPort
- _DrawString
-
-
- PushWord #0 ; start this drawing off
- PushWord #80 ; at the left edge
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- stz Sample ; and zero out all global values
- STZEXT MaxValue
- STZEXT Temp1
- STZEXT Temp2
- STZEXT TempFactor
-
- DHWLoop1 jsr SaneFFTIteration ; do one iteration
-
- lda Sample ; now save tempValue into our array
- asl a ; multiply by 2
- sta Temp1 ; and save it for a sec
- asl a
- asl a ; multiply by 8
- clc
- adc Temp1 ; x*8+x*2=x*10
- tax ; use as an index into the sample array
-
- lda TempValue ; now stow the current value
- sta FFTWave,x ; into our wave table. Later this
- lda TempValue+2 ; table will be normalized
- sta FFTWave+2,x
- lda TempValue+4
- sta FFTWave+4,x
- lda TempValue+6
- sta FFTWave+6,x
- lda TempValue+8
- sta FFTWave+8,x
-
- inc Sample ; bump the sample counter
- lda #255
- cmp Sample ; test to see if we have reached the
- bge DHWLoop1 ; last sample, if not do the next one
-
- ; if the last sample was reached, it is time to go thru the wavetable and
- ; convert all the number so they are between 0 and 160.
-
- stz Count ; initialize the index
- DHWLoop2 inc Count
- jsr doNormIter ; normalize one iteration
-
- PushWord Count ; X coordinate
- PushWord TempValue ; value returned by doNormIter
- jsr setCachePort ; draw the line
- _LineTo
- jsr setViewPort
- _LineTo
-
- lda #255 ; see if the counter has reached the max
- cmp Count ; sample we recorded
- bge DHWLoop2 ; if not, do another point
-
-
- _InitCursor ; if it has, then we can simply end
- rts
- end
-
- EJECT
- *******************************************************************************
- *
- SaneFFTIteration start
- *
- * Description: This routine takes the current sample value and computes
- * all the harmonic components that make up the wave for that
- * sample.
- *
- *
- * Inputs: Sample - current sample to compute for
- *
- * Outputs: TempValue - output sample value
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
- using FFTransData
-
- STZEXT TempValue
-
- PushLong #Sample
- PushLong #TempFactor
- FI2X ; convert the max sample rate to extended
-
- PushLong #MaxSample
- PushLong #Temp1
- FI2X
-
- PushLong #Temp1
- PushLong #TempFactor
- FDIVX ; TempFactor:=TempFactor/Temp1
-
- PushLong #TwoPi
- PushLong #TempFactor
- FMULX ; TempFactor:=6.28318*(count/maxSample)
-
- stz Count ; zero out the counter
-
- FFLoop ANOP
- ExtendEq TwoPi,Temp2
-
- lda Count ; get the count
- asl a ; multiply by 2
- tax
- lda PhaseTbl,x
- sta TempI
- PushLong #TempI
- PushLong #Temp1
- FI2X ; Temp1:=Phase[count]
-
- PushLong #Const10
- PushLong #Temp1
- FDIVI ; divide by 10 to make it fractional
-
- PushLong #Temp1
- PushLong #Temp2
- FMulX ; Temp2:=(Temp1)/10*TwoPi
-
- ExtendEq TempFactor,Temp1
-
- PushLong #Count
- PushLong #Temp1
- FMULI ; tempi:=count*TempFactor
-
- PushLong #Temp2
- PushLong #Temp1
- FADDX ; Temp1:=((count*TempFactor)+(6.28318*Phase[count]))
-
- PushLong #Temp1
- FCOSX ; Temp1:=Cos(Temp1)
-
- lda Count ; get the count
- asl a ; multiply by 2
- tax
- lda AmpTbl,x
- sta TempI
- PushLong #TempI
- PushLong #Temp1
- FMULI ; Temp1:=Temp1*Amp[count]
-
- PushLong #Temp1
- PushLong #TempValue
- FADDX ; finally tempValue:=tempValue+Temp1
-
- PushLong #TempValue
- PushLong #Temp1
- FX2X ; copy tempvalue into Temp1
-
- PushLong #Temp1
- FABSX
-
- PushLong #Temp1
- PushLong #MaxValue
- FCMPX ; now update the max value if needed
-
- FBLE FFTL010 ; if the new number <= old max ignore next line
-
- ExtendEq Temp1,MaxValue
-
- FFTL010 ANOP
- inc Count
- lda Count
- cmp MaxHarm ; are we done yet???
- bge FFTDone
- brl FFLoop
- FFTDone rts
- end
-
- EJECT
- *******************************************************************************
- *
- doNormIter start
- *
- * Description: Normalize one iteration of the wavetable. This routine
- * takes the current sample value and converts it to
- *
- *
- * Inputs: Count - current sample number
- *
- * Outputs: TempValue - the normalized value
- *
- * External Refs: None
- *
- * Entry Points: None
- *
- *******************************************************************************
- using Globals
- using FFTransData
-
- lda Count
- asl a ; multiply by 2
- sta Temp1 ; and save it for a sec
- asl a
- asl a ; multiply by 8
- clc
- adc Temp1 ; x*8+x*2=x*10
- tax
-
- lda FFTWave,x ; now load the current value
- sta TempValue
- lda FFTWave+2,x
- sta TempValue+2
- lda FFTWave+4,x
- sta TempValue+4
- lda FFTWave+6,x
- sta TempValue+6
- lda FFTWave+8,x
- sta TempValue+8
-
- ExtendEq MaxValue,Temp2
-
- PushLong #Temp2
- PushLong #TempValue ; divide the two
- FDIVX
-
- PushLong #Const127 ; now scale it
- PushLong #TempValue
- FMULI
-
- PushLong #Const127
- PushLong #TempValue
- FADDI
-
- PushLong #TempValue ; now, convert ot to an integer
- PushLong #TempI
- FX2I
-
- lda TempI
- sta TempValue
- rts
- end
-
-
-
- EJECT
- *******************************************************************************
- *
- IntHarmWave start
- *
- * Description: This routine will create a complex waveformusing the
- * integer math tools
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- * Import IntFFTIteration
- * Import IntHarmI
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
- using FFTransData
-
- _WaitCursor
-
- PushLong #ContRect ; first, start with a clean screen
- jsr setCachePort ; by erasing the old screen
- _EraseRect
- jsr setViewPort
- _EraseRect
-
- PushWord #10 ; label the bottom of the window
- PushWord #170 ; to show what we are doing
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- PushLong #IntHarmTitle
- jsr setCachePort
- _DrawString
- jsr setViewPort
- _DrawString
-
- PushWord #0 ; start this drawing off
- PushWord #80
- jsr setCachePort
- _MoveTo
- jsr setViewPort
- _MoveTo
-
- stz Sample ; zero out some starting values
- STZL MaxValue
- STZL Temp1
- STZL Temp2
- STZL TempFactor
-
-
- DIWLoop1 jsr IntFFTIteration ; do one iteration of the wave
-
- lda Sample ; now save tempValue into our array
- asl a ; multiply by 2
- asl a
- tax
-
- lda TempValue ; now stow the temp value
- sta FFTWave,x ; into an array for later use
- lda TempValue+2
- sta FFTWave+2,x
-
- inc Sample ; bump the sample counter
- lda #255
- cmp Sample ; see if we are done
- bge DIWLoop1 ; if not, get another sample
-
- ; Now that the array of values has been created. Go thru and scale
- ; each value so that it fits in our wave and is between 0 and 160
-
- stz Count ; zero the sample counter
- DIWLoop2 inc Count
- jsr IntHarmI ; normalize one iteration
-
- PushWord Count ; X coordinate
- PushWord TempValue
- jsr setCachePort ; draw the line
- _LineTo
- jsr setViewPort
- _LineTo
-
- lda #255
- cmp Count
- bge DIWLoop2
-
- _InitCursor
- rts
- end
-
- EJECT
- *******************************************************************************
- *
- IntFFTIteration start
- *
- * Description: This routine will calculate one single iteration of the
- * wave. It will add a the Cosine*amp of each desired
- * harmonic to create a single sample
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
- using FFTransData
-
- stzL TempValue
-
- LongResult ; push room on the stack
- LongResult ; push room on the stack
- PushLong FixSamp ; sample fixed number format
- PushLong FixMaxSamp ; max sample fixed point number
- _FixDiv
-
- PushLong TwoPiFix
- _FixMul ; now multiply the two to get theFactor
- PullLong TempFactor
-
-
- stz Count ; zero out the counter
-
- FFLoop ANOP
-
- lda Count ; get the count
- asl a ; multiply by 2
- asl a
- tax
- lda PhaseTblF,x
- sta TempF
- lda PhaseTblF+2,X
- sta TempF+2
-
- LongResult ; push room on the stack
- PushLong TwoPiFix
- PushLong TempF
- _FixMul ; Temp2:=Phase(Count)*TwoPi
- PullLong Temp2
-
- LongResult ; push room on the stack
- PushLong FixCount
- PushLong TempFactor
- _FixMul ; Temp1:=count*TempFactor
- PullLong Temp1
-
- lda Temp1 ; Temp2:=Temp1+Temp2
- clc
- adc Temp2
- sta Temp2
- lda Temp1+2
- adc Temp2+2
- sta Temp2+2
-
- LongResult ; push room on the stack
- LongResult ; push room on the stack
- LongResult ; push room on the stack
- PushLong Temp2
- _FracCos ; Temp2:=Cos(Temp2)
- _Frac2Fix ; convert back to fixed!
- PullLong Temp2
-
- PushLong Temp2
- lda Count ; get the count
- asl a ; multiply by 2
- tax
- lda AmpTbl,x
- pha
- pea $0 ; Low word of fixed count
- _FixMul ; Temp1:=Temp1*Amp[count]
- PullLong Temp2
-
- lda TempValue ; now add it to tempValue
- clc
- adc Temp2
- sta TempValue
- sta Temp2
- lda TempValue+2
- adc Temp2+2
- sta TempValue+2 ; Now test for max value
- sta Temp2+2
- bpl TestHigh ; number is positive, test for high
- lda #0 ; Negate this number to get absolute value
- sec
- sbc Temp2 ; negate this number
- sta Temp2
- lda #0
- sbc Temp2+2
- sta Temp2+2
- TestHigh lda Temp2+2
- cmp MaxValue+2 ; is it bigger than max value+2?
- beq FFTTestLow ; if equal test the low byte
- bge FFTStoreMax ; if greater move it to high
- bra FFTL010
- FFTTestLow lda Temp2
- cmp MaxValue ; is it bigger?
- blt FFTL010
- FFTStoreMax lda Temp2+2
- sta MaxValue+2
- lda Temp2
- sta MaxValue
-
- FFTL010 ANOP
- inc Count
- lda Count
- cmp MaxHarm ; are we done yet???
- bge FFTDone
- brl FFLoop
- FFTDone rts
- end
-
- EJECT
- *******************************************************************************
- *
- IntHarmI start
- *
- * Description: Takes an iteration of the wave divides it by the max value
- * and multiplies it by 160 to create a valid screen location
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
- using FFTransData
-
- lda Count
- asl a ; multiply by 4
- asl a
- tax
- lda FFTWave+2,x ; push current value on stack
- sta Temp1+2
- lda FFTWave,x ;
- sta Temp1
-
- LongResult ; push room on the stack
- LongResult ; push room on the stack
- PushLong Temp1
- PushLong MaxValue ; divide it by maxvalue
- _FixDiv
- PullLong Temp2
-
- PushLong Temp2
- PushWord #$4F
- PushWord #0 ; now scale it
- _FixMul
- PullLong Temp1
-
- lda Temp1+2
- clc
- adc #79
- sta TempValue
- rts
- end
-
- copy math.init.asm
-
- END
-