HomeArticlesProjectsBlogContact
Articles
Simon P5
Colin Mitchell
Colin Mitchell
Make sure to subscribe to our newsletter and be the first to know the news.

Program for PIC16F628 micro

  • P1
  • P2
  • P3
  • P4
  • P5

The following sets up the ports and the equates for the notes for the tunes:

;****************************************************************
;* MEMORY GAME - Simon              *
;****************************************************************

;Port A definitions
PORTA_CONFIG1   equ 0xFD    ;1111 1110
            0       ;not used
BUZZER      equ 1   ;buzzer output
            2       ;not used
            3       ;not used
            4       ;not used

;Port B definitions
PORTB_CONFIG1   equ 0x0F    ;bit7: out,out,out,out,in,in,in,in :bit0
KEY_RED         equ 0       ;red key input   - bit0
KEY_GREEN       equ 1       ;green key input  - bit1
KEY_YELLOW      equ 2       ;yellow key input - bit2
KEY_ORANGE      equ 3       ;orange key input - bit3
LED_RED         equ 4       ;red led output   - bit4
LED_GREEN       equ 5       ;green led output - bit5
LED_YELLOW      equ 6       ;yellow led output- bit6
LED_ORANGE      equ 7       ;orange led output- bit7

RAM_START       equ 0x20    ;start of global variable ram
LINE_OFFSET     equ 0x3A    ;start of step memory in ram area

RECORD_STEPS    equ 0x00    ;eeprom address for step record

                ;Data for song notes

                ;Value = 10's of microseconds
                ;octave 1
NOTE_G0         equ D'255'  ;196 Hz
NOTE_A0         equ D'227'  ;220 Hz
NOTE_B0         equ D'202'  ;247 Hz

;octave 2
NOTE_C1         equ D'191'  ;262 Hz
NOTE_D1         equ D'170'  ;294 Hz
NOTE_E1         equ D'152'  ;330 Hz
NOTE_F1         equ D'143'  ;349 Hz
NOTE_G1         equ D'128'  ;392 Hz
NOTE_A1         equ D'114'  ;440 Hz
NOTE_B1         equ D'101'  ;494 Hz

;octave 3
NOTE_C2         equ D'95'   ;524 Hz
NOTE_D2         equ D'85'   ;588 Hz
NOTE_E2         equ D'76'   ;660 Hz
NOTE_F2         equ D'72'   ;698 Hz
NOTE_G2         equ D'64'   ;784 Hz
NOTE_A2         equ D'57'   ;880 Hz
NOTE_B2         equ D'51'   ;988 Hz

;octave 4
NOTE_C3         equ D'48'   ;1048 Hz
NOTE_D3         equ D'43'   ;1176 Hz
NOTE_E3         equ D'38'   ;1320 Hz
NOTE_F3         equ D'36'   ;1396 Hz
NOTE_G3         equ D'32'   ;1568 Hz
NOTE_A3         equ D'28'   ;1760 Hz
NOTE_B3         equ D'25'   ;1976 Hz

                ;length of notes
;"tempo"(nomalized) length is set in SoundPlay function by timerb
LENGTH_SEMIBREVE        equ 0x20    ;tempo
LENGTH_MINIM            equ 0x10    ;tempo/2
LENGTH_CROTCHET         equ 0x08    ;tempo/4
LENGTH_QUAVER           equ 0x04    ;tempo/8
LENGTH_SEMIQUAVER       equ 0x02    ;tempo/16
LENGTH_DEMISEMIQUAVER   equ 0x01    ;tempo/32


SONG_HEY_JUDE_LEN   equ D'68'   ;total No of notes + lengths
SONG_OSUSANA_LEN    equ D'108'
SONG_DEATHMARCH_LEN equ D'22'

KEY_RED_SOUND       equ NOTE_C2
KEY_GREEN_SOUND     equ NOTE_E2
KEY_YELLOW_SOUND    equ NOTE_G2
KEY_ORANGE_SOUND    equ NOTE_B2

Program for PIC16F628 micro (Simon.asm)

The following contains all the comments for the Simon program:

Note: __Config 3F18h covers the following:

_CP_off & _LVP_off & _PWRTE_off & Boden_off & _WDT_off & _IntRC_osc_I/O

where:
CP = code protection
LVP = low-voltage programming
PWRTE = power-up timer
Boden = Brown-out detector
WDT = watchdog timer
IntRC_osc_I/O = internal RC for 4MHz - all pins for in-out

You can simply write: __Config 3F18h
or:

__Config _CP_off & _LVP_off & _PWRTE_off & Boden_off & _WDT_off & _IntRC_osc_I/O

