Contestant Lockout System

by Randy Glenn

prepared for the SX Starter Contest July 2002

My entry for the contest is an SX-based contestant lockout system, for 8-player, 2-team games, like Reach For The Top (where Alex Trebek got his start). It's like Jeopardy, but with 2 teams of 4 members each. One member answers the question by "buzzing in", at which point a tone sounds, their light lights, and everyone else is locked out.

My system adds a twist - an auto-reset 4 seconds after the sound ends. This is due to my own experiences, where moderators forget to reset the board, and no one can buzz in for the next question.

The code uses the RTCC interrupt to generate the tone, and the RB interrupt to detect when someone has buzzed in. I've designed it to run on a 4 MHz oscillator, in Turbo mode. Details on hardware connections are in the attached ASM file.

The code is untested, of course, and not likely to work the first time. It's my first attempt at writing for the SX (long time lurker).

Thanks,

-Randy Glenn
Comp. Eng. & Mgt. II, McMaster University
===================================================
picxpert-at-cogeco.ca - glennrb-at-mcmaster.ca
picxpert-at-yahoo.com - randy_glenn-at-ieee.org
http://picxpert.dyndns.org/
===================================================

; Contestant Lockout System
; by Randy Glenn
; prepared for the SX Starter Contest July 2002

; Version 1.0 - July 31, 2002
; - initial release

; 8 buttons in on RB
; 8 LEDs out on RC
; Audio out on RA1
; Manual reset button attached to reset line

; Code is supposed to work like this:
; Contestant pushes button, a team tone sounds, and their light is lit - others locked out
; Tone lasts for 1 sec, followed by 4 sec until auto-reset (lights out, board unlocked)

	device	turbo,stackx_optionx
	reset	startup
	freq	4000000	;4 MHz
	org	8
SysStat	ds	1	; variable to hold flags for delay loop status, sound output
i	ds	1	; counter variables
j	ds	1
k	ds	1
InpBuf	ds	1	; variable to buffer RB


; variable declarations

	org	0
isr	snb	SysStat.0	; are we in a delay?
	jmp	:ProcDelay
	snb	SysStat.2	; are we doing tone 1?
	jmp	:ProcTone1	
	snb	SysStat.3	; are we doing tone 2?
	jmp	:ProcTone2	
				; we must be checking input then
:ProcInput
	mov	M, #$09	; set mode register to read pending RB interrupts
	mov	W, !RB	; read pending RB interrupts
	mov	M, #$0B	; disable RB interrupts
	clr	!RB
	mov	M, #$0F	; reset the mode register to power-up condition
	mov	InpBuf, W	; move the W reg into an input buffer
	snb	InpBuf.0	; check to see which light to light
	jmp	:Player1
	snb	InpBuf.1
	jmp	:Player2
	snb	InpBuf.2
	jmp	:Player3
	snb	InpBuf.3
	jmp	:Player4
	snb	InpBuf.4
	jmp	:Player5
	snb	InpBuf.5
	jmp	:Player6
	snb	InpBuf.6
	jmp	:Player7
	snb	InpBuf.7
	jmp	:Player8

:Player1
	call	SetupTone1	; set variables for the appropriate tone
	clr	RC		; clear the port
	setb	RC.0		; turn on the appropriate light
	jmp	iout		; done interrupt

:Player2
	call	SetupTone1
	clr	RC
	setb	RC.1
	jmp	iout

:Player3
	call	SetupTone1
	clr	RC
	setb	RC.2
	jmp	iout

:Player4
	call	SetupTone1
	clr	RC
	setb	RC.3
	jmp	iout

:Player5
	call	SetupTone2
	clr	RC
	setb	RC.4
	jmp	iout

:Player6
	call	SetupTone2
	clr	RC
	setb	RC.5
	jmp	iout

:Player7
	call	SetupTone2
	clr	RC
	setb	RC.6
	jmp	iout

:Player8
	call	SetupTone2
	clr	RC
	setb	RC.7
	jmp	iout

:ProcDelay
	;standard delay loop - 256 * 256 * 244 = 4 sec at 4MHz
	djnz	i, :DoneDelay
	mv	i, #255
	djnz	j, :DoneDelay
	setb	SysStat.1
:DoneDelay
	jmp	iout

:ProcTone1
	;tone 1 - 1 KHz, 1 sec long
	djnz	i, iout	; invert RA1 every 16 interrupts
	mv	i, #16
	sb	RA.1
	jmp	:ClearSnd1
	jmp 	:SetSnd1
:ContSnd1
	djnz	j, iout	; various counters to allow for 1 second tone
	mv	j, #250
	djnz	k, iout
	clrb	SysStat.2
	setb	SysStat.0	; set up registers for 4 sec delay before auto-reset
	mv	i, #255
	mv	j, #254
	jmp	iout
:ClearSnd1
	clrb	RA.1
	jmp	:ContSnd1
:SetSnd1
	setb	RA.1
	jmp	:ContSnd1
	
:ProcTone2
	;tone 2 - different constants for 600 KHz tone, 1 sec
	; otherwise, same deal as tone 1
	djnz	i, iout
	mv	i, #25
	sb	RA.1
	jmp	:ClearSnd2
	jmp 	:SetSnd2
:ContSnd2
	djnz	j, iout
	mv	j, #150
	djnz	k, iout
	clrb	SysStat.3
	setb	SysStat.0
	mv	i, #255
	mv	j, #254
	jmp	iout
:ClearSnd2
	clrb	RA.1
	jmp	:ContSnd2
:SetSnd2
	setb	RA.1
	jmp	:ContSnd2
iout
	reti

startup
	clr	SysStat	; clear all variables, just in case (and for auto-reset)
	clr	InpBuf
	clr	i
	clr	j
	clr	k

	mov	!rb, #$FF	; rb is all inputs
	mov	!rc, #$00	; rc is all outputs
	mov	M, #$0B	; set rb to allow interrupts
	mov	!rb, #$00
	mov	M, #$0A	; rb is edge detect
	mov	!rb, #$00
	mov	M, #$0F	; revert MODE to post-reset status

	mov	!option, #$87	; enable RTCC interrupt, prescaler 1:256

:loop
	snb	SysStat.1	; if no auto-reset has occured, keep looping
	jmp	:loop		; otherwise restart
	jmp	startup	; otherwise restart

SetupTone1
	setb	SysStat.2	; tone 1
	mv	i, #16	; toggle audio pin every 16 interrupts for 1 KHz-ish
	mv	j, #259	; 250 * 4 = 1000 toggles = 1 sec
	mv	k, #4
	ret

SetupTone2
	setb	SysStat.3	; tone 2
	mv	i, #25	; toggle audio pin every 25 interrupts for 600 Hz-ish tone
	mv	j, #150	; 150 * 4 = 600 toggles = 1 sec
	mv	k, #4
	ret

Randy G Glenn Says:

Yes, folks, I know there's an error here - a fairly colossal error, that causes any timed loops to run about 256 times longer than the comments would indicate. 'twill be fixed.