Home

Hari Says...

This is my version of the game "Simon Says".
It starts with the above display. Pressing one of the four buttons starts the game.
The game would playback longer and longer sequence of notes, and the player must repeat them. If player can repeat the whole sequence, a winning song is played, otherwise a loosing song is played. Score is displayed on the LCD and updated throughout the game.

The circuit is extremely simple, pins 0 through 3 are connected to the four switches.
Pins 4 through 7 are connected to the LEDs. Pin 14 is connected to the LCD, and pin 15 is connected to the piezo electric speaker.

 
I was going to make this a permanent game, but lost interest in the game after I got it prototyped. I had fun building it and not much fun playing the game. So, the Stamp would soon become part of a new project.

'
' "Hari Says..." - a game like "Simon Says"
'
' Hari Wiguna, July 2000
'


'--- Beep parameters ---
kSpeakerPin	CON	15
kDuration	CON	100	' x miliSeconds
kFreq4	CON	659
kFreq3	CON	587
kFreq2	CON	500
kFreq1	CON	440
kPause	CON	200


'--- Array parameters ---
kWords	CON	0	' (see below)
kWords1	CON	1	' kWords1 * 8 = the length of the beep sequence


'--- Game Speed ---
kGameSpeed	CON	255	' Starting game speed

'--- LCD ---
kLCDPin	CON	14
N9600	con	$4054
Esc		con	254
CLR		con	1


'--- Variables ---
gArr		VAR	WORD(kWords1)	' Where beep sequence is stored
tRnd		VAR	WORD			' Utility random#
tNote	VAR	WORD			' Frequency of beep
i		VAR	BYTE			' Utility bytes
j		VAR	BYTE			'
k		VAR	BYTE			'
gWhich	VAR	BYTE			' Which beep to play (0..3)
tBeeps	VAR	BYTE			' How many beeps to play
tWords	VAR	BYTE			' How many words to play
tLoop	VAR	BYTE
gButton	VAR	BYTE
gPause	VAR	WORD
inNum	VAR	BYTE


'-----------------------------------------------------------------

Start:
gPause = kGameSpeed

'--- Clear LCD ---
SEROUT kLCDPin, N9600, [Esc,CLR]
PAUSE 500
  
'--- PIC Says ---
SEROUT kLCDPin, N9600, [Esc,128,"Hari Says..."]
SEROUT kLCDPin, N9600, [Esc,192,"Press any button"]

'--- Randomize Random# sequence while waiting for button press ---
WaitForStart:
  RANDOM tRnd
  gButton = INS & %00001111
  IF gButton = %00001111 THEN WaitForStart

  GOSUB GameStartMusic

  '--- Save random numbers (Words) in array gArr() ---
  FOR i = 0 TO kWords
    RANDOM tRnd
    gArr(i) = tRnd
  NEXT


  '--- Playback the sequence repeatedly, each time playing one more note ---
  For tBeeps = 0 TO (kWords1 * 8) - 1
    GOSUB ShowScore
    GOSUB PlaySequence
    PAUSE 1000
    if gPause < 20 Then ItsFastEnough
      gPause = gPause - 10
    ItsFastEnough:
  NEXT

PlayWinSong:
  SEROUT kLCDPin, N9600, [Esc,CLR]
  FREQOUT kSpeakerPin, 100, 900
  PAUSE 50
  FREQOUT kSpeakerPin, 1000, 900
  SEROUT kLCDPin, N9600, [Esc,128,"*** SWEET!!! ***"]
GOTO Start

GameEnd:
  FREQOUT kSpeakerPin, 1000, 300
  SEROUT kLCDPin, N9600, [Esc,CLR]
  PAUSE 500
  SEROUT kLCDPin, N9600, [Esc,128,"** GAME OVER! **"]
  GOSUB ShowScore
  PAUSE 3000
GOTO Start


'-----------------------------------------------------------------

ShowScore:
  SEROUT kLCDPin, N9600, [Esc,192,"Score: "]
  inNum = tBeeps
  GOSUB ShowNum
RETURN


ShowNum:
  SEROUT kLCDPin, N9600, [48 + (inNum / 10)]
  SEROUT kLCDPin, N9600, [48 + (inNum // 10)]
RETURN


inDuration	VAR	WORD
inNote	VAR	WORD

'--- Game Start Music ---
GameStartMusic:

  '--- Clear LCD ---
  inDuration = 100
  inNote = 700
  SEROUT kLCDPin, N9600, [Esc,CLR]
  GOSUB FlashAll
  SEROUT kLCDPin, N9600, [Esc,128,"Get SET..."]
  PAUSE 1000

  SEROUT kLCDPin, N9600, [Esc,CLR]
  GOSUB FlashAll
  SEROUT kLCDPin, N9600, [Esc,128,"READY..."]
  PAUSE 1000

  inDuration = 600
  SEROUT kLCDPin, N9600, [Esc,128,"*** PLAY ***"]
  GOSUB FlashAll
  PAUSE 1000
RETURN


FlashAll:
  HIGH 4
  HIGH 5
  HIGH 6
  HIGH 7
  FREQOUT kSpeakerPin, inDuration, inNote
  LOW 4
  LOW 5
  LOW 6
  LOW 7
RETURN

'--- Playback random numbers two bits at a time ---
' Input: tBeeps = number of beeps to play
PlaySequence:
  tWords = tBeeps / 8
  FOR tLoop = 0 to 1 ' 0=play, 1=wait for buttons
    FOR i = 0 TO tWords
      tRnd = gArr(i)
      IF i = tWords THEN LastWord
      k = 7
PlayWord:
      FOR j = 0 TO k
        gWhich = tRnd & 3 ' Get lowest two bits
        IF tLoop = 0 THEN JustBeep
          GOSUB WaitForButton
          IF gWhich <> gButton THEN GameEnd
JustBeep:
        GOSUB BeepAndBlink
        tRnd = tRnd >> 2 ' Shift down two bits (clobbering the one we've just used)
      NEXT
    NEXT
  NEXT
RETURN

LastWord:
  k = tBeeps - (i*8)
GOTO PlayWord


'--- Play tone and blink LED ---
' Input: gWhich (0..3)
BeepAndBlink:
  LOOKUP gWhich, [kFreq1, kFreq2, kFreq3, kFreq4], tNote
  HIGH 4 + gWhich
  FREQOUT kSpeakerPin, kDuration, tNote
  LOW 4 + gWhich
  PAUSE gPause
RETURN


'--- Wait for button press ---
WaitForButton:
  i = 255
KeepWaiting:
  gButton = 0
  IF IN0 = 0 THEN Pressed

  gButton = 1
  IF IN1 = 0 THEN Pressed

  gButton = 2
  IF IN2 = 0 THEN Pressed

  gButton = 3
  IF IN3 = 0 THEN Pressed

  ' Have we waited long enough?
  i = i - 1
  IF i > 0 Then KeepWaiting

  ' If we got here, it means player did not press any button in time.
  gButton = -1
Pressed:
RETURN

Home