or select the boxes in IC Prog at the time of burning the chip.
In all cases the chip will get burnt with the correct configuration value and when it is copied, the copy will automatically have the correct configuration value.

;****************************************************************
;* Memory Game - SIMON              *
;****************************************************************

    list p=16f628,          ;microcontroller

    include "p16F628.inc"   ;registers for F628
    include "simon628.inc"  ;Simon definitions for F628

__Config 3F18h

;****************************************************************
;global variables
;Files for PIC16F628 start at 0x20
;****************************************************************
timera          equ 0x2c    ;general purpose timer
timerb          equ 0x2d    ;general purpose timer
timerc          equ 0x2e    ;general purpose timer
timerd          equ 0x2f    ;general purpose timer
note_select     equ 0x30    ;selection of note
note_tone       equ 0x31    ;frequency of note
note_length     equ 0x32    ;length of note
note_tempo      equ 0x33    ;tempo of song
random          equ 0x34    ;random number
key             equ 0x35    ;key last pressed
column_w        equ 0x36    ;write pointer in sequence table X
line_w          equ 0x37    ;write pointer in sequence table Y
column_r        equ 0x38    ;read pointer in sequence table X
line_r          equ 0x39    ;read pointer in sequence table Y
steps0104       equ 0x3a    ;step memory
steps0508       equ 0x3b    ;step memory
steps0912       equ 0x3c    ;step memory
steps1316       equ 0x3d    ;step memory
steps1720       equ 0x3e    ;step memory
steps2124       equ 0x3f    ;step memory
steps2528       equ 0x40    ;step memory
steps2932       equ 0x41    ;step memory
steps3336       equ 0x42    ;step memory
steps3740       equ 0x43    ;step memory
steps4144       equ 0x44    ;step memory
steps4548       equ 0x45    ;step memory
steps4952       equ 0x46    ;step memory
steptemp        equ 0x47    ;temporary step memory
stepsgood       equ 0x48    ;number of successful steps by player

;****************************************************************
;reset vector
;****************************************************************
reset:  org 0x00            ;reset vector address
    goto    Begin           ;start program execution


Begin:  org     0x06        ;start of program
    goto    start
;****************************************************************
; Data tables for Songs
;****************************************************************
SongHeyJude:
    addwf   pcl,f           ;jump forward according to W value
    retlw   NOTE_G1         ;Hey
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E1         ;jude
    retlw   LENGTH_MINIM
    retlw   NOTE_E1         ;don't
    retlw   LENGTH_QUAVER
    retlw   NOTE_G1         ;make
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;it
    retlw   LENGTH_QUAVER
    retlw   NOTE_D1         ;bad,
    retlw   LENGTH_MINIM
    retlw   NOTE_D1         ;take
    retlw   LENGTH_QUAVER
    retlw   NOTE_E1         ;a
    retlw   LENGTH_QUAVER
    retlw   NOTE_F1         ;sad
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2         ;song
    retlw   LENGTH_MINIM
    retlw   NOTE_C2         ;and
    retlw   LENGTH_QUAVER
    retlw   NOTE_B1         ;make
    retlw   LENGTH_QUAVER
    retlw   NOTE_G1         ;it
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;bet-
    retlw   LENGTH_QUAVER
    retlw   NOTE_G1         ;ter.
    retlw   LENGTH_MINIM
    retlw   NOTE_G1         ;Re-
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;mem-
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;ber
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A1         ;to
    retlw   LENGTH_QUAVER
    retlw   NOTE_D2         ;let
    retlw   LENGTH_SEMIQUAVER
    retlw   NOTE_C2         ;her
    retlw   LENGTH_CROTCHET
    retlw   NOTE_B1         ;in
    retlw   LENGTH_QUAVER
    retlw   NOTE_C2         ;to
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;your
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G1         ;heart,
    retlw   LENGTH_MINIM
    retlw   NOTE_C1         ;then
    retlw   LENGTH_QUAVER
    retlw   NOTE_D1         ;you
    retlw   LENGTH_QUAVER
    retlw   NOTE_E1         ;can
    retlw   LENGTH_QUAVER
    retlw   NOTE_A1         ;start
    retlw   LENGTH_MINIM
    retlw   NOTE_G1         ;to
    retlw   LENGTH_QUAVER
    retlw   NOTE_F1         ;make
    retlw   LENGTH_QUAVER
    retlw   NOTE_E1         ;it
    retlw   LENGTH_QUAVER
    retlw   NOTE_C1         ;bet-
    retlw   LENGTH_QUAVER
    retlw   NOTE_C1         ;ter.
    retlw   LENGTH_MINIM

