;-----------------------------------------------------------------------; ; number_guess.asm ; ; Nathanial Hendler ; ; http://retards.org/projects/ ; ; ; ; v0.0 2004-11-30 Started ; ; v0.1 2004-12-04 Simple working version ; ; v1.0 2004-12-07 Blink upon high score ; ; 2005-01-05 Code Cleanup ; ; 2005-01-06 Code Cleanup ; ; ; ; This is likely the last version of this ; ; code for this hardware. ; ; ; ; ; ; HARDWARE: ; ; ; ; PIC 16F84 ; ; BCD number put on PORTB 0-3 for a 7447 or 7448 BCD to seven segment ; ; decoder. Which TTL chip depends on wether your 7-segment ; ; display is common cathode or anode ; ; Push buttons on PORTB 4,5,6 ; ; RB4 == Select ; ; RB5 == Up ; ; RB6 == Down ; ; LEDs on PORTA 0,1,2 to ground through resistors ; ; RA0 == Guess to high LED ; ; RA1 == Guess to low LED ; ; RA2 == Won LED ; ; 2.5Mhz Xtal (adjust delay for different value) ; ; ; ; ; ; GAME PLAY: ; ; ; ; Object: ; ; To guess the random number between 0 and 15 ; ; ; ; User presses start button to start the game. The PIC generates a ; ; random number and the user must guess it using the up/down push ; ; buttons and using the select button to make their guess. LEDs let ; ; the player know if their guess was too high or too low. If they ; ; guess correctly the high/low and won LEDs light up and the number ; ; of guesses is displayed. ; ; ; ; ; ; THANKS: ; ; ; ; Thanks to the piclist for the CHEAPIC tutorials. ; ; http://www.piclist.com/techref/piclist/cheapic/index.htm ; ; ; ;-----------------------------------------------------------------------; ;-----------------------------------------------------------------------; ; Compiler Directives ; ;-----------------------------------------------------------------------; LIST P=16f84 INCLUDE "p16f84.inc" ERRORLEVEL -224 __CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; ;-----------------------------------------------------------------------; ; User Defined Registers ; ;-----------------------------------------------------------------------; CBLOCK H'0C' delay_count temp_w temp_status random_number game_number user_number guess_count high_score blink_count game_flags ; bits used to track status of the game ; see DEFINES below for bit assignments ENDC ;-----------------------------------------------------------------------; ; #DEFINES ; ;-----------------------------------------------------------------------; #DEFINE FLAG_GAME game_flags, 0 ; unused #DEFINE FLAG_BLINK game_flags, 1 ; blink leds? #DEFINE BUTTON_START PORTB, 4 #DEFINE BUTTON_SELECT PORTB, 4 #DEFINE BUTTON_UP PORTB, 5 #DEFINE BUTTON_DOWN PORTB, 6 #DEFINE LED_UP PORTA, 0 ; guess is too high LED #DEFINE LED_DOWN PORTA, 1 ; guess is too low LED #DEFINE LED_WON PORTA, 2 ORG 0 goto main ;-----------------------------------------------------------------------; ; Interup routine ; ;-----------------------------------------------------------------------; ORG 4 ; Save registers movwf temp_w ; save W swapf STATUS, W ; save STATUS movwf temp_status incf random_number, f btfsc random_number, 4 ; 00010000 is too high clrf random_number ; so set to zero ; LED blinking stuff incf blink_count, f ; timer for blinks btfsc FLAG_BLINK ; check game state call blink_leds ; we're blinking, go do it ; Restore registers swapf temp_status, W movwf STATUS swapf temp_w, f swapf temp_w, W bcf INTCON, T0IF retfie blink_leds bcf LED_DOWN bcf LED_UP bcf LED_WON btfss blink_count, 2 return ; LEDs off state bsf LED_DOWN ; LEDs on state bsf LED_UP bsf LED_WON return ;-----------------------------------------------------------------------; ; M a i n ; ;-----------------------------------------------------------------------; main: ;-----------------------------------------------------------------------; ; Init registers and setup interupt ; ;-----------------------------------------------------------------------; movlw B'00000000' tris PORTA movlw B'01110000' tris PORTB movlw B'00000111' option movlw B'10100000' movwf INTCON ; initialize registers for game clrf PORTB clrf PORTA clrf game_flags movlw b'11111111' movwf high_score restart: btfsc BUTTON_START ; wait for start button to be pressed goto $ -1 ; setup game variables movf random_number, W ; set the number to be guessed: game_number movwf game_number movlw b'00000000' ; set user_number to zero movwf user_number clrf guess_count ; guess_count = 0 clrf game_flags bcf LED_DOWN ; turn off all LEDs bcf LED_UP bcf LED_WON goto start_button ; debounce start_button game_loop: ; display current number movf user_number, W movwf PORTB ; button scan btfss BUTTON_SELECT goto select_button btfss BUTTON_UP goto inc_button btfss BUTTON_DOWN goto dec_button goto game_loop select_button: movlw D'12' ; debounce call nmsec btfss PORTB, 4 goto $ -1 movlw D'12' call nmsec btfss PORTB, 4 goto $ -5 bcf LED_UP ; turn off LEDs bcf LED_DOWN incf guess_count, f ; guess_count++ movf user_number, W ; compare guess with right answer subwf game_number, W btfsc STATUS, Z goto game_won btfss STATUS, C goto too_high bsf LED_DOWN goto game_loop too_high: bsf LED_UP goto game_loop inc_button: bcf LED_UP ; turn off LEDs bcf LED_DOWN movlw D'12' ; debounce call nmsec btfss PORTB, 5 goto $ -1 movlw D'12' call nmsec btfss PORTB, 5 goto $ -5 incf user_number, f ; user_number++ btfss user_number, 4 ; did we go to high? goto game_loop ; nope, user_guess is 1111 or less movlw b'00000000' ; yep, we went to high. movwf user_number goto game_loop dec_button: bcf LED_UP ; turn off LEDs bcf LED_DOWN movlw D'12' ; debounce call nmsec btfss PORTB, 6 goto $ -1 movlw D'12' call nmsec btfss PORTB, 6 goto $ -5 decf user_number, f ; user_number-- btfss user_number, 7 ; did we go to low? goto game_loop ; nope, user_guess is 0000 or greater movlw b'00001111' ; yep, we went to low. movwf user_number goto game_loop start_button: movlw D'12' ; debounce call nmsec btfss BUTTON_START goto $ -1 movlw D'12' call nmsec btfss BUTTON_START goto $ -5 goto game_loop game_won: bsf LED_UP ; turn on all three LEDs bsf LED_DOWN bsf LED_WON movf guess_count, W ; display number of guesses taken movwf PORTB ; high score? movf guess_count, W subwf high_score, W btfsc STATUS, Z goto set_high_score btfss STATUS, C goto restart goto set_high_score set_high_score: bsf FLAG_BLINK ; this lets the ISR know to blink LEDs movf guess_count, W movwf high_score goto restart nmsec: movwf delay_count dlyloop: nop nop nop nop nop nop nop nop nop nop nop nop decfsz delay_count, f goto dlyloop return end