; Dublin Pedestrian Crossing Lights Emulator ; Filename: crossing.asm ; This is a state machine that emulates the sound of Dublin's pedestrian crossings. ; When button is pressed it waits a random time then goes green. ; V0.0 151115 New project ; V0.1 151116 TMR0 interrupt, CONFIG bits ; V0.2 151117 pew sound (second version) ; V0.3 151117 pew sound (third version) ; V0.4 151118 pew sound (final version) ; V0.5 151119 pop ; V1.0 151122 Release, MCLR enabled, BTN -> GPIO2 LIST P=12F629, F=INHX8M #include <P12F629.INC> __CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_OFF ; Equates RESET_V EQU 0x00 ; Address of RESET Vector OSC_FREQ EQU D'4000000' ; Oscillator Frequency is 4.0 MHz ; Registers PERIOD EQU 0x20 ; Determines sound frequency RND EQU 0x21 ; Used as cheap source of randomness (PIPCOUNT) STATE EQU 0x22 ; Only one bit should be active at any time but the test takes the first set one PIPON EQU 0x23 ; pip/pop active PIPOFF EQU 0x24 ; pip/pop silent PIPCOUNT EQU 0x25 ; # of pips/pops to generate ; Ports #define RED GPIO,0 ; Red LED #define GRN GPIO,1 ; Green LED #define BTN GPIO,2 ; Call Button, WPU bit set on POR #define SPKN GPIO,4 ; Negative terminal of speaker #define SPKP GPIO,5 ; Positive terminal of speaker #define IDLE STATE,0 ; Wait for button press, no sound #define WAIT STATE,1 ; Button pressed, wait for green, don't generate pip #define WAITP STATE,2 ; Button pressed, wait for green, generate pip #define PREPEW STATE,3 ; Wait before sliding tone, red light #define PEW STATE,4 ; Generate sliding tone, green light #define PREPOP STATE,5 ; Short silence before pop, green light #define POP STATE,6 ; Generate pop, green light #define NOPOP STATE,7 ; Don't generate pop, green light ORG 0x00 GOTO START ORG 0x04 ; Interrupt handlers BCF INTCON,T0IF ; Clear source of interrupt (TMR0) MOVLW 0xF0 MOVWF TMR0 TESTIDLE BTFSC IDLE GOTO BTNCHK TESTPIP BTFSC WAITP GOTO GENPIP TESTNOPIP BTFSC WAIT GOTO NOGENPIP TESTPREPEW BTFSC PREPEW GOTO GENPREPEW TESTPEW BTFSC PEW GOTO GENPEW TESTPREPOP BTFSC PREPOP GOTO GENPREPOP TESTPOP BTFSC POP GOTO GENPOP TESTNOPOP BTFSC NOPOP GOTO NOGENPOP GOTO ENDINT BTNCHK ; IDLE set BTFSC BTN GOTO ENDINT BCF IDLE BSF WAITP ; Change state to generate pip MOVLW 0x0C ; 1 kHz MOVWF PERIOD MOVFW RND ANDLW 0x0F MOVWF PIPCOUNT BTFSC PIPCOUNT,3 GOTO COUNTOK BTFSC PIPCOUNT,2 GOTO COUNTOK ; Test for PIPCOUNT <4 MOVLW 0x03 IORWF PIPCOUNT,1 ; PIPCOUNT is minimum 3 and max 15 COUNTOK BSF SPKP ; Start pip GOTO ENDINT NOGENPIP ; Don't generate pip, duh... Wait 1.9 s, WAIT set DECFSZ PERIOD,1 GOTO ENDINT MOVLW 0x0C ; 1 kHz MOVWF PERIOD DECFSZ PIPON,1 ; Inner loop? GOTO ENDINT MOVLW 0x32 MOVWF PIPON DECFSZ PIPOFF,1 ; Outer loop? GOTO ENDINT MOVLW 0x4C MOVWF PIPOFF BSF WAITP BCF WAIT BSF SPKP ; Start pip GOTO ENDINT GENPIP ; Generate 1 kHz, WAITP set DECFSZ PERIOD,1 GOTO ENDINT MOVLW 0x0C ; 1 kHz MOVWF PERIOD MOVLW B'00110000' XORWF GPIO,1 ; Toggle SPKP and SPKN DECFSZ PIPON,1 GOTO ENDINT BCF SPKP BCF SPKN BCF WAITP BSF WAIT MOVLW 0x32 MOVWF PIPON DECFSZ PIPCOUNT,1 ; # of pips GOTO ENDINT BCF WAIT BSF PREPEW BCF SPKP BCF SPKN MOVLW 0x02 MOVWF PIPCOUNT MOVLW 0x3F MOVWF PIPOFF MOVLW 0xFF MOVWF PERIOD GOTO ENDINT GENPREPEW ; Wait 652 ms, PREPEW set DECFSZ PERIOD,1 ; Inner loop? (resumes @ 0xFF) GOTO ENDINT DECFSZ PIPOFF,1 ; Outer loop? (total 0x3FFF) GOTO ENDINT MOVLW 0x2B ; 0x2B=0.279 ms, 0xD2=1.61 ms MOVWF PERIOD MOVWF PIPOFF ; Copy of PERIOD MOVLW 0x04 ; Slide extender MOVWF PIPON BCF PREPEW BSF PEW BCF RED BSF GRN BSF SPKP ; Start pew GOTO ENDINT GENPEW ; Doesn't use TMR0 to create the gliding tone but PERIOD, PIPON and PIPOFF DECFSZ PERIOD,1 GOTO GENPEW CALL PEWTOGGLE DECFSZ PIPON,1 GOTO GENPEW MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD MOVLW 0x08 ; Slide extender (note: one cycle is two periods) MOVWF PIPON INCF PIPOFF,1 MOVLW 0x40 SUBWF PIPOFF,0 BTFSS STATUS,Z ; Test for short slide extender GOTO GENPEW ; Not yet MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD GENPEW1 DECFSZ PERIOD,1 GOTO GENPEW1 CALL PEWTOGGLE DECFSZ PIPON,1 GOTO GENPEW1 MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD MOVLW 0x04 ; Slide extender MOVWF PIPON INCF PIPOFF,1 MOVLW 0x4D SUBWF PIPOFF,0 BTFSS STATUS,Z ; Test for shorter slide extender GOTO GENPEW1 ; Not yet MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD GENPEW2 DECFSZ PERIOD,1 GOTO GENPEW2 CALL PEWTOGGLE DECFSZ PIPON,1 GOTO GENPEW2 MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD MOVLW 0x02 ; Slide extender MOVWF PIPON INCF PIPOFF,1 MOVLW 0x7C SUBWF PIPOFF,0 BTFSS STATUS,Z ; Test for end slide extender GOTO GENPEW2 ; Not yet MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD GENPEW3 DECFSZ PERIOD,1 GOTO GENPEW3 CALL PEWTOGGLE INCF PIPOFF,1 MOVLW 0xC8 SUBWF PIPOFF,0 BTFSC STATUS,Z ; Test for end pew GOTO ENDPEW ; Yes GOTO GENPEW3 PEWTOGGLE ; Subroutine, used four times in GENPEW MOVFW PIPOFF ; Restore PERIOD MOVWF PERIOD MOVLW B'00110000' XORWF GPIO,1 ; Toggle SPKP and SPKN RETURN ENDPEW BCF SPKP BCF SPKN BCF PEW BSF PREPOP MOVLW 0xFF MOVWF PERIOD GOTO ENDINT GENPREPOP ; Wait 12 ms, PREPOP set DECFSZ PERIOD,1 GOTO ENDINT BSF POP BCF PREPOP MOVLW 0x69 ; 105 pops MOVWF PIPCOUNT MOVLW 0x19 ; 480 Hz MOVWF PERIOD MOVLW 0x0C ; pop of 12 ms is only 6 cycles MOVWF PIPON BSF SPKP ; Start pop NOGENPOP ; Registers for pip are reused, NOPOP set, wait 122 ms DECFSZ PERIOD,1 GOTO ENDINT MOVLW 0x19 ; 480 Hz MOVWF PERIOD DECFSZ PIPOFF,1 ; Loop? GOTO ENDINT MOVLW 0x78 MOVWF PIPOFF MOVLW 0x0C MOVWF PIPON BSF POP BCF NOPOP BSF SPKP ; Start pop GOTO ENDINT GENPOP ; Generate 480 Hz, POP set DECFSZ PERIOD,1 GOTO ENDINT MOVLW 0x19 ; 480 Hz MOVWF PERIOD MOVLW B'00110000' XORWF GPIO,1 ; Toggle SPKP and SPKN DECFSZ PIPON,1 GOTO ENDINT BCF SPKP BCF SPKN BCF POP BSF NOPOP MOVLW 0x78 MOVWF PIPOFF DECFSZ PIPCOUNT,1 ; # of pips GOTO ENDINT BCF POP BSF IDLE BCF SPKP BCF SPKN BCF GRN BSF RED MOVLW 0x0C ; 1 kHz MOVWF PERIOD MOVLW 0x32 MOVWF PIPON MOVLW 0x4C MOVWF PIPOFF ENDINT BSF INTCON,GIE ; Enable global interrupts RETFIE START CLRF STATUS ; Do initialization, Select bank 0 CLRF INTCON ; Clear int-flags, Disable interrupts CLRF PCLATH ; Keep in lower 2KByte BANKSEL TRISIO MOVLW B'00001100' ; All outputs except GPIO3 (MCLR) and GPIO2 (BTN) MOVWF TRISIO MOVLW B'00000000' ; TMR0 Prescaler 1:2 MOVWF OPTION_REG BANKSEL T1CON CLRF T1CON MOVLW B'00000111' ; Comparators off MOVWF CMCON MOVLW B'10100000' ; Enable GIE, TMR0 interrupt MOVWF INTCON CLRF GPIO BSF RED MOVLW 0x0C ; 1 kHz MOVWF PERIOD CLRF STATE BSF IDLE ; Wait for button MOVLW 0x32 ; Prep pip MOVWF PIPON MOVLW 0x4C MOVWF PIPOFF MAIN INCF RND,1 GOTO MAIN END