SongOSusana:
    addwf   pcl,f           ;jump forward according to W value
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_QUAVER
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_QUAVER
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_MINIM
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_QUAVER
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_MINIM
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_F2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_F2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_MINIM
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_QUAVER
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_A2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_G2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_MINIM
    retlw   NOTE_D2
    retlw   LENGTH_QUAVER
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_D2
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C2
    retlw   LENGTH_SEMIBREVE

SongDeathMarch:
    addwf   pcl,f   ;jump forward according to W value
    retlw   NOTE_C1
    retlw   LENGTH_MINIM
    retlw   NOTE_C1
    retlw   LENGTH_QUAVER
    retlw   NOTE_C1
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C1
    retlw   LENGTH_QUAVER
    retlw   NOTE_C1
    retlw   LENGTH_CROTCHET
    retlw   NOTE_E1
    retlw   LENGTH_QUAVER
    retlw   NOTE_D1
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C1
    retlw   LENGTH_QUAVER
    retlw   NOTE_C1
    retlw   LENGTH_CROTCHET
    retlw   NOTE_B0
    retlw   LENGTH_CROTCHET
    retlw   NOTE_C1
    retlw   LENGTH_MINIM

;****************************************************************
;Name : Start
;Description : set-up ports A and B
;****************************************************************
Start:  MOVLW 07    ;to disable the comparators
    MOVWF 0x1F      ;file 1F is the CMCON file
    bsf status,rp0  ;select bank1 register



    movlw PORTA_CONFIG1     ;porta configuration
    movwf 0x05
    movlw PORTB_CONFIG1     ;portb configuration
    movwf 0x06
    movlw 0x81          ;Fosc/4;No prescaler
    movwf 0x81          ;Timer configuration in option register
    bcf status,rp0      ;select bank0 registers



NewGame:
    clrf    porta       ;turn off status leds
    clrf    portb       ;turn off all leds
    movlw   RAM_START   ;clear global variables
    movwf   fsr
S1: clrf    indf
    incf    fsr,f
    btfss   fsr,6
    goto    S1
    movf    line_w,w        ;initialise step memory base
    addlw   LINE_OFFSET     ;put 3Ah into file 37h at beginning
    movwf   line_w
    call    ClearRecord     ;clear record steps?
    call    Introduction    ;introductory song & calibration

;****************************************************************
;Name       : Mainloop
;Description    :
;****************************************************************
Mainloop:
    call    MakeStep        ;create a new step & add it to sequence
    call    ShowSequence    ;show sequence on LEDs
    call    GetUserSequence ;player's sequence (result returned in W)
                            ;W=1 - correct, W=0 - wrong
    xorlw   1               ;is player's sequence correct?
    btfss   status,z        ;yes - ignore next instruction
    goto    SequenceBad     ;no - it's wrong!
    incf    stepsgood,f     ;another successful step by player
    call    Delay150
    call    Delay150
    call    Delay150
    movf    line_w,w        ;max sequence reached (52 steps)?
    xorlw   D'52'
    btfss   status,z
    goto    Mainloop        ;no - do another step
    movf    column_w,w
    xorlw   D'3'
    btfss   status,z
    goto    Mainloop        ;no - do another step
    goto    SequenceRecord  ;yes - max sequence correct!


;****************************************************************
;Name       : ClearRecord
;Description    : allows the player to clear the current step
;       : record. Player must press one of the keys
;       : at power-on for EEPROM to be set to zero
;****************************************************************
ClearRecord:
    movf    portb,w         ;test for a key press
    andlw   0x0f            ;mask keys
    xorlw   0x00            ;are any keys being pressed?
    btfsc   status,z        ;yes - skip next instruction
    return                  ;no - return!
    movlw   RECORD_STEPS    ;clear step record in EEPROM
    movwf   eeadr
    clrf    eedata
    bsf     status,rp0      ;select bank1
    bsf     eecon1,wren     ;enable write
    movlw   0x55            ;unlock codes
    movwf   eecon2
    movlw   0xaa
    movwf   eecon2
    bsf     eecon1,wr       ;write begins
    bcf     eecon1,wren     ;disable further writes
Crec:   btfsc   eecon1,wr   ;wait to write complete
    goto    Crec
    bcf     status,rp0      ;select bank0
    movlw   0x02
    movwf   note_tempo
    call    SoundRisingRocket   ;cleared record indication
    return

