; This code works with ElecFilDes Version 2.1 ; May 18, 2014 include "MC56F84789.inc" section rtlib ;Edit the next line to point to dspfilter.asm include "C:\ElecFilDes\dspfilter.asm" org p: global Fmain SUBROUTINE "Fmain",Fmain,FmainEND-Fmain ; assembly level entry point Fmain: nop ; do nothing move.w #$0300, X:COP_CTRL ;Disable COP, It causes glithes in VREFH and VREFL move.w #$f054, X:SIM_PCE0 ;Enable IPBUs clock on GPIOA, GPIOC, and GPIOE move.w #$2000, X:SIM_PCE1 ;clock only the DAC move.w #$1100, X:SIM_PCE2 ;clock only the 16-bit A/D and CMPA move.w #$0080, X:SIM_PCE3 ;clock only PWMA channel 0 move.w #$0FFF, X:SIM_SD0 ;Clock everything even in stop mode move.w #$FFFF, X:SIM_SD1 move.w #$FFFF, X:SIM_SD2 move.w #$FFFF, X:SIM_SD3 move.w #$FFFF, X:GPIOA_PER ;Port A is all peripherals move.w #$FFFF, X:GPIOB_PER ;Port B is all peripherals move.w #$0025, X:GPIOC_PER ;Set GPIOC5 to peripheral mode because it is the DAC ;Set GPIOC0 to peripheral mode for XTAL bfset #$0010, OMR ;Enable saturation of ALU ;The next statements support the XTAL oscillator ;----------------------------------------------------------------------- move.w #$0000, X:OCCS_OSCTL2 ;Crystal oscillator and RC oscillator enabled move.w #$026D, X:OCCS_OSCTL1 ;Trim 8MHz Frequency for this particular ;evaluation board ;Set EXT_SEL = 0 to enable XTAL ;Set CLK_MODE to 0 to enable XTAL rep #8 ;Wait for XTAL oscillator to stabilize nop move.w #$0085, X:OCCS_CTRL ;Power UP PLL, Must wait to select PLL output as clock ;External Reference Selected ;Wait 6 NOPs for synchronizing circuit to change clocks rep #8 nop move.w #$826D, X:OCCS_OSCTL1 ;Power down RC oscillator ; move.w #$0085, X:OCCS_CTRL ;Select PLL output again and XTAL ; ;----------------------------------------------------------------------- ;The next statements support RC oscillator ;----------------------------------------------------------------------- ;move.w #$066D, X:OCCS_OSCTL1 ;Trim 8MHz Frequency for this particular ;evaluation board ;move.w #$0081, X:OCCS_CTRL ;Power UP PLL, Must wait to select PLL output as clock ;rep #8 ;nop ;move.w #$0081, X:OCCS_CTRL ;----------------------------------------------------------------------- ; move.w #$2031, X:OCCS_DIVBY ;Use 400MHz Clock move.w #T0PRELOAD, X:TMRA_0_CMPLD1 move.w #T0PRELOAD, X:TMRA_0_CMPLD2 move.w #T1PRELOAD, X:TMRA_1_LOAD move.w #T0PRELOAD, X:TMRA_0_LOAD ;initialize to a count of XXXXXX samples per second move.w #$3010, X:TMRA_0_CTRL ;COUNT RISING EDGE OF IP BUS CLOCK, ROLL OVER MOVE.W #$e830, X:TMRA_1_CTRL ;CASCADE WYTH TYMER 0 move.w #$0030, X:SIM_GPSCL ;Selects DAC on GPIO_C5 as opposed to the XBAR perpherial ;Also Select C2 to be Clockout0 ;C0 is selected to be External XTAL move.w #$1000, X:SIM_CLKOUT ;Dump 8MHz OSC ouput on pin C2 move.w #$0002, X:DAC_CTRL0 ;Words are left justified move.w #$00FF, X:GPIOE_DDR ;PortE is output on ports 0-7 move.w #$0000, X:SIM_GPSAL ;Select A move.w #$0008, X:ADC16_SC1A ;Select A/D on channel 8 move.w #$006C, X:ADC16_CFG1 ;Select 16 bit mode, Clock rate is inputclock/8 move.w #$000F, X:ADC16_CFG2 ;Enable asynchronous clock move.w #$0000, X:ADC16_SC2 ;Use VRFEFH and VREFL, don't know why this works as ;there is no voltage on these pins move.w #$0000, X:ADC16_SC3 ;continuous converson, averaging disabled move.w #$1da4, X:ADC12_PWR ;POWER DOWN 12 BIT A/D TO MAKE SURE IT IS NOT RUNNING move.w #$0000,X:GPIOE_DR ;Turn off 8 LEDs on Port E move.w #$00FF,X:GPIOE_DR ;Turn on 8 LEDs on Port E moveu.w #states,r0 ;point to filter states moveu.w #ntaps-1,m01 ;mod(ntaps) moveu.w #coef,r3 ;point to filter coefficients move.w #FILTERTYPE, a cmp #1, a ;a = 1 means FIR filter beq loop_at_end_of_app nop moveu.w #$FFFF,m01 ;mod(ntaps) cmp #2, a ;a = 2 means IIR filter beq appA cmp #3, a ;a = 3 means DDS beq appB appA jmp loop_at_end_of_appA appB move.w #T1PRELOAD, c ;Is T1PRELOAD = 0 ? asl c ;Set or clear the z bit bne wait3B ;If = 0, then do the next instruction move.w #$3030, X:TMRA_0_CTRL ;Can auto reload lower 16 bit counter wait3B jmp loop_at_end_of_appB ;This section is to implement a FIR filter loop_at_end_of_app: ;debughlt move.w #$0008, X:ADC16_SC1A ;Select 16 bit A/D on channel moveu.w #coef,r3 ;point to filter coefficients eorc #$8000, y0 ;Must convert to two complement for math operations clr a y0,x:(r0)+ ;x:(r3)+,x0 move.w x:(r3)+,x0 ;Added instruction to do X:(r1)+,YO moveu.w #(ntaps-1)/2, LC ;This sets up a DO loop for an even number of loops NOP ;Required NOP NOP ;Required NOP doslc loopend ;Begin DO loop. Two instructions in DO loop for increased speed mac y0,x0,a x:(r0)+,y0 x:(r3)+,x0 mac y0,x0,a x:(r0)+,y0 x:(r3)+,x0 loopend move.w #ntaps-1, b ;additional MAC if tap length is even brclr #$0001, b, skipover mac y0,x0,a x:(r0)+,y0 x:(r3)+,x0 skipover nop ;Last MAC instruction. Total MACs should equal ntaps macr y0,x0,a MOVE.W x:(r0)-, Y1 loop1 eorc #$8000, a ;Must convert from two complement for DAC output move.w A, X:$E001 ;DAC_DATAREG wait1 ;nop brclr #$8000, X:TMRA_1_SCTRL, wait1 ;wait until timer1 ;nop move.w #T1PRELOAD, a ;Is T1PRELOAD = 0 ? asl a ;Set or clear the z bit bne wait2 ;If = 0, then do the next instruction move.w #$3030, X:TMRA_0_CTRL ;Can auto reload lower 16 bit counter wait2 ;nop brclr #$8000, X:TMRA_0_SCTRL, wait2 ;wait until A/D conversion is complete ;nop move.w #T1PRELOAD, a ;Is T1PRELOAD = 0 ? asl a ;Set or clear the z bit beq sk1 ;If =0 then skip next instruction move.w #(T0PRELOAD-22), X:TMRA_0_CNTR ;Timer was rollover, needs to be reset ;to initial value sk1 MOVE.W #$0000, X:TMRA_1_SCTRL ;CLEAR TIMER COMPARE FLAGS MOVE.W #$0000, X:TMRA_0_SCTRL wait nop brclr #$0080, X:ADC16_SC1A, wait ;wait until A/D conversion is complete nop move.w X:ADC16_RA, y0 ;This process works in real time, but not in single step mode, ;for some reason jmp loop_at_end_of_app ;This section is to implement an IIR filter loop_at_end_of_appA: ;debughlt move.w #$0008, X:ADC16_SC1A ;Select 16 bit A/D on channel 8 eorc #$8000, a ;Must convert to two complement for math operations asr a ;Divide input by 2 to prevent it from getting close to saturation nop move.w #$0000, y0 move.w #ntaps-1, d loopxA move.w #$2, N move.l a10,X:(r0+8) ;save Vin in location ro+8 move.l x:(r3)+, b ;load P2 move.l x:(r0), y ;load Vin z-2 mpy32 y,b, a x:(r3)+,b ;multiply and load P1 move.l X:(r0+2),y ;load Vin z-1 move.l y, x:(r0) ;move Vin z-1 to Vin z-2 mac32 y,b, a x:(r3)+,b ;multiply and load P0 move.l x:(r0+8),y ;move Vin to Y move.l y, x:(r0+2) ;move Vin to Vin z-1 mac32 y,b,a x:(r3)+,b ;multiply and load -d2 move.l x:(r0+4), y ;load Vo z-2 mac32 y,b,a x:(r3)+,b ;multiply and load -d1 move.l X:(r0+6), y ;load Vo z-1 move.l y,x:(r0+4) ;to Vo z-1 mac32 y,b, a move.w x:(r3)+n,x0 rep x0 asl a ;multiply Vo by 2 because coefficients were /2 move.l a10,x:(r0+6) ;move Vo to Vo z-1 move.w #$A,n move.w x:(r0)+n, y1 ;set r0 to point to next stage z-2 and z-1 dec.w d bcc loopxA loop1A nop nop asl a ;Multiply output by 2 because input was divided by 2 eorc #$8000, a ;Must convert from two complement for DAC output move.w A, X:$E001 ;DAC_DATAREG wait1A brclr #$8000, X:TMRA_1_SCTRL, wait1A ;wait until timer1 move.w #T1PRELOAD, a ;Is T1PRELOAD = 0 ? asl a ;Set or clear the z bit bne wait2A ;If = 0, then do the next instruction move.w #$3030, X:TMRA_0_CTRL ;Can auto reload lower 16 bit counter wait2A brclr #$8000, X:TMRA_0_SCTRL, wait2A ;wait until second timer move.w #T1PRELOAD, a ;Is T1PRELOAD = 0 ? asl a ;Set or clear the z bit beq sk1a ;If =0 then skip next instruction move.w #(T0PRELOAD-22), X:TMRA_0_CNTR ;Timer was rollover, needs to be reset to ;initial value sk1a MOVE.W #$0000, X:TMRA_1_SCTRL ;CLEAR TIMER COMPARE FLAGS MOVE.W #$0000, X:TMRA_0_SCTRL waitA nop brclr #$0080, X:ADC16_SC1A, waitA ;wait until A/D conversion is complete nop move.w X:ADC16_RA, a ;This process works in real time, but not in single step mode, ;for some reason move.w #$0000, a0 moveu.w #coef,r3 ;point to filter coefficients moveu.w #states,r0 jmp loop_at_end_of_appA ;This section is to synthesize a sine wave loop_at_end_of_appB: ;debughlt move.w #$0008, X:ADC16_SC1A ;Select 16 bit A/D on channel 8 eorc #$8000, a ;Must convert to two complement for math operations asr a ;Divide input by 2 to prevent it from getting ;close to saturation nop move.w #$0000, y0 move.w #ntaps-1, d loopxB move.l a10,X:(r0+8) ;save Vin in location ro+8 move.l x:(r3)+, b ;load P2 move.l x:(r0), y ;load Vin z-2 mpy32 y,b, a x:(r3)+,b ;multiply and load P1 move.l X:(r0+2),y ;load Vin z-1 move.l y, x:(r0) ;move Vin z-1 to Vin z-2 mac32 y,b, a x:(r3)+,b ;multiply and load P0 move.l x:(r0+8),y ;move Vin to Y move.l y, x:(r0+2) ;move Vin to Vin z-1 mac32 y,b,a x:(r3)+,b ;multiply and load -d2 move.l x:(r0+4), y ;load Vo z-2 mac32 y,b,a x:(r3)+,b ;multiply and load -d1 move.l X:(r0+6), y ;load Vo z-1 move.l y,x:(r0+4) ;to Vo z-1 mac32 y,b, a move.w x:(r3)+n,x0 rep x0 asl a ;multiply Vo by 2 because coefficients were /2 move.l a10,x:(r0+6) ;move Vo to Vo z-1 loop1B asl a ;Multiply output by 2 because input was divided by 2 eorc #$8000, a move.w a, X:$E001 ;X:DAC_DATAREG wait1B brclr #$8000, X:TMRA_1_SCTRL, wait1B ;wait until timer1 wait2B brclr #$8000, X:TMRA_0_SCTRL, wait2B ;wait until second timer nop move.w #T1PRELOAD, c ;Is T1PRELOAD = 0 ? asl c ;Set or clear the z bit beq sk1B ;If =0 then skip next instruction move.w #(T0PRELOAD-22), X:TMRA_0_CNTR ;Timer was rollover, needs to be reset to ;initial value sk1B MOVE.W #$0000, X:TMRA_1_SCTRL ;CLEAR TIMER COMPARE FLAGS MOVE.W #$0000, X:TMRA_0_SCTRL waitB andc #$8000, a ;If it is negative, keep the negative sign. orc #$6000, a ;Make is 6000 positive, or E000 negative move.w #$0000, a0 ror.w a ror.w a ror.w a ror.w a moveu.w #coef,r3 ;point to filter coefficients moveu.w #states,r0 jmp loop_at_end_of_appB rts FmainEND: endsec end