;============================================================================ ; PROJECT : PIC'SPECTRUM ; ; FILE : PICSPECT.ASM ; ; VERSION : 1.0 ; ; DESCRIPTION : ; ; PIC'SCOPE digital audio spectrum analyser - Main source file ; ; This project is a complete audio spectrum analyser with output on a ; standard VGA display, done entirely with a PIC17C756 microcontroler. ; ; The controler is in charge of : ; - ADC acquisition of the incoming signal ; - Fast Fourier Transform of the signal ; - Power calculation and if required logarithmic scaling ; - Video generation entirely in software ; of course in real time. ; ; Developped on MICROCHIP's MPLAB 3.31.0 ; To be embedded in a PIC17C756 (32MHz crystal) ; ;============================================================================ ; Developped & Copyrighted by Robert LACOSTE ;============================================================================ ;---------------------------------------------------------------------------- ; System definitions ;---------------------------------------------------------------------------- PROCESSOR 17C756 ; Assembler directives RADIX HEX ERRORLEVEL 0 ERRORLEVEL -302 ; no bank control warnings TITLE "PIC'SPECTRUM" SUBTITLE "(C) Robert Lacoste" #include "P17C756.INC" ; Processor dependant declarations ; config register : ; XT osc, no watchdog, brown-out reset active, microcontroler __CONFIG (_XT_OSC & _WDT_OFF & _BODEN_ON & _MC_MODE) ;---------------------------------------------------------------------------- ; Application constants ;---------------------------------------------------------------------------- MAXPIXVAL equ D'127' ; maximum scaled pixel value INITTIM equ H'FFFF'-D'254'+D'13'+D'5'; timer load value, ; 254 because 31.77µS=254*4/32MHz ; minus 13 for irq to reload delay ; minus 5 for timer to irq delay BKG_COLOR equ B'00000100' ; background=Blue SLINE_COLOR equ B'00000011' ; separation lines=Yellow SHORTS_COLOR equ B'00000011' ; small scale indicator=Yellow LONGS_COLOR equ B'00000011' ; long scale indicator=Yellow FREQ_COLOR equ B'00000001' ; Frequency bars=Red BKGTITLE_COLOR equ B'00000010' ; Background title=Green TITLE_COLOR equ B'00000000' ; Title=Black HOLD_COLOR equ B'00000001' ; Hold=Red ;---------------------------------------------------------------------------- ; Vectors ;---------------------------------------------------------------------------- reset_vector org H'0000' goto start ; Initialisation intpin_vector org H'0008' goto start ; should not occur timer0_vector org H'0010' goto it_timer ; horizontal sync interrupt t0cki_vector org H'0018' goto start ; should not occur periph_vector org H'0020' goto start ; should not occur start_appl org H'0050' ; start of application area ;---------------------------------------------------------------------------- ; Inclusion of extern application files ;---------------------------------------------------------------------------- #include "vars.inc" ; Variables declarations #include "fixed.inc" ; Fixed point arithmetic #include "testsig.inc" ; Test signals generation #include "fft.inc" ; FFT calculation routines #include "powers.inc" ; power calculation & display access #include "irq.inc" ; interrupt routine & video generation ;---------------------------------------------------------------------------- ; Main starting point ;---------------------------------------------------------------------------- start nop BANKSEL zone_main ;--> Initialisation call initialize ; initialization of ports & variables call realfft ; do the first FFT (on the test signal) call init_timer ; launch timer0 interrupts mainloop nop ;--> Power spectrum calculation & scaling movlb 0 ; if RB7=0 (mode log), btfsc PORTB,7 goto spectlin spectlog call powerlog ; calculate spectrum in log scale goto main1 spectlin call powerlin ; else calculate spectrum in lin scale main1 nop ;--> Analog acquisition movlb 0 ; if RB6=1 (non hold mode), btfss PORTB,6 ; do analog sample acquisition : goto main2 movlb 1 ; RD1=1 (debug line : ADC going on) bsf PORTD,1 BANKSEL num_sample ; sample number=0 clrf num_sample,F call init_adc ; initialize analog acquisition BANKSEL acq_request movlw 1 ; put acqrequest flag to 1 movwf acq_request clrf WREG,F ; and wait for it to be 0 acqwait cpfseq acq_request goto acqwait movlb 1 ; RD1=0 (debug line : ADC going on) bcf PORTD,1 ;--> Do the FFT movlb 1 ; RD0=1 (debug line : FFT going on) bsf PORTD,0 BANKSEL zone_main call realfft ; do the FFT movlb 1 ; RD0=0 (debug line : FFT going on) bcf PORTD,0 ;--> And loop ! main2 goto mainloop ;---------------------------------------------------------------------------- ; Ports & variables initialization ;---------------------------------------------------------------------------- initialize nop ;--> Variables initialization BANKSEL acq_request ; reset adc control registers clrf acq_request,F clrf num_sample,F BANKSEL scan_line ; reset scan line number clrf scan_line,F ; (will be incremented to 1 at the clrf scan_line+1,F ; first interrupt) BANKSEL displ0 ; reset displ0 buffer movlw low displ0 movwf FSR0 bcf ALUSTA,FS1 ; auto increment mode bsf ALUSTA,FS0 bcf ALUSTA,C movlw low displ0+D'64' rstdispl0 clrf INDF0,F cpfseq FSR0 goto rstdispl0 BANKSEL displ1 ; reset displ1 buffer movlw low displ1 movwf FSR0 bcf ALUSTA,FS1 ; auto increment mode bsf ALUSTA,FS0 bcf ALUSTA,C movlw low displ0+D'64' rstdispl1 clrf INDF0,F cpfseq FSR0 goto rstdispl1 bsf ALUSTA,FS1 ; return to non-increment mode BANKSEL zone_main m_ldaconst H'2000' ; generate test square signal movlw D'16' call test_square ;--> Ports initialization movlw B'11111000' ; RB0 to RB2 are outputs movlb 0 movwf DDRB clrf PORTB,F ; initialized to 0 movlw B'10101111' ; RC4 and RC6 are outputs movlb 1 movwf DDRC bcf PORTC,4 ; RC4=0 (Hsync) bsf PORTC,6 ; RC6=1 (Vsync) movlw B'11111000' ; RD0 to RD2 are outputs movlb 1 movwf DDRD clrf PORTD,F ; initialized to 0 movlw B'01111111' ; RG7 is output movlb 5 movwf DDRG clrf PORTG,F ; initialized to 0 return ;---------------------------------------------------------------------------- ; Initialization of timer0 ; ; Generate an interrupt every 31.77 micro-second (horizontal refresh ; rate for VGA display in 640x350 mode = 31.476KHz) ; ; Warning : interrupts will start immediatly after calling this routine ;---------------------------------------------------------------------------- init_timer nop bsf CPUSTA,GLINTD ; disable global interrupts bsf T0STA,T0CS ; select internal clock bcf T0STA,T0PS3 ; and prescale factor 1:1 bcf T0STA,T0PS2 bcf T0STA,T0PS1 bcf T0STA,T0PS0 BANKSEL tmpcpt movlw high INITTIM ; load timer movwf tmpcpt movlw low INITTIM movwf TMR0L movfp tmpcpt,TMR0H bcf INTSTA,PEIE ; disable PEI interrupts bcf INTSTA,T0CKIE ; disable external interrupts on RA1 bcf INTSTA,INTE ; disable external interrupts on RA0 bsf INTSTA,T0IE ; enable timer0 interrupts bcf CPUSTA,GLINTD ; enable global interrupts return ;---------------------------------------------------------------------------- ; Configuration of analog acquisition port ; ; Connect the analog source and configure the A/D sub-system. Acquisition ; will be done by the interrupt routine synchronously with video generation. ;---------------------------------------------------------------------------- init_adc movlb 5 movlw B'10000000' ; clock=F/64 (2µS conversion), movwf ADCON1 ; left justified, ref 0/5V movlw B'10000000' ; select chanel AD8 movwf ADCON0 bsf ADCON0,ADON ; switch on ADC sub-system return END ;============================================================================ ; - END OF FILE - ;============================================================================