PROCESSOR 16F883 ; RADIX DEC INCLUDE "P16F883.INC" ; Imosta i bit di configurazione ;__CONFIG _CONFIG1, _DEBUG_ON & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_OFF & _WDT_OFF & _INTOSCIO ;__CONFIG _CONFIG2, _BOR21V & _WRT_OFF __CONFIG _CONFIG1, _FOSC_INTRC_NOCLKOUT & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOR_ON & _IESO_OFF & _FCMEN_OFF & _LVP_OFF __CONFIG _CONFIG2, _BOR40V & _WRT_OFF ; costanti per le routine matematiche B0 equ 0 B1 equ 1 B2 equ 2 B3 equ 3 B4 equ 4 B5 equ 5 B6 equ 6 B7 equ 7 MSB equ 7 LSB equ 0 #define _C STATUS,0 #define _Z STATUS,2 FPFLAGS equ 0x2A ; floating point library exception flags IOV equ 0 ; bit0 = integer overflow flag FOV equ 1 ; bit1 = floating point overflow flag FUN equ 2 ; bit2 = floating point underflow flag FDZ equ 3 ; bit3 = floating point divide by zero flag NAN equ 4 ; bit4 = not-a-number exception flag DOM equ 5 ; bit5 = domain error exception flag RND equ 6 ; bit6 = floating point rounding flag, 0 = truncation ; 1 = unbiased rounding to nearest LSB SAT equ 7 ; bit7 = floating point saturate flag, 0 = terminate on ; exception without saturation, 1 = terminate on ; exception with saturation to appropriate value InizioMatrice equ 160 ; prima locazione di memoria della matrice LunghezzaMatrice equ 31 ; lunghezza della matrice SogliaDeb equ 5 ; soglia per il debounching del pulsante mode DurataAnimazione equ 65 ; durata anumazione ; Riserva spazio per le variabili del programma udata 32 ; zona di memoria "general purpose register" (nel banco di memoria 0) cfh res 1 ; 32 contatore che determina quanti campionamenti si eseguono in una finestra cfl res 1 ; 33 eih res 1 ; 34 valore dell'energia istantanea di un campionamento eil res 1 ; 35 e' il valore istantaneo del segnale campionato dall'ad meno 512 in valore assoluto efl res 1 ; 36 energia di una finestra, contatore che sommma i valori di energia in una finestra di tempo efh res 1 ; 37 efol res 1 ; valore della finestra precedente (la finestra attuale e' la media tra la finestra attuale e la precedente) efoh res 1 ; per evitare che picchi di energia caschino a meta' tra una finestra e l'altra e non vengano ; visti efll res 1 ; 39 quando una finestra di tempo e' completa il valore ef viene copiato in efl eflh res 1 ; 40 flag res 1 ; bit 0 se settato allora e' stato memorizzato un nuovo valore in efl ; bit 1 indica se c'e' stato un overflow nella sommatoria dei valori di energia di una finestra ; bit 2 c'e' il beat ; bit 3 indica la posizione del tasto mode + o - fi res 1 ; variabile che conta alla rovesca per determinare la durata della fase iniziale maxl res 1 maxh res 1 i res 1 sml res 1 ; somma della matrice smh res 1 con res 1 ; contatore per le animazioni effetto res 1 ; variabile che indica l'animazione selezionata deb res 1 ; contatore per il debounching del pulsante Mode scala res 1 dish res 1 disl res 1 disi res 1 ; variabili per le routine matematiche AARGB7 res 1 AARGB6 res 1 AARGB5 res 1 AARGB4 res 1 AARGB3 res 1 AARGB2 res 1 AARGB1 res 1 AARGB0 res 1 SIGN res 1 BARGB3 res 1 BARGB2 res 1 BARGB1 res 1 BARGB0 res 1 TEMPB3 res 1 TEMPB2 res 1 TEMPB1 res 1 TEMPB0 res 1 LOOPCOUNT res 1 PortaB res 1 PortaC res 1 PortaA res 1 CBLOCK H'70' ; zona di memoria comune ai 4 banchi di memoria ; spazio di 16 byte W_TEMP STATUS_TEMP PCLATH_TEMP ENDC ORG 0000h ; reset vector goto Inizio ;8888888 888 888 ; 888 888 888 ; 888 888 888 ; 888 88888b. 888888 .d88b. 888d888 888d888 888 888 88888b. 888888 ; 888 888 "88b 888 d8P Y8b 888P" 888P" 888 888 888 "88b 888 ; 888 888 888 888 88888888 888 888 888 888 888 888 888 ; 888 888 888 Y88b. Y8b. 888 888 Y88b 888 888 d88P Y88b. ;8888888 888 888 "Y888 "Y8888 888 888 "Y88888 88888P" "Y888 ; 888 ; 888 ; 888 ORG 0004h ; interrupt vector MOVWF W_TEMP ;Copy W to TEMP register SWAPF STATUS,W ;Swap status to be saved into W ; bcf STATUS,IRP ;Swaps are used because they do not affect the status bits MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register movf PCLATH,W movwf PCLATH_TEMP clrf PCLATH BANKSEL INTCON btfss INTCON,T0IF ; verifica se e' stato il timer0 a causare l'interrupt goto NoTimer0Interrupt bcf INTCON,T0IF ; resetta l'interrupt su timer 0 BANKSEL TMR0 bsf TMR0,7 ; porta avanti il timer 0 di 128 + 64 bsf TMR0,6 BANKSEL ADRESH ; legge il convertitore ad e lo copia in ei (banco di memoria 0) movf ADRESH,w movwf eih BANKSEL ADRESL ; banco di memoria 1 movf ADRESL,w BANKSEL eil ; ritorna al banco di memoria 0 movwf eil BSF ADCON0,GO ; start conversion AD (banco memoria 0) btfss eih,1 ; se il valore e' maggiore o uguale a 512 ; allora calcola valore - 512 goto SottEinversa ; altrimenti fa la sottrazione inversa : 512 - valore bcf eih,1 bcf PORTA,3 ; adatta la massa virtuale dell'amplificatore operazionale alla meta' del conv AD goto DopoSotte SottEinversa: movlw 255 xorwf eil,f movlw 1 XORWF eih,f bsf PORTA,3 ; adatta la massa virtuale dell'amplificatore operazionale alla meta' del conv AD DopoSotte: ; ef = ef + ei incrementa ef con il valore di ei movf eil,w addwf efl,f btfsc _C ; verifica se c'è stato un riporto incf efh,F ; se c'è stato lo memorizza nella variabile TEMP movf eih,w addwf efh,f btfsc _C bsf flag,1 ; se c'e' stato un overflow setta il flag BANKSEL cfl decfsz cfl,f ; decrementa il contatore cfl goto NonRiportoCf decfsz cfh,f ; decrementa il contatore cfh goto NonRiportoCf movlw 2 ; memorizza il valore 750 in cfh e cfl movwf cfh movlw 238 movwf cfl btfss flag,1 ; c'e' stato un overflow goto NoOverflowEf movlw 255 movwf efl movwf efh bcf flag,1 ; azzera il flag di overflow NoOverflowEf: bcf _C ; ef = ef /2 rrf efh rrf efl MOVF efl,W ; efo = efo + ef ADDWF efol,f MOVF efh,W BTFSC _C INCF efh,W ADDWF efoh,f movf efl,w ; efo = ef movwf efol movf efh,w movwf efoh movf efol,w ; efl = efo movwf efll movf efoh,w movwf eflh bsf flag,0 ; setta il flag che indica che si e' conclusa una finestra clrf efl ; azzera ef clrf efh incf con NonRiportoCf: NoTimer0Interrupt: EsceDaInterrupt: ; Esce dagli interrupt movf PCLATH_TEMP,W movwf PCLATH SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W ;(sets bank to original state) MOVWF STATUS ;Move W into STATUS register SWAPF W_TEMP,F ;Swap W_TEMP SWAPF W_TEMP,W ;Swap W_TEMP into W retfie ;8888888 d8b d8b ; 888 Y8P Y8P ; 888 ; 888 88888b. 888 88888888 888 .d88b. ; 888 888 "88b 888 d88P 888 d88""88b ; 888 888 888 888 d88P 888 888 888 ; 888 888 888 888 d88P 888 Y88..88P ;8888888 888 888 888 88888888 888 "Y88P" Inizio: ; Imposta il registro dell'oscillatore interno BANKSEL OSCCON ; il registro e' nel banco di memoria 1 movlw B'11110000' ; usa il quarzo esterno movwf OSCCON ; movwf OSCCON ; Imposta la porta A ; ra0 = ingresso analogico microfono ; ra1 = ingresso digitale pulsante mode + ; ra2 = ingresso digitale pulsante mode - ; ra3 = uscita filtro massa virtuale ; ra4 = uscita led rosso pulsanti ; ra5 = uscita led verde sopra ; ra6 = uscita led verde basso sx ; ra7 = uscita led verde basso dx BANKSEL PORTA CLRF PORTA ; Init PORTA BANKSEL ANSEL movlw B'00000001' ; Solo il canale 0 in analogico movwf ANSEL BCF STATUS,RP1 ; Bank 1 BANKSEL TRISA ; movlw B'00000111' ; AN0 input microfono ; ra 1 2 input digitale ; ra 3 4 5 6 7 output MOVWF TRISA BANKSEL PORTA bsf PORTA,4 bsf PORTA,5 bsf PORTA,6 bsf PORTA,7 ; Imposta il convertitore analogico digitale BANKSEL ADCON1 MOVLW B'10000000' ;right justify MOVWF ADCON1 ;Vdd and Vss as Vref BANKSEL ADCON0 ; MOVLW B'10000001' ;ADC clock FOSC/32, seleziona canale AN0 accende il convertitore AD MOVWF ADCON0 ; Imposta la porta C BANKSEL PORTC CLRF PORTC BANKSEL TRISC MOVLW B'00000000' ; All output MOVWF TRISC ; Imposta la porta B BANKSEL PORTB CLRF PORTB BANKSEL TRISB MOVLW B'00000000' ; All output MOVWF TRISB ; Imposta il timer0 e gli interrupt BANKSEL OPTION_REG bcf OPTION_REG,T0CS ;il timer 0 viene incrementato usando il clock interno bsf OPTION_REG,PSA ; il prescaler e' assegnato al watch dog timer, il timer0 non ha prescaler BANKSEL TMR0 clrf TMR0 ; azzera il timer 0 BANKSEL INTCON bsf INTCON,T0IE ; attiva l'interrupt per il timer 0 bsf INTCON,GIE ; Attiva gli interrupt ; Inizializza le variabili BANKSEL flag clrf flag movlw DurataAnimazione ; durata della fase iniziale movwf fi clrf deb movlw 4 movwf effetto ResettaMax: movlw 20 movwf maxl ; inizializza la variabile max clrf maxh ; per test ;pertest: ; banksel PORTB ; movlw 255 ; movwf PORTB ; goto pertest ;888b d888 d8b 888 ;8888b d8888 Y8P 888 ;88888b.d88888 888 ;888Y88888P888 8888b. 888 88888b. 888 .d88b. .d88b. 88888b. ;888 Y888P 888 "88b 888 888 "88b 888 d88""88b d88""88b 888 "88b ;888 Y8P 888 .d888888 888 888 888 888 888 888 888 888 888 888 ;888 " 888 888 888 888 888 888 888 Y88..88P Y88..88P 888 d88P ;888 888 "Y888888 888 888 888 88888888 "Y88P" "Y88P" 88888P" ; 888 ; 888 ; 888 BANKSEL PORTC MainLoop: banksel flag btfss flag,0 ; e' terminata una nuova finestra goto NonNuovaFinestra ; movf fi,f BTFSC STATUS, Z ; Skip if not zero goto CalcolaMax DECF fi, F btfsc _Z goto ResettaMax movf fi,w ; passaggio 1 xorlw 64 btfss _Z goto dopoAnim1 Anim1: bsf PORTA,4 bcf PORTA,5 bcf PORTA,6 bcf PORTA,7 dopoAnim1: movf fi,w ; passaggio 2 xorlw 48 btfss _Z goto dopoAnim2 Anim2: bcf PORTA,4 bcf PORTA,5 bsf PORTA,6 bcf PORTA,7 dopoAnim2: movf fi,w ; passaggio 3 xorlw 32 btfss _Z goto dopoAnim3 Anim3: bcf PORTA,4 bcf PORTA,5 bcf PORTA,6 bsf PORTA,7 dopoAnim3: movf fi,w ; passaggio 4 xorlw 16 btfss _Z goto dopoAnim4 Anim4: bsf PORTA,4 bsf PORTA,5 bcf PORTA,6 bcf PORTA,7 dopoAnim4: bcf _C btfsc fi,3 bsf _C btfsc fi,2 bcf _C rlf PortaC,f rlf PortaB,f ; ----------------------------------------------------------------------------- goto NonCalcolaMax CalcolaMax: ; il valore massimo viene diminuito di un pelino DimMax equ 5 MinMax equ 250 movf maxh,f btfss _Z goto MaxHnonZero MaxHZero: movlw DimMax subwf maxl,f movlw MinMax subwf maxl,f btfsc _C goto DopoDecrementaMax movlw MinMax movwf maxl MaxHnonZero: movlw DimMax subwf maxl,f btfss _C decf maxh DopoDecrementaMax: ; DECF maxh, F ; MOVF maxl, F ; Test lo byte ; BTFSC STATUS, Z ; Skip if not zero ; DECF maxh, F ; DECF maxl, F ; Decrement lo byte ; se il valore attuale e' maggiore del valore massimo allora massimo viene aggiornato con valore attuale movf maxh,w subwf eflh,w btfss _Z goto NonUguale1 movf maxl,w subwf efll,w btfss _C goto NoMaggiore0 movf efll,w movwf maxl NoMaggiore0: goto NoMaggiore1 NonUguale1: btfss _C goto NoMaggiore1 movf eflh,w movwf maxh movf efll,w movwf maxl NoMaggiore1: NonCalcolaMax: ; un una matrice di 20 o 40 numeri viene scartato il piu vecchio, spostati i valori di una posizione e inserito il piu nuovo ; la somma della matrice viene aggiornata sottraendo il valore piu vecchio e aggiungendo il nuovo ; viene calcolata la media della matrice ; il valore istantaneo del vu meter = valore istantaneo * 256 * 256 / valore massimo movf eflh,w ; A = efl * 256 * 256 movwf AARGB0 movf efll,w movwf AARGB1 clrf AARGB2 clrf AARGB3 ; clrf AARGB0 ; clrf AARGB1 ; movlw 2 ; movwf AARGB2 ; clrf AARGB3 ; clrf BARGB0 ; clrf BARGB1 ; clrf BARGB2 ; movlw 5 ; movwf BARGB3 clrf BARGB0 ; B = Max clrf BARGB1 movf maxh,w movwf BARGB2 movf maxl,w movwf BARGB3 movlw HIGH 0800h movwf PCLATH call DivisioneSenzaSegno movf AARGB2,w ; copia AARGB2 (byte piu significativo) alla fine della matrice movwf InizioMatrice+LunghezzaMatrice+1 clrf sml ; azzera la somma clrf smh movlw InizioMatrice ; indirizza alla prima locazione di memoria movwf FSR ; puntatore alla prima posizione CicloSpostaMatrice: incf FSR,f ; incrementa di uno il puntatore movf INDF,w ; copia il contenuto della cella in w decf FSR,f ; decrementa di uno movwf INDF ; copia w nella cella addwf sml,f ; aggiunge w a sml btfsc _C ; controlla se ce' stato il riporto incf smh ; in caso aumenta smh incf FSR ; incrementa il puntatore movf FSR,w ; confronta se e' arrivato alla fine della matrice xorlw InizioMatrice+LunghezzaMatrice+1 btfss _Z ; esce dal ciclo se e' arrivato alla fine goto CicloSpostaMatrice bcf _C ; divide per 32 rrf smh,f rrf sml,f bcf _C rrf smh,f rrf sml,f bcf _C rrf smh,f rrf sml,f bcf _C rrf smh,f rrf sml,f bcf _C rrf smh,f rrf sml,f ; in questo punto solo sml dovrebbe avere un valore clrf smh bcf _C rrf sml,w movwf smh movwf sml bcf _C rrf smh,f movf smh,w addwf sml,f bcf _C rrf smh,w addwf sml,f ; sml = sml + ( sml / 4 ) + ( sml / 8 ) = sml * 1.375 btfsc _C goto NoBeat movf sml,w subwf AARGB2,w ; confronta il valore attuale con la media *1.5 btfss _C goto NoBeat Beat: bsf flag,2 goto AfterBeat NoBeat: bcf flag,2 AfterBeat: ;-------------------------------------------------------------------- ; Legge il pulsante Mode btfss PORTA,2 goto ModeMeno btfss PORTA,1 goto ModePiu NoMode: movlw SogliaDeb subwf deb,w clrf deb btfss _C goto DopoMode ; e' stato premuto il tasto mode abbastanza a lungo btfss flag,3 incf effetto,f btfsc flag,3 decf effetto,f movlw DurataAnimazione movwf fi goto DopoMode ModePiu: bsf flag,3 goto IncrementaDeb ModeMeno: bcf flag,3 IncrementaDeb: incfsz deb,f incf deb,f decf deb,f DopoMode: movf fi,f btfss _Z goto UltimoEffetto Effetto3: movf effetto,w ; effetto 3 vu meter scorrevole xorlw 3 btfsc _Z goto VuMeterPuntiforme Effetto0: movf effetto,w ; effetto 0 Vu meter puntiforme xorlw 0 btfss _Z goto Effetto1 VuMeterPuntiforme: movlw 10 subwf scala,f btfss _C clrf scala movf AARGB2,w subwf scala,w movf scala,w btfss _C movf AARGB2,w movwf scala movwf i bcf _C rrf i,f bcf _C rrf i,f bcf _C rrf i,f bcf _C rrf i,f ; per test ; imposta i ; movlw 14 ; movwf i incf i,f clrf AARGB7 clrf AARGB6 bsf _C CicloBarraVu: rlf AARGB7,f rlf AARGB6,f decfsz i,f goto CicloBarraVu clrf PORTA bsf PORTA,4 btfss flag,2 goto NoAccendeLuciBeat bsf PORTA,5 bsf PORTA,6 bsf PORTA,7 NoAccendeLuciBeat: movf effetto,w xorlw 0 btfss _Z goto EffettoScorrevole movf AARGB7,w movwf PortaC movf AARGB6,w movwf PortaB goto DopoEffettoScorrevole EffettoScorrevole: bcf _C rrf PortaB,f rrf PortaC,f movf AARGB7,w iorwf PortaC,f movf AARGB6,w iorwf PortaB,f ; bcf _C ; rrf AARGB6,f ; rrf AARGB7,f ; bcf _C ; rrf AARGB6,f ; rrf AARGB7,f; ; comf AARGB6,f ; comf AARGB7,f ; movf AARGB7,w ; andwf PORTC,f ; movf AARGB6,w ; andwf PORTB,f DopoEffettoScorrevole: Effetto1: movf effetto,w ; effetto 1 Luce strobo scorrevole xorlw 1 btfss _Z goto Effetto2 bcf _C rrf PortaC,f rrf PortaA,f clrf PORTA btfsc PortaA,7 bsf PORTA,5 btfsc PortaA,6 bsf PORTA,5 btfsc PortaA,6 bsf PORTA,6 btfsc PortaA,5 bsf PORTA,4 bcf _C rlf PortaB,f bcf i,0 btfss flag,2 goto NoStrobo SiStrobo: bsf i,0 btfss con,3 bcf i,0 btfss con,2 bcf i,0 btfss con,1 bcf i,0 btfss con,0 bcf i,0 btfss i,0 goto DopoStrobo bsf PortaB,0 bsf PortaC,7 goto DopoStrobo NoStrobo: movlw 254 movwf con DopoStrobo: Effetto2: movf effetto,w ; effetto 2 Luce strobo xorlw 2 btfss _Z goto DopoEffetto2 bcf i,0 btfss flag,2 goto NoStrobo1 SiStrobo1: bsf i,0 btfss con,3 bcf i,0 btfss con,2 bcf i,0 btfss con,1 bcf i,0 btfss con,0 bcf i,0 btfss i,0 goto SpegneStrobo1 movlw B'00000010' xorwf i,f btfss i,1 StroboUno: goto StroboDue movlw B'00001111' movwf PortaB movlw B'11110000' movwf PortaC goto AccendeScatolaStrobo StroboDue: movlw B'00001111' movwf PortaC movlw B'11110000' movwf PortaB AccendeScatolaStrobo: bsf PORTA,7 bsf PORTA,6 bsf PORTA,5 bsf PORTA,4 goto DopoStrobo1 NoStrobo1: movlw 254 movwf con SpegneStrobo1: clrf PortaC clrf PortaB bcf PORTA,7 bcf PORTA,6 bcf PORTA,5 bcf PORTA,4 DopoStrobo1: DopoEffetto2: Effetto4: movf effetto,w ; effetto 4 vu meter tura su xorlw 4 btfss _Z goto DopoEffetto4 VuMeterPuntiforme1: movlw 10 subwf scala,f btfss _C clrf scala movf AARGB2,w subwf scala,w movf scala,w btfss _C movf AARGB2,w movwf scala movwf i bcf _C rrf i,f bcf _C rrf i,f bcf _C rrf i,f bcf _C rrf i,f clrf AARGB7 clrf AARGB6 incf i,f NonSuperioreTiraSu: CicloBarraVu1: bsf _C rlf AARGB7,f rlf AARGB6,f decfsz i,f goto CicloBarraVu1 bsf PORTA,4 bsf PORTA,5 bsf PORTA,6 bsf PORTA,7 movf AARGB7,w movwf PortaC movf AARGB6,w movwf PortaB DopoEffetto4: ; ultimo effetto (riporta la variabile effetto dopo che ha superato il massimo) UltimoEffetto: movf PortaB,w movwf PORTB movf PortaC,w movwf PORTC movf effetto,w ; xorlw 5 btfss _Z goto DopoUltimoEffetto clrf effetto DopoUltimoEffetto: ; primo effetto (riporta la variabile effetto a zero dopo che e' andata in negativo) PrimoEffetto: movf effetto,w xorlw 255 btfss _Z goto DopoPrimoEffetto movlw 4 movwf effetto DopoPrimoEffetto: ; movlw 17 ; i = 17 ; movwf i ;CicloLogaritmo: ; decf i,f ; bsf _C ; rlf AARGB0,f ; rlf AARGB1,f ; btfss _C ; goto CicloLogaritmo ; prova visuallizza vu meter ; il beat viene determinato se valore istantaneo e' maggiore di 1.4 volte media ; per fare prima prendo il valore medio e divido per due, poi questo valore lo aggiungo al valore medio e ottengo media * 1.5 bcf flag,0 NonNuovaFinestra: goto MainLoop ; Pagina 1 del program memory org 0800h ; Divisione senza segno DivisioneSenzaSegno: call FXD3232U goto RitornaDa1a0 ; Routine matematiche INCLUDE "FXD22.A16" ; Ritorna dalla chiamata e imposta la pagina di programma a 0 RitornaDa1a0: movlw HIGH 0005h ; imposta il program counter latch H sulla pagina 0 prima di tornare dalla chiamata movwf PCLATH return END