;SINEFM.ASM - GENERATES A SINE WITH 128 POINTS USING INTERRUPTS WITH FM ;Modified by Tim Wilson from sine8i.asm during NSF DSP workshop .start "intsect",0x809FC5 ;starting addr for interrupt .start ".text",0x809900 ;starting address for text .start ".data",0x809C00 ;starting address for data .include "AICCOM31.ASM" ;AIC communication routines .sect "intsect" ;section for interrupt vector BR ISR ;XINT0 interrupt vector .data ;data section AICSEC .word 162Ch,1h,4892h,67h ;Fs = 8 kHz TWO_PI .set 8*atan(1.0) ;pi SINE_ADDR .word SINE_VAL ;starting addr of sine values LENGTH .set 128 ;length of circular buffer .brstart "SINE_BUFF",2*LENGTH ;align sine table SINE_VAL .loop LENGTH ;fill the sine table .float sin(($ - SINE_VAL)*TWO_PI/LENGTH) ; sin(2 pi n / N) .endloop SCALE .float 1000.0 ; output scale value INC .float 0.001 ; FM rate MASK .set LENGTH-1 ;prevent falling off edge .entry BEGIN ;start of code .text ;text section BEGIN LDP AICSEC ;init to data page 128 CALL AICSET_I ;init AIC LDI LENGTH,BK ;BK=size of circular buffer LDI @SINE_ADDR,AR1 ;AR1=starting addr of sine values LDI 0,IR0 ;initial offset LDF 0.0,R2 ;index increment WAIT IDLE ;wait for interrupt BR WAIT ;branch to wait until interrupt ; INTERRUPT SERVICE ROUTINE ;;; If you replace IR0 in the instruction below with 1, you get ;;; a constant frequency sinusoid (f = Fs/N = 8000/128 = 62.5Hz) ISR LDF *AR1++(IR0)%,R1 ;R1=sine value for output ;;; On each tick we add increment INC to R2 ADDF @INC,R2 ;R2 contains the offset phasor FIX R2,IR0 ;only use the integer part AND MASK,IR0 ;keep only bits that reference table LDF @SCALE,R0 ;SCALE value for output MPYF R1,R0 ;sine's between 0-1, goose it up FIX R0,R7 ;D->A is integer CALL AICIO_I ;call AIC for output RETI ;return from interrupt