;****************************************************************
;Name       : Introduction
;Description    : plays the introductory "hey jude" song until
;       : one of the keys is pressed.
;Inputs     : none
;****************************************************************
Introduction:
    clrf    note_select     ;beginning of "hey jude" song
Intr1:  incf    steptemp,f
    movf    steptemp,w
    andlw   0x03
    movwf   random
    call    Delay150
    call    ShowLed         ;show it on leds
    movlw   0x10
    movwf   note_tempo      ;speed of song
    movf    note_select,w   ;get next "hey jude" note
    call    SongHeyJude     ;returned in W
    movwf   note_tone
    incf    note_select,f
    movf    note_select,w   ;get length of note
    call    SongHeyJude
    movwf   note_length
    call    SoundPlay       ;play music
    clrf    portb           ;turn all leds off
    incf    note_select,f   ;select next note
    movf    note_select,w
    xorlw   SONG_HEY_JUDE_LEN   ;end of song?
    btfsc   status,z        ;no - skip next instruction
    clrf    note_select     ;yes - play it again from beginning
    movf    portb,w         ;test for a key press
    andlw   0x0f            ;mask keys
    xorlw   0x00            ;are any keys being pressed?
    btfsc   status,z        ;yes - skip next instruction
    goto    Intr1           ;no - keep playing music!
    movlw   0x02
    movwf   note_tempo
    call    SoundRisingRocket   ;start new game indication
    return                  ;start new game

;****************************************************************
;Name       : SoundPlay
;Description    : plays a tone on the buzzer
;Inputs     : note_tone - frequency of the tone
;       : note_length - length of note
;       : note_tempo - speed of song
;****************************************************************
SoundPlay:
    clrf    timerc          ;initialise timer
Sp1:    movf    timerc,w
    xorwf   note_length,w   ;end of note?
    btfsc   status,z        ;no - skip next instruction
    return                  ;yes - exit function
    movf    note_tempo,w
    movwf   timerb
Sp2:    movf    note_tone,w ;frequency
    bsf     porta,BUZZER    ;high time
    call    SoundDelay
    bcf     porta,BUZZER    ;low time
    call    SoundDelay
    decfsz  timerb,f
    goto    Sp2
    incf    timerc,f
    goto    Sp1

