Last active
July 1, 2020 18:31
-
-
Save neuro-sys/e5a7834cc10041fef97124845972a56c to your computer and use it in GitHub Desktop.
Wrote this mess when I was learning assembly with PIC for the first time back about 10 years ago.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#INCLUDE p16f690.inc | |
PROCESSOR P16F690 | |
__CONFIG _INTRC_OSC_NOCLKOUT&_FCMEN_ON&_IESO_ON&_BOR_ON&_CPD_OFF&_CP_OFF&_MCLRE_OFF&_PWRTE_OFF&_WDT_OFF | |
ERRORLEVEL -302 ; SUPRESS BANK WARNING. | |
RADIX DEC | |
CBLOCK 0x20 ; RAM AREA | |
PULSE_TEMP ; PULSE FREQUENCY ALTERNATING FLAG | |
ISR_W_TEMP ; ISR STATE SAVING REGISTERS | |
ISR_STATUS_TEMP | |
ISR_PCLATH_TEMP | |
IS_PLAYING | |
SILENT_NOTE | |
DURATION | |
NOTE | |
COUNTER | |
TEMP | |
ENDC | |
ORG 0x0 ; RESET VECTOR | |
GOTO RESET | |
ORG 0x4 ; INTERRUPT VECTOR | |
MOVWF ISR_W_TEMP ; SAVE PREVIOUS STATE. | |
SWAPF STATUS,W | |
MOVWF ISR_STATUS_TEMP | |
BANKSEL PCLATH | |
MOVF PCLATH,W | |
MOVWF ISR_PCLATH_TEMP | |
BANKSEL PIR1 | |
BTFSC PIR1,TMR1IF ; IS TIMER1 THE SOURCE OF INTERRUPT? | |
GOTO TIMER1_ISR ; JUMP TO ITS ISR | |
TIMER0_ISR: | |
BTFSS IS_PLAYING,0 ; IS PLAYING? | |
GOTO TIMER0_EXIT ; THEN DON'T ALTERNATE THE PULSE | |
MOVLW 0xFF | |
XORWF NOTE,W ; DOES NOTE EQUAL TO 0xFF? | |
BTFSC STATUS,Z | |
GOTO PULSE_OFF ; YES, IT'S A MUTE NOTE, DON'T ALTERNATE. | |
BANKSEL PORTA | |
BTFSC PULSE_TEMP,0 ; CHECK THE LAST STATE OF PULSE, IS IT ZERO? | |
GOTO PULSE_ON | |
PULSE_OFF: | |
BCF PORTA,1 | |
BSF PULSE_TEMP,0 | |
GOTO TIMER0_EXIT | |
PULSE_ON: | |
BSF PORTA,1 | |
BCF PULSE_TEMP,0 | |
TIMER0_EXIT: | |
BANKSEL TMR0 | |
MOVF NOTE,W ; SET THE NOTE'S FREQUENCY DELAY EACH TIME | |
MOVWF TMR0 ; IN CASE IT WAS CHANGED BY TIMER1. | |
BANKSEL INTCON | |
BCF INTCON,T0IF ; ENABLE TIMER0 AGAIN. | |
ISR_EXIT: | |
SWAPF ISR_STATUS_TEMP,W ; RESTORE PREVIOUS STATE. | |
MOVWF STATUS | |
SWAPF ISR_W_TEMP,F | |
SWAPF ISR_W_TEMP,W | |
BANKSEL PCLATH | |
MOVF ISR_PCLATH_TEMP,W | |
MOVWF PCLATH | |
RETFIE | |
TIMER1_ISR: | |
BTFSS IS_PLAYING,0 ; IS THE MUSIC PLAYING? | |
GOTO TIMER1_EXIT ; NO, GET OUT. | |
BANKSEL PCLATH | |
MOVLW HIGH NOTE_DELAY_FACTORS | |
MOVWF PCLATH | |
MOVF COUNTER,W | |
CALL MUSIC ; GET THE NOTE FROM MUSIC SHEET | |
MOVWF TEMP ; SAVE IT TO TEMP. | |
MOVLW 0x80 | |
XORWF TEMP,W ; IS IT ENDED? (0x80) | |
BTFSC STATUS,Z | |
GOTO RESET_COUNTER ; YES, REWIND THE SONG. | |
MOVLW 0xFF ; IS IT MUTE NOTE? (0xFF) | |
XORWF TEMP,W | |
BTFSS STATUS,Z | |
GOTO NOT_MUTE ; NO, CONTINUE AS USUAL. | |
MOVLW 0xFF ; YES WE HAVE A MUTE NOTE. | |
MOVWF NOTE ; SKIP DELAY FACTOR TABLE. | |
GOTO MUTE_END | |
NOT_MUTE: | |
MOVF TEMP,W ; RESTORE THE NOTE FROM TEMP. | |
CALL NOTE_DELAY_FACTORS ; GET THE FREQUENCY DELAY FOR THE NOTE | |
MUTE_END: | |
MOVWF NOTE ; STORE IT FOR TIMER0 TO PROCESS | |
; SET DURATION OF NOTE | |
INCF COUNTER,F ; THE SECOND VALUE IN MUSIC SHEET TABLE | |
BANKSEL T1CON ; IS THE DURATION DIVIDER. | |
BCF T1CON,TMR1ON ; TURN OFF TIMER1 TO MAKE CHANGES TO IT | |
MOVF COUNTER,W | |
CALL MUSIC ; GET THE SECOND VALUE/DURATION DIVIDER. | |
BANKSEL TMR1H | |
MOVWF TMR1H ; STORE IT IN THE HIGH BYTE OF TIMER1 | |
BANKSEL T1CON ; COUNTER | |
BSF T1CON,TMR1ON ; TURN ON TIMER1 TO ACTIVE IT. | |
INCF COUNTER,F ; THE NEXT NOTE IN MUSIC SHEET TABLE. | |
TIMER1_EXIT: | |
BANKSEL PIR1 | |
BCF PIR1,TMR1IF | |
GOTO ISR_EXIT | |
RESET_COUNTER: | |
CLRF COUNTER ; REWIND THE MUSIC SHEET COUNTER | |
MOVLW 0xFF | |
MOVWF NOTE ; MUTE IT FOR THE REWIND DELAY | |
GOTO TIMER1_EXIT | |
ORG 0x100 | |
RESET: | |
MOVLW HIGH NOTE_DELAY_FACTORS | |
MOVWF PCLATH | |
BANKSEL TRISA | |
CLRF TRISA ; MAKE ALL PORTA OUTPUT. | |
BANKSEL PORTA | |
CLRWDT ; CLEAR WATCH-DOG TIMER SO THAT PRESCALER | |
; BELONGS TO TIMER0 | |
BANKSEL OPTION_REG | |
MOVLW B'11010011' ; TIMER0 HAS 1:16 PRESCALER | |
ANDWF OPTION_REG,F | |
BANKSEL T1CON ; TIMER 1 HAS 1:8 PRESCALER | |
BCF T1CON,TMR1ON | |
BSF T1CON,T1CKPS1 | |
BSF T1CON,T1CKPS0 | |
BCF T1CON,T1OSCEN | |
BCF T1CON,TMR1CS | |
CLRF TMR1L | |
CLRF TMR1H | |
BSF T1CON,TMR1ON | |
BANKSEL INTCON | |
BSF INTCON,T0IE ; ENABLE INTERRUPTS. | |
BSF INTCON,GIE | |
CALL CLEAR_RAM | |
BSF IS_PLAYING,0 | |
START: | |
GOTO START | |
; FIRST BYTE IS THE NOTE OFFSET FROM NOTE_DELAY_FACTORS TABLE. | |
; SECOND BYTE IS THE DURATION DIVIDER. 0 IS A ROUGHLY LONG. 0x80 IS THE HALF OF | |
; THAT. ETC... | |
; 0x80 IN THE FIRST BYTE MARKS THE ENDING OF THE SONG. | |
; 0xFF IN THE FIRST BYTE MEANS A MUTE NOTE. | |
MUSIC: | |
ADDWF PCL,F | |
DT 10,0x80 | |
DT 0xFF,0x80 | |
DT 10,0x80 | |
DT 0xFF,0x80 | |
DT 10,0x80 | |
DT 0xFF,0x80 | |
DT 6,0x80 | |
DT 0xFF,0xC0 | |
DT 13,0xC0 | |
DT 10,0x80 | |
DT 0xFF,0x80 | |
DT 6,0x80 | |
DT 0xFF,0xC0 | |
DT 13,0xC0 | |
DT 10,0x0 | |
DT 0xFF,0 | |
DT 17,0x80 | |
DT 0xFF,0x80 | |
DT 17,0x80 | |
DT 0xFF,0x80 | |
DT 17,0x80 | |
DT 0xFF,0x80 | |
DT 18,0x80 | |
DT 0xFF,0xC0 | |
DT 13,0xC0 | |
DT 9,0x80 | |
DT 0xFF,0x80 | |
DT 6,0x80 | |
DT 0xFF,0xC0 | |
DT 13,0xC0 | |
DT 10,0x0 | |
DT 0xFF,0 | |
DT 18,0xC0 | |
DT 15,0xC0 | |
DT 12,0xC0 | |
DT 9,0xC0 | |
DT 15,0xC0 | |
DT 12,0xC0 | |
DT 9,0xC0 | |
DT 6,0xC0 | |
DT 12,0xC0 | |
DT 9,0xC0 | |
DT 6,0xC0 | |
DT 3,0xC0 | |
DT 9,0xC0 | |
DT 6,0xC0 | |
DT 3,0xC0 | |
DT 0,0xC0 | |
DT 10,0x0 | |
DT 0x80 | |
; (0xFF - WREG) * TIMER0_PRESCALER EQUALS HALF OF THE NOTE'S PULSE WIDTH. | |
; IT'S HALF, BECAUSE IT'S %50 DUTY-CYCLE. | |
NOTE_DELAY_FACTORS: | |
ADDWF PCL,F | |
RETLW 82 ;180hz | |
RETLW 92 ;190hz | |
RETLW 101 ;202hz | |
RETLW 110 ;214hz | |
RETLW 118 ;226hz | |
RETLW 125 ;240hz | |
RETLW 133 ;254hz | |
RETLW 140 ;269hz | |
RETLW 146 ;285hz | |
RETLW 152 ;302hz | |
RETLW 158 ;320hz | |
RETLW 164 ;339hz | |
RETLW 169 ;359hz | |
RETLW 174 ;381hz | |
RETLW 178 ;404hz | |
RETLW 183 ;428hz | |
RETLW 187 ;453hz | |
RETLW 190 ;480hz | |
RETLW 194 ;509hz | |
RETLW 198 ;539hz | |
RETLW 201 ;571hz | |
RETLW 204 ;605hz | |
RETLW 207 ;641hz | |
RETLW 210 ;679hz | |
RETLW 0 | |
CLEAR_RAM: | |
MOVLW 0x20 | |
MOVWF FSR | |
CLEAR_NEXT: | |
CLRF INDF | |
INCF FSR,F | |
BTFSS FSR,4 | |
GOTO CLEAR_NEXT | |
RETURN | |
END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment