;***************************************************************************** ; Colorgan4.s ; A DSP-based colour organ using digital filters ; Professor M. Csele, Niagara College, Canada, 2010 ; Revised: 2010/04/24 ; ; Uses FIR filters - Output Side Algorithm from chapter 6 of Smith ; ; Other Files Required : p30F6012.gld, p30f6012.inc ; Tools Used : MPLAB IDE version 8.xx ; ; Hardware: ; dsPICDEM board standard hardware (with ds30F6012 chip) ; Line IN provided via AN3/RB3 (via on-board 4KHz analog sampling filter) ; Line OUT provided via MCP4101 (thru on-board analog filter) - for testing ; Indicator LEDs on RD4-RD7 ; ZCD input (active high) on RG12 ; Triac/SCR output LOW channel (red) on RG15 ; Triac/SCR output MID channel (yellow) on RG14 ; Triac/SCR output HIGH channel (green) on RG13 ; ; User Interface (Optional - NOT IMPLEMENTED): ; Pushbutton "Parameter" on RD0 ; Pushbutton "Increase / +" on RD1 ; Pushbutton "Decrease / -" on RD2 ; Pressing "Parameter" selects next parameter to set ; Parameter Order: LO Gain, LO Background, MID Gain, MID Back, HI Gain, Hi Back ; Mode indicated by constant lights on other two channels ; Gain is set in 10% increments from 10% to 500% ; Background is set in steps from 0 to 66 ; Parameters are stored in EEPROM and read upon startup ; ;***************************************************************************** .equ __30F6012, 1 .include "p30f6012.inc" ;............................................................................. ; Configuration bits: ;............................................................................. config __FOSC, CSW_FSCM_OFF & XT_PLL16 ;16xPLL - 64MHz/16MIPs at 4MHz XTAL ; - 118MHz/30MPIs at 7.37MHz XTAL config __FWDT, WDT_OFF ;Turn off Watchdog Timer config __FBORPOR, PBOR_ON & BORV_42 & PWRT_64 & MCLR_EN ;Set Brown-out Reset voltage and config __FGS, CODE_PROT_OFF ;Set Code Protection Off ;............................................................................. ; Global Declarations: ;............................................................................. .global __reset ;Label for first line of code. .global __ICD2RAM ;Allows ICD2 to be used .global __OscillatorFail ;Declare Oscillator Fail trap routine label .global __AddressError ;Declare Address Error trap routine label .global __StackError ;Declare Stack Error trap routine label .global __MathError ;Declare Math Error trap routine label ;............................................................................. ; Storage in Data space (X and Y) ;............................................................................. .section .ybss ;Uninitialized Y-Space .align 2 Samples: .space 512 ;256 samples (16 bits each) .section .xbss ;Uninitialized X-Space .align 2 ;Kernels are in X space (Program memory via PSV) PeakAverageCounter: .space 2 ;Counter for samples to find peaks PeakTemp: .space 2 ;Temp peak for the current period Peak: .space 2 ;Peak amplitude found for last period Gain: .space 2 ;Current gain (from CVA) Sample: .space 2 ;Current incoming sample PeakLo: .space 2 ;Peak filter output for last half-cycle PeakLoTemp: .space 2 ;Temp peak for current period PeakMid: .space 2 PeakMidTemp: .space 2 PeakHi: .space 2 PeakHiTemp: .space 2 PhaseCounter: .space 2 ;Counter for AC cycle trigger points ;............................................................................. ; Program Constants ;............................................................................. .equ TIMECONST, #32000 ;Use 32000 samples (4 seconds) as constant to find peak .equ TARGETPEAK, #0x4000 ;Target peak for samples is 0x4000 ;**** Operational Parameters - all determined by trial-and-error **** ;Background light levels (0=Min, 66=Max) .equ BACKGROUND_LO,#18 ;GREEN .equ BACKGROUND_MID,#12 ;YELLOW .equ BACKGROUND_HIGH,#15 ;RED ;Channel Gain (0=Min, 8=100%, 32=400%) .equ GAIN_LO,#10 ;Low channel gain .equ GAIN_MID,#10 .equ GAIN_HI,#10 ;**** I/O Bit definitions **** .equ SS,#9 ;RG9 = Slave Select for MCP .equ ZCD,#12 ;ZCD input from Optocoupler .equ TRIAC_LO,#15 .equ TRIAC_MID,#14 .equ TRIAC_HI,#13 ;............................................................................. ; Code Section in Program Memory ;............................................................................. .text ;Start of Code section __reset: mov #__SPLIM_init-#128, W15 ;Initialize the Stack Pointer to base address mov #__SPLIM_init, W0 ;Initialize the Stack Pointer Limit Register mov W0, SPLIM nop bset CORCON,#IF ;Select Integer mode for DSP Multiplier bset CORCON,#PSV ;Allow PSV access of frame data in program date clr PSVPAG ;Map lowest program memory page into Data RAM space ;Setup Ports mov #0xFF0F,W0 ;RD4-7=LED Outputs (used for level meter - debug) mov W0,TRISD mov #0x0000,W0 mov w0,PORTD mov #0x1EFF,W0 ;PORTG Outputs on RG13-15, RG9 (SS) mov w0,TRISG clr PORTG bset PORTG,#SS ;set SPI slave select high bclr TRISG,#SS ;set tris bit to output ;Setup hardware to allow ADC conversion on AN2-AN7 mov #0B1111111111110011,W0 ;RB3 = analog input mov W0,ADPCFG mov #0B0000000011100000,W0 ;Set for Auto Sampling (SSRC=111) mov W0,ADCON1 mov #0x0003,W0 ;Select RB3/AN3 as CH0 input .. mov W0,ADCHS clr ADCSSL mov #0B0000000100111001,W0 ;Auto Sample, Tad for 30 MIPs max mov W0,ADCON3 clr ADCON2 ;AVdd,AVss external references on the 6011 chip bset ADCON1,#ADON ;Turn ADC ON bset ADCON1,#SAMP ; start sampling ... ;Setup Timer 1 for sampling delay: Tcy = 16MHz (64MHz Clock) mov #0x8000,w1 ;8KS/s at Tcy=16MHz mov w1,T1CON ;1:1, Int Clk, ON mov #2000,W1 ;Load PR1 for delay, 8KS/s Sample Rate @16MHz Internal mov w1,PR1 ;Setup the SPI port 2 for the MCP chip ;The MCP chip is used as a DAC for analog output when testing filter kernels mov #0x053B,w0 ;Master mode, 16 bits,no frame, 1:2 prescale mov w0,SPI2CON clr SPI2STAT bset SPI2STAT,#SPIEN ;Enable SPI2 ;Startup Splash bset PORTG,#TRIAC_LO mov #2000,w5 SplashLo: call SamplingDelay dec w5,w5 bra nz,SplashLo bclr PORTG,#TRIAC_LO bset PORTG,#TRIAC_MID mov #2000,w5 SplashMid: call SamplingDelay dec w5,w5 bra nz,SplashMid bclr PORTG,#TRIAC_MID bset PORTG,#TRIAC_HI mov #2000,w5 SplashHi: call SamplingDelay dec w5,w5 bra nz,SplashHi bclr PORTG,#TRIAC_HI ;Initialize Peak detector for Constant Volume Algorithm (CVA) clr Peak clr PeakTemp clr PeakLoTemp clr PeakMidTemp clr PeakHiTemp clr PhaseCounter mov #TIMECONST,w1 ;Preload counter for peak detector mov w1,PeakAverageCounter ;***************************************** ;* Main program loop (runs continuously) * ;***************************************** MainLoop: inc PhaseCounter ;Check for ZCD btss PORTG,#ZCD ;Low for ZCD goto NotZcd ;If early in the cycle, omit test for ZCD (ensures peaks only captured once) mov #10,w0 mov PhaseCounter,w1 cp w1,w0 bra lt,NotZcd ;Zero-Cross, grab peaks for lights nop nop nop clr PhaseCounter bclr PORTG,#TRIAC_LO ;Turn off all channels bclr PORTG,#TRIAC_MID bclr PORTG,#TRIAC_HI mov PeakLoTemp,w0 ;Save peak amplitudes from last half-cycle mov w0,PeakLo clr PeakLoTemp mov PeakMidTemp,w0 ;Save peak amplitudes from last half-cycle mov w0,PeakMid clr PeakMidTemp mov PeakHiTemp,w0 ;Save peak amplitudes from last half-cycle mov w0,PeakHi clr PeakHiTemp NotZcd: call SampleIn ;Read a sample from the ADC (12-bits resolution) mov #0x800,w1 ;Make into a signed number (16 bit) sub w0,w1,w0 mov w0,Sample ;Peak Detector: Constant Volume Algorithm (CVA) btsc Sample,#15 ;Test only positive numbers goto PeakDone mov PeakTemp,w1 cp w0,w1 ;Check if sample > old peak found bra lt,NoNewPeak mov w0,PeakTemp ;Update new peak reading NoNewPeak: dec PeakAverageCounter cp0 PeakAverageCounter bra nz,PeakDone mov #TIMECONST,w1 ;Reload peak detector counter mov w1,PeakAverageCounter ;Update peak for the past