;****************************************************************
;Name       : SoundDelay
;Description    : a delay used whenever sound
;       : must be produced on the piezo diaphragm. The W register
;       : contains the number of cycles to wait (in 10's
;       : of microseconds.
;Inputs     : W - contains the note to be played
;       : ie. W=191, delay==1,91msec
;****************************************************************
SoundDelay:
    movwf   timera
Sd1:    nop
    nop
    nop
    nop
    nop
    nop
    nop
    decfsz  timera,f
    goto    Sd1
    return

;****************************************************************
;Name       : SoundRisingRocket
;Description    : rising rocket sound effect
;Inputs     : note_tempo - speed of rocket
;Outputs    : none
;****************************************************************
SoundRisingRocket:
    clrf    note_tone       ;make tone=255 - start
    comf    note_tone,f     ;with lowest frequency
Srr1:   movlw   LENGTH_DEMISEMIQUAVER
    movwf   note_length
    call    SoundPlay
    decfsz  note_tone,f     ;do a "rising" sound
    goto    Srr1
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    CALL    Delay150
    return

;****************************************************************
;Name       : MakeRandom
;Description    : reads the PIC's timer register at various
;       : "random" intervals caused by the player
;Inputs     : pressing one of the keys.
;Outputs        : random number will be 0, 1, 2, 3
;****************************************************************
MakeRandom:
    movf    tmr0,w
    andlw   0x03    ;mask all but bit0 and bit1
    movwf   random  ;move random number into file 34h
    return

;****************************************************************
;Name       : MakeStep
;Description    : gets a random number and stores it into the
;       : next available position in table.
;****************************************************************
MakeStep:
    call    MakeRandom  ;ascertain random number
    movf    line_w,w    ;get current line
    movwf   fsr         ;pointer to next available memory
    bcf status,c        ;initialise carry
    movf    column_w,w  ;get current column
    xorlw   0
    BTFSC   STATUS,Z
    GOTO    GCol0       ;column=0 - don't shift
    xorlw   0x01
    BTFSC   STATUS,Z
    GOTO    GCol1       ;column=1 - shift random 2 times
    XORLW   0x03
    BTFSC   STATUS,Z
    GOTO    GCol2       ;column=2 - shift random 4 times
    rlf random,f        ;column=3 - shift random 6 times
    rlf random,f
GCol2:  rlf random,f
    rlf random,f
GCol1:  rlf random,f
    rlf random,f
GCol0:  movf    indf,w  ;get current memory byte of table
    iorwf   random,w    ;merge new random number into table
    movwf   indf        ;restore in sequence table
    incf    column_w,f  ;update column
    btfss   column_w,2  ;end of this memory byte in table?
    return              ;no - return
    clrf    column_w    ;yes - select next memory byte in table
    incf    line_w,f
    return

;****************************************************************
;Name       : ShowSequence
;Description    : displays the step sequence that the player
;       : has to remember and repeat.
;****************************************************************
ShowSequence:
    clrf    column_r        ;begin at start of step sequence
    movlw   LINE_OFFSET
    movwf   line_r
Ss1:    movf    line_r,w
    movwf   fsr
    movf    indf,w
    movwf   steptemp
    movf    column_r,w      ;get current column
    xorlw   0
    BTFSC   STATUS,Z
    GOTO    SCol0           ;column=0 - don't shift
    xorlw   0x01
    BTFSC   STATUS,Z
    GOTO    SCol1           ;column=1 - shift random 2 times
    XORLW   0x03
    BTFSC   STATUS,Z
    GOTO    SCol2           ;column=2 - shift random 4 times
    rrf steptemp,f          ;column=3 - shift random 6 times
    rrf steptemp,f
SCol2:  rrf steptemp,f
    rrf steptemp,f
SCol1:  rrf steptemp,f
    rrf steptemp,f
SCol0:  movf    steptemp,w  ;get current memory byte of table
    andlw   0x03            ;mask bits 2-7
    movwf   random
    call    ShowStep        ;display LED according to stored value
    call    Delay150        ;wait a little after player
    call    Delay150        ;has pressed a key
    call    Delay150
    incf    column_r,f      ;update column
    btfsc   column_r,2      ;overflow?
    goto    Colov1          ;yes
Ss2:    movf    column_r,w  ;no
    xorwf   column_w,w      ;column pointers the same?
    btfss   status,z
    goto    Ss1             ;no - at least another step to show
    movf    line_r,w        ;yes
    xorwf   line_w,w        ;reached the end of sequence?
    btfsc   status,z        ;no - jump next instruction
    return                  ;yes - sequence complete!
    goto    Ss1             ;at least another step to show
Colov1: clrf    column_r
    incf    line_r,f
    goto    Ss2

;****************************************************************
;Name       : ShowStep
;Description    : turns on one of the LEDs and beeps according to
;       : the random number & level of difficulty
;Inputs     : random - random number
;Outputs    : none
;****************************************************************
ShowStep:
    call    ShowLed     ;show random number on led
    movwf   note_tone   ;ShowLed returns with beep value in W
    movlw   LENGTH_SEMIBREVE
    movwf   note_length
    movlw   0x10        ;easy level
    btfss   porta,LEVEL ;get level of difficulty
    movlw   0x01        ;hard level
    movwf   note_tempo  ;speed of beep
    call    SoundPlay   ;play button beep
    clrf    portb       ;turn all leds off
    return

;****************************************************************
;Name       : ShowLed
;Description    : turns on one of the LEDs according to the random
;       : number & prepares W with tone value
;Inputs     : random - random number
;Outputs    : W - value of tone frequency
;****************************************************************
ShowLed:
    movf    random,w        ;get random number
    xorlw   0
    BTFSC   STATUS,Z
    goto    ShowRed         ;random=0
    xorlw   0x01
    BTFSC   STATUS,Z
    GOTO    ShowGreen       ;random=1
    xorlw   0x03
    BTFSC   STATUS,Z
    GOTO    ShowYellow      ;random=2
    goto    ShowOrange      ;random=3

ShowRed:
    bsf portb,LED_RED       ;turn on red led
    retlw   KEY_RED_SOUND   ;tone frequency

ShowGreen:
    bsf portb,LED_GREEN     ;turn on green led
    retlw   KEY_GREEN_SOUND ;tone frequency

ShowYellow:
    bsf portb,LED_YELLOW    ;turn on yellow led
    retlw   KEY_YELLOW_SOUND    ;tone frequency

ShowOrange:
    bsf portb,LED_ORANGE    ;turn on orange led
    retlw   KEY_ORANGE_SOUND    ;tone frequency

;****************************************************************
;Name       : GetUserSequence
;Description    : checks the player's sequence to that required
;Inputs     : none
;Outputs    : W=0 : player has made a mistake
;       : W=1 : player has successfully repeated sequence
;****************************************************************
GetUserSequence:
    clrf    column_r        ;begin at start of step sequence
    movlw   LINE_OFFSET
    movwf   line_r
Us1:    movf    line_r,w
    movwf   fsr
    movf    indf,w
    movwf   steptemp
    movf    column_r,w      ;get current column
    xorlw   0
    BTFSC   STATUS,Z
    GOTO    UCol0           ;column=0 - don't shift
    xorlw   0x01
    BTFSC   STATUS,Z
    GOTO    UCol1           ;column=1 - shift random 2 times
    xorlw   0x03
    BTFSC   STATUS,Z
    GOTO    UCol2           ;column=2 - shift random 4 times
UCol3:  rrf steptemp,f      ;column=3 - shift random 6 times
    rrf steptemp,f
UCol2:  rrf steptemp,f
    rrf steptemp,f
UCol1:  rrf steptemp,f
    rrf steptemp,f
UCol0:  movf    steptemp,w  ;get current memory byte of table
    andlw   0x03            ;mask bits 2-7
    movwf   random

    call    Keypad          ;get player's input - returned in W
                ;W=0 - no key pressed (timeout)
                ;W=1 - player has pressed a key
    xorlw   0               ;did player press a key?
    btfsc   status,z        ;yes - jump next instruction
    retlw   0               ;no - exit function
    movf    key,w           ;compare pressed key with step
    xorwf   random,w        ;is it the same?
    btfss   status,z        ;yes - jump next instruction
    retlw   0               ;no - incorrect, exit function
    incf    column_r,f      ;update column
    btfsc   column_r,2      ;overflow?
    goto    Colov2          ;yes
Us2:    movf    column_r,w  ;no
    xorwf   column_w,w      ;column pointers the same?
    btfss   status,z
    goto    Us1             ;no - at least another step to show
    movf    line_r,w        ;yes
    xorwf   line_w,w        ;reached the end of sequence?
    btfsc   status,z        ;no - jump next instruction
    retlw   1               ;yes - sequence complete!
    goto    Us1             ;at least another step to show

Colov2: clrf    column_r
    incf    line_r,f
    goto    Us2

;****************************************************************
;Name       : Keypad
;Description    : scans the keys for a press and lights up the
;       : corresponding LED and beeps.
;Inputs     : none
;Outputs    : W=0 : key timeout - no key has been pressed
;       : W=1 : key has been pressed
;       : key : 0=red,1=green,2=yellow,3=orange
;****************************************************************
Keypad:
    clrf    key     ;initialise key
    movlw   0x07        ;assume easy level - 5 sec timeout
    btfss   porta,LEVEL ;get level of difficulty
    movlw   0x03        ;hard level - 2 sec timeout
    movwf   timerc
Kp2:    movlw   0xff
    movwf   timerb
Kp1:    movlw   0xff
    movwf   timera

Kwait:  btfsc   portb,KEY_RED
    goto    KeyRed
    btfsc   portb,KEY_GREEN
    goto    KeyGreen
    btfsc   portb,KEY_YELLOW
    goto    KeyYellow
    btfsc   portb,KEY_ORANGE
    goto    KeyOrange
    decfsz  timera,f
    goto    Kwait
    decfsz  timerb,f
    goto    Kp1
    decfsz  timerc,f
    goto    Kp2
    retlw   0               ;player hasn't pressed key!

KeyRed:
    bsf portb,LED_RED   ;turn on red led
    clrf    key     ;key=0
    movlw   KEY_RED_SOUND   ;tone frequency
    goto    Beep1

KeyGreen:
    bsf portb,LED_GREEN ;turn on green led
    bsf key,0       ;key=1
    movlw   KEY_GREEN_SOUND ;tone frequency
    goto    Beep1

KeyYellow:
    bsf portb,LED_YELLOW    ;turn on yellow led
    bsf key,1       ;key=2
    movlw   KEY_YELLOW_SOUND    ;tone frequency
    goto    Beep1

KeyOrange:
    bsf portb,LED_ORANGE    ;turn on orange led
    bsf key,0       ;key=3
    bsf key,1
    movlw   KEY_ORANGE_SOUND    ;tone frequency
Beep1:  movwf   note_tone       ;save tone
    movlw   LENGTH_SEMIBREVE
    movwf   note_length
    movlw   0x03
    movwf   note_tempo      ;speed of beep
Beep2:  call    SoundPlay   ;play button beep
    movf    portb,w         ;test for a key press
    andlw   0x0f            ;mask keys
    xorlw   0x00            ;are any keys being pressed?
    btfss   status,z        ;no - skip next instruction
    goto    Beep2           ;yes - keep beeping!
    clrf    portb           ;turn off all leds
    retlw   1               ;return to calling function


;****************************************************************
;Name       : SequenceBad
;Description    : player has made a mistake - show player the
;       : correct sequence. Test to see if a record has
;       : been made.
;****************************************************************
SequenceBad:
    movlw   0x01
    movwf   note_tempo
    call    SoundRisingRocket
    movlw   0x01
    movwf   note_tempo
    call    SoundRisingRocket
    call    ShowSequence    ;replay proper sequence again
    movlw   0x01
    movwf   note_tempo
    call    SoundRisingRocket
    movlw   0x01
    movwf   note_tempo
    call    SoundRisingRocket
    call    Delay150
    call    Delay150
    call    Delay150
    movlw   RECORD_STEPS    ;get current record from EEPROM
    movwf   eeadr
    bsf status,rp0          ;select bank1
    bsf eecon1,rd           ;read eeprom
    bcf status,rp0          ;select bank0
    movf    eedata,w        ;W=record number of steps
    subwf   stepsgood,w     ;a record sequence (or same)?
    btfsc   status,c        ;no - jump next instruction
    goto    SequenceRecord  ;yes - tell player about it!
    clrf    note_select     ;beginning of song
    movlw   0x10            ;slow
    movwf   note_tempo      ;speed of song
Sb1:    call    Delay150
    movf    note_select,w   ;get next note
    call    SongDeathMarch  ;returned in W
    movwf   note_tone
    incf    note_select,f
    movf    note_select,w   ;get length of note
    call    SongDeathMarch
    movwf   note_length
    call    SoundPlay       ;play music
    incf    note_select,f   ;select next note
    movf    note_select,w
    xorlw   SONG_DEATHMARCH_LEN ;end of song?
    btfss   status,z        ;yes - skip next instruction
    goto    Sb1             ;no - keep playing
    call    Delay150
    call    Delay150
    call    Delay150
    goto    NewGame         ;start new game

;****************************************************************
;Name       : SequenceRecord
;Description    : player has beaten the record, save new step
;       : record in EEPROM and play record tune.
;****************************************************************
SequenceRecord:
    movlw   RECORD_STEPS    ;save new step record in EEPROM
    movwf   eeadr
    movf    stepsgood,w
    movwf   eedata
    bsf     status,rp0      ;select bank1
    bsf     eecon1,wren     ;enable write
    movlw   0x55            ;unlock codes
    movwf   eecon2
    movlw   0xaa
    movwf   eecon2
    bsf     eecon1,wr       ;write begins
    bcf     eecon1,wren     ;disable other writes
Sre1:   btfsc   eecon1,wr   ;wait for "write" to complete
    goto    Sre1
    bcf status,rp0          ;select bank0
    clrf    note_select     ;beginning of song
Sr1:    incf    steptemp,f
    movf    steptemp,w
    andlw   0x03
    movwf   random
    call    Delay150
    call    ShowLed         ;show it on leds
    movlw   0x5             ;fast
    movwf   note_tempo      ;speed of song
    movf    note_select,w   ;get next note
    call    SongOSusana     ;returned in W
    movwf   note_tone
    incf    note_select,f
    movf    note_select,w   ;get length of note
    call    SongOSusana
    movwf   note_length
    call    SoundPlay       ;play music
    clrf    portb           ;turn all leds off
    incf    note_select,f   ;select next note
    movf    note_select,w
    xorlw   SONG_OSUSANA_LEN    ;end of song?
    btfsc   status,z        ;no - skip next instruction
    goto    Sr2             ;yes - end playing
    movf    portb,w         ;test for a key press
    andlw   0x0f            ;mask keys
    xorlw   0x00            ;are any keys being pressed?
    btfsc   status,z        ;yes - skip next instruction
    goto    Sr1             ;no - keep playing music!
    goto    NewGame         ;start new game
Sr2     call    Delay150
    call    Delay150
    call    Delay150
    goto    NewGame         ;start new game

;****************************************************************
;Name       : Delay
;Description    : causes a delay of 150msec with 4MHz crystal!
;****************************************************************
Delay150:
    movlw   0xc3        ;number of wait states
    movwf   timerb
L4: movlw   0xff        ;number of wait states
    movwf   timera
L5: decfsz  timera,f
    goto    L5
    decfsz  timerb,f
    goto    L4
    return

    END

Hex file for Simon PIC16F628:

:020000000628D0
:04000C00D02882076F
:1000100080340834983410349834043480340434F0
:1000200072340434AA341034AA34043498340434B6
:100030008F3408345F3410345F340434653404344E
:100040008034043472340434803410348034043402
:100050007234043472340834723404345534023443
:100060005F340834653404345F3404347234083443
:1000700080341034BF340434AA3404349834043443
:1000800072341034803404348F340434983404349B
:10009000BF340434BF34103482075F341034553415
:1000A00004344C340834403408344034083439348F
:1000B0000834403408344C3408345F341034553438
:1000C00004344C3408344C340834553408345F3428
:1000D0000834553410345F341034553404344C34FF
:1000E0000834403408344034083439340834403457
:1000F00008344C3408345F341034553410344C34E4
:1001000008344C340834553408345F3410344834DF
:10011000083448340834393408343934083439342C
:10012000083440340834403408344C3408345F34E4
:100130000834553410345F341034553404344C349E
:1001400008344034083440340834393408344034F6
:1001500008344C3408345F341034553404344C348F
:1001600008344C34083455340834553408345F347A
:1001700020348207BF341034BF340434BF34083411
:10018000BF340434BF34083498340434AA340834F7
:10019000BF340434BF340834CA340834BF34103494
:1001A00007309F008316FD3085000F3086008130B8
:1001B000810083128601203084008001840A041F9C
:1001C000DD2837083A3EB700F92010215F217C2155
:1001D000C721013A031D2F2AC80A872287228722B6
:1001E0003708343A031DE6283608033A031DE6288B
:1001F000572A06080F39003A0319080000309B00FF
:100200009A0183161C1555309D00AA309D009C1440
:100210001C119C18092983120230B3004B210800DD
:10022000B001C70A47080339B4008722B42110304F
:10023000B30030080720B100B00A30080720B20030
:1002400030218601B00A3008443A0319B00106088B
:100250000F39003A031911290230B3004B2108006D
:10026000AE012E083206031908003308AD0031082C
:100270008514402185104021AD0B3729AE0A312964
:10028000AC000000000000000000000000000000C2
:10029000AC0B41290800B101B1090130B200302195
:1002A000B10B4D2987228722872287228722872226
:1002B00087228722080001080339B40008005B2167
:1002C0003708840003103608003A03197329013AED
:1002D00003197129033A03196F29B40DB40DB40D34
:1002E000B40DB40DB40D000834048000B60A361DF8
:1002F0000800B601B70A0800B8013A30B900390859
:1003000084000008C7003808003A03199329013A0D
:1003100003199129033A03198F29C70CC70CC70C7D
:10032000C70CC70CC70C47080339B400A9218722A2
:1003300087228722B80A3819A62938083606031DED
:100340007F2939083706031908007F29B801B90A3F
:100350009D29B421B1002030B2001030051E0130BB
:10036000B3003021860108003408003A0319BF2980
:10037000013A0319C129033A0319C329C5290616ED
:100380005F3486164C340617403486173334051113
:100390008515B8013A30B900390884000008C70053
:1003A0003808003A0319E029013A0319DE29033A13
:1003B0000319DC29C70CC70CC70CC70CC70CC70C2A
:1003C00047080339B400FA21003A0319003435080C
:1003D0003406031D0034B80A3819F72938083606E0
:1003E000031DCC293908370603190134CC29B8017B
:1003F000B90AEE29B5010730051E0330AE00FF3003
:10040000AD00FF30AC000618122A8618162A06190D
:100410001A2A86191E2AAC0B032AAD0B012AAE0B31
:10042000FF2900340616B5015F30222A86163514DE
:100430004C30222A0617B5144030222A861735146C
:10044000B5143330B1002030B2000330B300302196
:1004500006080F39003A031D272A860101340130AE
:10046000B3004B210130B3004B217C21872287222E
:10047000872200309B0083161C1483121A0848023E
:100480000318572AB0011030B30087223008B92072
:10049000B100B00A3008B920B2003021B00A3008EB
:1004A000163A031D452A872287228722DA28003040
:1004B0009B0048089A0083161C1555309D00AA30F1
:1004C0009D009C141C119C18632A8312B001C70A5A
:1004D00047080339B4008722B4210530B30030083F
:1004E0004C20B100B00A30084C20B2003021860107
:1004F000B00A30086C3A0319832A06080F39003A0B
:100500000319672ADA28872287228722DA28C3304C
:10051000AD00FF30AC00AC0B8B2AAD0B892A080074
:02400E00183F59
:00000001FF

Colin Mitchell

Colin Mitchell

Expertise

electronics
writing
PIC-Chips

Social Media

instagramtwitterwebsite

Related Posts

TODO
Transistor Test
© 2021, All Rights Reserved.

Quick Links

Advertise with usAbout UsContact Us

Social Media