Gadget Freak Case 142: GameCube Cop Keeps the Peace
Design News Staff -- Design News, June 15, 2009
Three siblings and one GameCube is a recipe for territorial skirmishes. Many games only support two users. Jeremy Willden bought his three kids a GameCube for Christmas and quickly discovered parental intervention was critical. He initially used a kitchen timer, but soon opted for a more technology-driven solution. He created an electronic Time Turner. The gadget uses a Microchip microcontroller connected to three LEDs and a small speaker. Every 15 minutes, the LEDs change (each labeled with a child’s name) to indicate whose turn it is.
| Amt | Part Description | Allied Part # |
| 1 | PIC 12F629 Microcontroller | 653-0248 |
| 1 | Piezo Speaker | 623-2038 |
| 2 | Switches | 676-3000 |
| 3 | 470Ω Resistors | 296-4768 |
| 3 | LEDs | 405-0011 |
| 1 | Enclosure | 272-0008 |
| 1 | Power Adapter | 653-0248 |
| 1 | U.S. Prongs for Power Adapter | 653-0260 |
|
Get Build Instructions |
-
;**********************************************************************
; This is the source file for a Gadget Freak Entry by Jeremy *
; Willden. It runs on the PICmicro PIC12F629. *
; Three LEDs indicate whose turn (of three possible players) *
; it currently is. Every 15 minutes the beeper sounds for two *
; seconds and the LEDs are updated to indicate the new players *
; for the next time period. A switch (GPIO4) selects whether *
; one player or two players at a time can play the game. *
; If interrupts are not used all code presented between the *
; code section "INT_VECTOR and code section "MAIN" can be removed. *
; *
; The LEDs connect to GPIO2..0 and the piezo speaker connects to *
; GPIO5. If a magnetic speaker is used, put a capacitor in *
; series with it to block DC. *
; *
; This code is released under the latest version of the GPL. *
; Copyright 2009 Jeremy Willden *
; *
;**********************************************************************
; *
; Filename: main.asm *
; Date: February 7, 2009 *
; *
; Author: Jeremy Willden *
; *
;**********************************************************************
; *
; Files required: *
; 12F629.lkr *
; *
;**********************************************************************
; *
; Notes: In order to change modes between one-at-a-time and *
; two-at-a-time, the device must be reset or power cycled. *
; Please pardon the poor coding, this is my first project *
; written in pure assembly. 8-) *
; *
;**********************************************************************
list p=12F629 ; list directive to define processor
#include ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
; example of using Shared Uninitialized Data Section
INT_VAR UDATA_SHR 0x20
w_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
scratch RES 1 ; variable used to alter counter value in ISR
outercount RES 1 ; variable used for the outer loop of the /2000 counter
innercount RES 1 ; variable for the inner loop of the /2000 counter
secondslsb RES 1 ; Least significant byte of the 1 Hz countdown timer
secondsmsb RES 1 ; Most significant byte of teh 1 Hz countdown timer
secrunning RES 1 ; A flag to indicate whether the 1 Hz countdown is running
beepenabled RES 1 ; A flag to turn on the beeper output
scratch2 RES 1 ; Used to store a copy of a variable for sign comparison
twoplayer RES 1 ; Stores the state of the 1/2 player control line at startup
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
INT_VECTOR CODE 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; INTERRUPT SERVICE ROUTINE
clrf INTCON ;clear the interrupt source without checking where it came from
movf TMR0,w ;copy the current timer0 value to the W register
movwf scratch ;store the saved timer value to a scratch location
movlw 0x17 ;load a constant into the W register to adjust the count total to 250
addwf scratch ;add the constant to the saved timer0 value
movwf TMR0 ;re-load the timer (it will be stalled for two instructions)
; and the prescaler will be reset (if used)
btfss beepenabled,0 ;check to see if the beeper flag is set
goto NoBeeper ;but if it's set, we skip this instruction
movlw b'00100000' ;we'll toggle this bit to make a 2 kHz buzzer with the Piezo speaker
xorwf GPIO ;XOR the bit into the GPIO register to flip it
NoBeeper
decfsz innercount ;decrement the inner counter (40..1) (this is reset every 10 ms)
goto DoneDecrementing ;if innercount is still non-zero, we're done with the counters
movlw 0x28 ;otherwise, we re-load the inner count register
movwf innercount ;with it's starting value (0x28 == 40)
decfsz outercount ;If we re-loaded the inner count, it's time to decrement outer count
goto DoneDecrementing ;and if it's still non-zero, we're done (reset every second)
movlw 0x64 ;But if we just wrapped the counter, it's time to reload (100 == 0x64)
movwf outercount ;which we do here, then we do the following code once per second
;incf GPIO ;increment the value on the GPIO port for testing purposes
movf secondslsb,w ;load up the seconds Least significant byte to see if it's nonzero
btfsc STATUS,Z ;if the lsbyte is nonzero, don't bother checking the msbyte
movf secondsmsb,w ;load up the seconds Most significant byte to see if it's nonzero
btfsc STATUS,Z ;skip the next instruction if either the lsb or msb are non-zero
goto DoneDecrementing ;we're done
movf secondslsb,w ;re-load the least significant byte
btfss STATUS,Z ;see if the lsb is zero
goto DecrementLsbyte ;if it's non-zero, we just decrement the LSByte
DecrementMsbyte
movf secondsmsb,w ;Let's make sure the MSByte is non-zero before we decrement it
btfss STATUS,Z
decf secondsmsb ;Decrement the MSByte
DecrementLsbyte
decf secondslsb
DoneDecrementing
movlw b'10100000' ;re-enable global interrupts and the TIMER0 overflow interrupt
movwf INTCON ;and write back to the interrupt control register
clrf secrunning ;clear out the "timer running" flag
movf secondslsb ;check to see if the seconds counter is running
btfss STATUS,Z ;If secondsLSB is zero, we'll skip the next instruction
bsf secrunning,0 ;If the LSByte of the timer is running, we'll set the flag
movf secondsmsb ;we'll also check the MSByte
btfss STATUS,Z ;If secondsMSB is zero, we'll skip the next instruction
bsf secrunning,0 ;Set the flag to indicate that the seconds timer is counting down
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
main
call 0x3FF ; retrieve factory calibration value for the internal oscillator
bsf STATUS,RP0 ; set file register bank to 1
movwf OSCCAL ; update register with factory cal value
bcf STATUS,RP0 ; set file register bank to 0
; INITIALIZE THE GPIO LINES
BCF STATUS,RP0 ; Bank 0
CLRF GPIO ; Init GPIO (set all outputs to low)
MOVLW 07h ; Set GP to digital IO
MOVWF CMCON ; and the comparator is disabled
BSF STATUS,RP0 ; Bank 1
MOVLW b'00010000' ; Set GP as outputs, GP as an input
MOVWF TRISIO ;store to the "tri-state" register
MOVWF WPU ;and enable the weak pull-up on the input pin
; PREPARE THE TIMEBASE VARIABLES (PRELOAD THEM)
movlw 0x28 ; The inner count will go from 40..1 (0x28..0x01)
movwf innercount ; it's stored in this variable
movlw 0x64 ; The outer count (which increments every 10 ms)
movwf outercount ; counts from 100..1 (0x64 .. 0x01)
clrf secondslsb ; don't start counting seconds yet
clrf secondsmsb ; and always load the lsbyte first, clear msbyte first
clrf secrunning ; we're not running, so clear this flag
; SET UP COUNTER 0 WITH A /2 PRESCALE, OPERATING FROM INTERNAL OSCILLATOR
;which should provide a 1 MHz / (250) interrupt rate (4000 Hz) (the ISR tweaks the counter)
clrwdt ;Clear WDT and
; postscaler
bsf STATUS,RP0 ;Bank 1
movlw b'00001000' ;Select TMR0,
; prescale (xxxxx000), and
; clock source (CLKOUT unscaled)
movwf OPTION_REG ;
bcf STATUS,RP0 ;Bank 0
; ENABLE INTERRUPTS
movlw b'10100000' ;Enable global interrupts and overflow interrupt on timer 0
movwf INTCON ;and write back to the interrupt control register
; DO THE STARTUP BEEP SEQUENCE (0.5s on, 0.5s off, 4 times, then 2 seconds on)
movlw 0x4 ;Start a 4 second countdown to time the beep sequence
movwf secondslsb
bsf secrunning,0 ;kick off the seconds timer
ShortBeepSequence
btfss secrunning,0 ;if the 4 second countdown has expired,
goto LongBeepSequence ;we're done and ready to move on
movlw 0x32 ;we're going to split the outercount timer in half
subwf outercount,w ;so we subtract and see if the result is positive
movwf scratch2 ;copy the result to our scratch variable
; (avoid bug where btfsc doesn't work with the W register)
btfsc scratch2,7 ;we're checking to see if the msbit is set
goto ShortBeepOff ;if it's set, outercount is below 0x32, the beep should be off
goto ShortBeepOn ;if it's not set, outercount is above 0x32, the beep should be on
ShortBeepOn
bsf beepenabled,0 ;turn on the beeper
goto ShortBeepSequence
ShortBeepOff
bcf beepenabled,0 ;turn off the beeper
goto ShortBeepSequence
LongBeepSequence
movlw 0x2 ;start a 2 second countdown for the long beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
LongBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto LongBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
CheckInputs
clrf twoplayer ;we'll start out assuming we're set for one player
btfss GPIO,4 ;If the "twoplayer" input is low, we're done
bsf twoplayer,0 ;otherwise, the input is high and we're doing a 2-player rotation
SetupOutputs
btfss twoplayer,0
goto SetupOnePlayer
goto SetupTwoPlayer
SetupOnePlayer ;Set up the LEDs for a one-player operating mode.
movlw b'11111000' ;start with the third output and work backwards
andwf GPIO ;(in my case, youngest child to the oldest)
movlw b'00000100'
addwf GPIO
goto StartTheTimer
SetupTwoPlayer ;Set up the LEDs for two player operating mode
movlw b'11111000'
andwf GPIO
movlw b'00000110'
addwf GPIO
StartTheTimer
movlw 0x84 ;Set the countdown timer for 900 seconds (15 minutes, 0x0384)
movwf secondslsb ;and copy it to the seconds LSByte
movlw 0x03 ;This is the MSByte of the countdown
movwf secondsmsb ;which we also copy over
bsf secrunning,0 ;set the countdown timer flag so we don't have to wait for the first interrupt
; main loop
MainLoop
nop
btfsc secrunning,0 ;Check to see if the countdown timer is running
goto MainLoop ;If it is running, restart the loop
FirstBeepSequence
movlw 0x2 ;start a 2 second countdown for the first beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
FirstBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto FirstBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
UpdateOutputs
btfsc twoplayer,0 ;see if we're doing one-player or two-player mode
goto TwoPlayerOutputs
goto OnePlayerOutputs
TwoPlayerOutputs
btfss GPIO,2 ;Output 0 is not currently getting a turn
goto Out1off
btfss GPIO,1 ;Output 1 is not currently getting a turn
goto Out0off
btfss GPIO,0 ;Output 3 is not currently getting a turn
goto Out2off
goto main ;Problem, reset the system
Out1off
movlw b'11111000'
andwf GPIO
movlw b'00000101' ;Advance to the next players
addwf GPIO
goto SecondBeepSequence
Out2off
movlw b'11111000'
andwf GPIO
movlw b'00000011'
addwf GPIO
goto SecondBeepSequence
Out0off
movlw b'11111000'
andwf GPIO
movlw b'00000110'
addwf GPIO
goto SecondBeepSequence
OnePlayerOutputs
btfsc GPIO,2 ;Output 0 is currently getting a turn
goto Out1on
btfsc GPIO,1 ;Output 1 is currently getting a turn
goto Out0on
btfsc GPIO,0 ;Output 3 is currently getting a turn
goto Out2on
goto main ;Problem, reset the system
Out1on
movlw b'11111000'
andwf GPIO
movlw b'00000010' ;Advance to the next player
addwf GPIO
goto SecondBeepSequence
Out2on
movlw b'11111000'
andwf GPIO
movlw b'00000100'
addwf GPIO
goto SecondBeepSequence
Out0on
movlw b'11111000'
andwf GPIO
movlw b'00000001'
addwf GPIO
goto SecondBeepSequence
SecondBeepSequence
movlw 0x2 ;start a 2 second countdown for the second beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
SecondBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto SecondBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
movlw 0x84 ;Set the countdown timer for 900 seconds (15 minutes, 0x0384)
movwf secondslsb ;and copy it to the seconds LSByte
movlw 0x03 ;This is the MSByte of the countdown
movwf secondsmsb ;which we also copy over
bsf secrunning,0 ;set the countdown timer flag so we don't have to wait for the first interrupt
;movlw b'00010000' ;we'll toggle this bit so we can see it change when the timer expires
;xorwf GPIO ;XOR the bit into the GPIO register to flip it
goto MainLoop ;We're done re-setting the timer, go back to the beginning
; initialize eeprom locations
EE CODE 0x2100
DE 0x00, 0x01, 0x02, 0x03
END ; directive 'end of program''>Source code (hopefully it doesn't get clipped)
;**********************************************************************
; This is the source file for a Gadget Freak Entry by Jeremy *
; Willden. It runs on the PICmicro PIC12F629. *
; Three LEDs indicate whose turn (of three possible players) *
; it currently is. Every 15 minutes the beeper sounds for two *
; seconds and the LEDs are updated to indicate the new players *
; for the next time period. A switch (GPIO4) selects whether *
; one player or two players at a time can play the game. *
; If interrupts are not used all code presented between the *
; code section "INT_VECTOR and code section "MAIN" can be removed. *
; *
; The LEDs connect to GPIO2..0 and the piezo speaker connects to *
; GPIO5. If a magnetic speaker is used, put a capacitor in *
; series with it to block DC. *
; *
; This code is released under the latest version of the GPL. *
; Copyright 2009 Jeremy Willden *
; *
;**********************************************************************
; *
; Filename: main.asm *
; Date: February 7, 2009 *
; *
; Author: Jeremy Willden *
; *
;**********************************************************************
; *
; Files required: *
; 12F629.lkr *
; *
;**********************************************************************
; *
; Notes: In order to change modes between one-at-a-time and *
; two-at-a-time, the device must be reset or power cycled. *
; Please pardon the poor coding, this is my first project *
; written in pure assembly. 8-) *
; *
;**********************************************************************
list p=12F629 ; list directive to define processor
#include ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
; example of using Shared Uninitialized Data Section
INT_VAR UDATA_SHR 0x20
w_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
scratch RES 1 ; variable used to alter counter value in ISR
outercount RES 1 ; variable used for the outer loop of the /2000 counter
innercount RES 1 ; variable for the inner loop of the /2000 counter
secondslsb RES 1 ; Least significant byte of the 1 Hz countdown timer
secondsmsb RES 1 ; Most significant byte of teh 1 Hz countdown timer
secrunning RES 1 ; A flag to indicate whether the 1 Hz countdown is running
beepenabled RES 1 ; A flag to turn on the beeper output
scratch2 RES 1 ; Used to store a copy of a variable for sign comparison
twoplayer RES 1 ; Stores the state of the 1/2 player control line at startup
;**********************************************************************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
INT_VECTOR CODE 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
; INTERRUPT SERVICE ROUTINE
clrf INTCON ;clear the interrupt source without checking where it came from
movf TMR0,w ;copy the current timer0 value to the W register
movwf scratch ;store the saved timer value to a scratch location
movlw 0x17 ;load a constant into the W register to adjust the count total to 250
addwf scratch ;add the constant to the saved timer0 value
movwf TMR0 ;re-load the timer (it will be stalled for two instructions)
; and the prescaler will be reset (if used)
btfss beepenabled,0 ;check to see if the beeper flag is set
goto NoBeeper ;but if it's set, we skip this instruction
movlw b'00100000' ;we'll toggle this bit to make a 2 kHz buzzer with the Piezo speaker
xorwf GPIO ;XOR the bit into the GPIO register to flip it
NoBeeper
decfsz innercount ;decrement the inner counter (40..1) (this is reset every 10 ms)
goto DoneDecrementing ;if innercount is still non-zero, we're done with the counters
movlw 0x28 ;otherwise, we re-load the inner count register
movwf innercount ;with it's starting value (0x28 == 40)
decfsz outercount ;If we re-loaded the inner count, it's time to decrement outer count
goto DoneDecrementing ;and if it's still non-zero, we're done (reset every second)
movlw 0x64 ;But if we just wrapped the counter, it's time to reload (100 == 0x64)
movwf outercount ;which we do here, then we do the following code once per second
;incf GPIO ;increment the value on the GPIO port for testing purposes
movf secondslsb,w ;load up the seconds Least significant byte to see if it's nonzero
btfsc STATUS,Z ;if the lsbyte is nonzero, don't bother checking the msbyte
movf secondsmsb,w ;load up the seconds Most significant byte to see if it's nonzero
btfsc STATUS,Z ;skip the next instruction if either the lsb or msb are non-zero
goto DoneDecrementing ;we're done
movf secondslsb,w ;re-load the least significant byte
btfss STATUS,Z ;see if the lsb is zero
goto DecrementLsbyte ;if it's non-zero, we just decrement the LSByte
DecrementMsbyte
movf secondsmsb,w ;Let's make sure the MSByte is non-zero before we decrement it
btfss STATUS,Z
decf secondsmsb ;Decrement the MSByte
DecrementLsbyte
decf secondslsb
DoneDecrementing
movlw b'10100000' ;re-enable global interrupts and the TIMER0 overflow interrupt
movwf INTCON ;and write back to the interrupt control register
clrf secrunning ;clear out the "timer running" flag
movf secondslsb ;check to see if the seconds counter is running
btfss STATUS,Z ;If secondsLSB is zero, we'll skip the next instruction
bsf secrunning,0 ;If the LSByte of the timer is running, we'll set the flag
movf secondsmsb ;we'll also check the MSByte
btfss STATUS,Z ;If secondsMSB is zero, we'll skip the next instruction
bsf secrunning,0 ;Set the flag to indicate that the seconds timer is counting down
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
main
call 0x3FF ; retrieve factory calibration value for the internal oscillator
bsf STATUS,RP0 ; set file register bank to 1
movwf OSCCAL ; update register with factory cal value
bcf STATUS,RP0 ; set file register bank to 0
; INITIALIZE THE GPIO LINES
BCF STATUS,RP0 ; Bank 0
CLRF GPIO ; Init GPIO (set all outputs to low)
MOVLW 07h ; Set GP to digital IO
MOVWF CMCON ; and the comparator is disabled
BSF STATUS,RP0 ; Bank 1
MOVLW b'00010000' ; Set GP as outputs, GP as an input
MOVWF TRISIO ;store to the "tri-state" register
MOVWF WPU ;and enable the weak pull-up on the input pin
; PREPARE THE TIMEBASE VARIABLES (PRELOAD THEM)
movlw 0x28 ; The inner count will go from 40..1 (0x28..0x01)
movwf innercount ; it's stored in this variable
movlw 0x64 ; The outer count (which increments every 10 ms)
movwf outercount ; counts from 100..1 (0x64 .. 0x01)
clrf secondslsb ; don't start counting seconds yet
clrf secondsmsb ; and always load the lsbyte first, clear msbyte first
clrf secrunning ; we're not running, so clear this flag
; SET UP COUNTER 0 WITH A /2 PRESCALE, OPERATING FROM INTERNAL OSCILLATOR
;which should provide a 1 MHz / (250) interrupt rate (4000 Hz) (the ISR tweaks the counter)
clrwdt ;Clear WDT and
; postscaler
bsf STATUS,RP0 ;Bank 1
movlw b'00001000' ;Select TMR0,
; prescale (xxxxx000), and
; clock source (CLKOUT unscaled)
movwf OPTION_REG ;
bcf STATUS,RP0 ;Bank 0
; ENABLE INTERRUPTS
movlw b'10100000' ;Enable global interrupts and overflow interrupt on timer 0
movwf INTCON ;and write back to the interrupt control register
; DO THE STARTUP BEEP SEQUENCE (0.5s on, 0.5s off, 4 times, then 2 seconds on)
movlw 0x4 ;Start a 4 second countdown to time the beep sequence
movwf secondslsb
bsf secrunning,0 ;kick off the seconds timer
ShortBeepSequence
btfss secrunning,0 ;if the 4 second countdown has expired,
goto LongBeepSequence ;we're done and ready to move on
movlw 0x32 ;we're going to split the outercount timer in half
subwf outercount,w ;so we subtract and see if the result is positive
movwf scratch2 ;copy the result to our scratch variable
; (avoid bug where btfsc doesn't work with the W register)
btfsc scratch2,7 ;we're checking to see if the msbit is set
goto ShortBeepOff ;if it's set, outercount is below 0x32, the beep should be off
goto ShortBeepOn ;if it's not set, outercount is above 0x32, the beep should be on
ShortBeepOn
bsf beepenabled,0 ;turn on the beeper
goto ShortBeepSequence
ShortBeepOff
bcf beepenabled,0 ;turn off the beeper
goto ShortBeepSequence
LongBeepSequence
movlw 0x2 ;start a 2 second countdown for the long beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
LongBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto LongBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
CheckInputs
clrf twoplayer ;we'll start out assuming we're set for one player
btfss GPIO,4 ;If the "twoplayer" input is low, we're done
bsf twoplayer,0 ;otherwise, the input is high and we're doing a 2-player rotation
SetupOutputs
btfss twoplayer,0
goto SetupOnePlayer
goto SetupTwoPlayer
SetupOnePlayer ;Set up the LEDs for a one-player operating mode.
movlw b'11111000' ;start with the third output and work backwards
andwf GPIO ;(in my case, youngest child to the oldest)
movlw b'00000100'
addwf GPIO
goto StartTheTimer
SetupTwoPlayer ;Set up the LEDs for two player operating mode
movlw b'11111000'
andwf GPIO
movlw b'00000110'
addwf GPIO
StartTheTimer
movlw 0x84 ;Set the countdown timer for 900 seconds (15 minutes, 0x0384)
movwf secondslsb ;and copy it to the seconds LSByte
movlw 0x03 ;This is the MSByte of the countdown
movwf secondsmsb ;which we also copy over
bsf secrunning,0 ;set the countdown timer flag so we don't have to wait for the first interrupt
; main loop
MainLoop
nop
btfsc secrunning,0 ;Check to see if the countdown timer is running
goto MainLoop ;If it is running, restart the loop
FirstBeepSequence
movlw 0x2 ;start a 2 second countdown for the first beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
FirstBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto FirstBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
UpdateOutputs
btfsc twoplayer,0 ;see if we're doing one-player or two-player mode
goto TwoPlayerOutputs
goto OnePlayerOutputs
TwoPlayerOutputs
btfss GPIO,2 ;Output 0 is not currently getting a turn
goto Out1off
btfss GPIO,1 ;Output 1 is not currently getting a turn
goto Out0off
btfss GPIO,0 ;Output 3 is not currently getting a turn
goto Out2off
goto main ;Problem, reset the system
Out1off
movlw b'11111000'
andwf GPIO
movlw b'00000101' ;Advance to the next players
addwf GPIO
goto SecondBeepSequence
Out2off
movlw b'11111000'
andwf GPIO
movlw b'00000011'
addwf GPIO
goto SecondBeepSequence
Out0off
movlw b'11111000'
andwf GPIO
movlw b'00000110'
addwf GPIO
goto SecondBeepSequence
OnePlayerOutputs
btfsc GPIO,2 ;Output 0 is currently getting a turn
goto Out1on
btfsc GPIO,1 ;Output 1 is currently getting a turn
goto Out0on
btfsc GPIO,0 ;Output 3 is currently getting a turn
goto Out2on
goto main ;Problem, reset the system
Out1on
movlw b'11111000'
andwf GPIO
movlw b'00000010' ;Advance to the next player
addwf GPIO
goto SecondBeepSequence
Out2on
movlw b'11111000'
andwf GPIO
movlw b'00000100'
addwf GPIO
goto SecondBeepSequence
Out0on
movlw b'11111000'
andwf GPIO
movlw b'00000001'
addwf GPIO
goto SecondBeepSequence
SecondBeepSequence
movlw 0x2 ;start a 2 second countdown for the second beep
movwf secondslsb
bsf secrunning,0 ;start the timer up again
bsf beepenabled,0 ;turn on the beeper
SecondBeepWait
btfsc secrunning,0 ;if the seconds timer is still running,
goto SecondBeepWait ;we loop here until it's done
bcf beepenabled,0 ;turn off the beeper
movlw 0x84 ;Set the countdown timer for 900 seconds (15 minutes, 0x0384)
movwf secondslsb ;and copy it to the seconds LSByte
movlw 0x03 ;This is the MSByte of the countdown
movwf secondsmsb ;which we also copy over
bsf secrunning,0 ;set the countdown timer flag so we don't have to wait for the first interrupt
;movlw b'00010000' ;we'll toggle this bit so we can see it change when the timer expires
;xorwf GPIO ;XOR the bit into the GPIO register to flip it
goto MainLoop ;We're done re-setting the timer, go back to the beginning
; initialize eeprom locations
EE CODE 0x2100
DE 0x00, 0x01, 0x02, 0x03
END ; directive 'end of program'
Jeremy Willden - 2009-23-6 16:35:14 EDT -
SOOO !!!
Where is the source code of the pic ?
and i think so , is probably do it with out pic , but any way
oscar g - 2009-23-6 13:01:46 EDT -
Can I be Player 3? Minor detail, the schematic labels all three LEDs as belonging to Player 3, lol.
The Bruce - 2009-22-6 19:36:48 EDT -
are you kidding me? a gamecube? they are like 30 bucks right now, buy one for each of them, you put more into your timer then what they cost for each of your kids....
tom lewis - 2009-22-6 17:10:58 EDT -
Where's the Source Code? Zip File?
Gregory M. Williams - 2009-22-6 14:48:08 EDT
























