'****************************************************************

'*  Name    : SIMON-Multiplexed-Btns-and-Leds_12F683-4MHzv2.BAS *

'*  Author  : FLOTUL                                            *

'*  Notice  : Copyright (c) 2006 Flotulopex & Co.               *

'*          : All Rights Reserved                               *

'*  Date    : 10.04.2007                                        *

'*  Version : 1.0                                               *

'*  Notes   : version2 - April 2008                             *

'*          :                                                   *

'****************************************************************

 

'SIMON game - Memory skills. Reproduce a LED sequence.

' Sound cannot be used with this PIC because GPIO.3 is Input only (can't be

'  toggled for button read).

'Switch-ON will show-up a "scrolling leds" light-show.

'Pressing a button will start the game at corresponding game speed.

'Three lives.

'After the 3rd fail, leds 3 & 4 will indicate score in Tens and Units.

 

'Version history:

' v2: - sound features deleted

'     - increasing speed game deleted

'     - added pause after btn press to avoid doubble entry

'     - program clean-up

 

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

' Circuitery

'Pn are µC ports.

 

' LEDS (3 ports for 4 Leds)

'     Leds are connected (resistors are needed if not 5V leds are used):

'     P0 - (A)Led0(k) - P1

'     P0 - (k)Led1(A) - P1

'     P2 - (A)Led2(k) - P1

'     P0 - (k)Led3(A) - P1

 

'   Led#  P2  P1  P0

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

'     -  | 0 | 0 | 0

'     0  | 0 | 0 | 1

'     1  | 1 | 1 | 0

'     2  | 1 | 0 | 0

'     3  | 0 | 1 | 1

'    0+2 | 1 | 0 | 1

'    1+3 | 0 | 1 | 0

 

' BUTTONS

'    Two buttons are connected to 1 same pin (example for one button pair):

'    VDD - Button_A (NO) - R2k2 - (C) - 10k - Pn

'    VSS - Button_B (NO) - R2k2 - (C)

 

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

' Fuses

@ DEVICE PIC12F683,FCMEN_OFF

@ DEVICE PIC12F683,IESO_OFF

@ DEVICE PIC12F683,BOD_ON

@ DEVICE PIC12F683,CPD_OFF

@ DEVICE PIC12F683,PROTECT_OFF

@ DEVICE PIC12F683,MCLR_OFF ;enable GPIO.3 as I/O

@ DEVICE PIC12F683,WDT_OFF

@ DEVICE PIC12F683,INTRC_OSC_NOCLKOUT ;Internal oscillator 4MHz

 

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

' Registers   76543210

WPU        = %00000000  'DISABLE Pull-Ups for buttons

OPTION_REG = %10000000  'Disable pull-ups

ANSEL      = %00000000  'Disable Analog I/O

CMCON0     = %00000111  'Comparator is OFF

TRISIO     = %00111000  'Inputs/Outputs

GPIO       = %00000000  'Drive all ports low

 

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

' Port allocation (PIC specific)

Led_P0 var GPIO.0

Led_P1 var GPIO.1

Led_P2 var GPIO.2

Btns01 var GPIO.5

Dirs01 var TRISIO.5

Btns23 var GPIO.4

Dirs23 var TRISIO.4

 

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

' Defines

 

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

' Variables

Value var WORD  'Source for RANDOM #

LedOn var word  'Time for Led is ON

LedOf var word  'Time for Led is OFF

Mem_L var byte  'DATA-Memory location of last stored # (Mem_D)

Mem_D var byte  'DATA Random value

Scre  var byte  'Score value

Speed VAR byte  'Game's speed

Lifes var byte  'You've got 3 lifes

Ctr_A var byte  'General Counter

Ctr_B var byte  'Counter

Ctr_L var byte  'Level Counter

Rand  var byte  'Holds random #

Rand3 var byte  'Holds number in DATA-Memory

Pbtn  var byte  'PressedButton - Holds number to compare pressed button and Rand

'GoSlp var byte  'Goto SLEEP if no Btn is pressed for x minutes

 

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

' Program Init sequence

gosub INIT

goto start

 

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

' Subroutines

LEDS_SEQUENCE:

    for ctr_a = 0 to mem_l   'read Led sequence

        read ctr_a, mem_d    'read Led to light

        gosub LEDS_DECODE    'light-on Led

        PAUSE Ledon          'time Led is switched-on

        GOSUB LEDS_OFF       'switch-off Led

        PAUSE ledof          'wait before next Led

    next   

    value = 0

    return

 

LEDS_DECODE:   

    if Mem_d = 0 then Led_P0 = 1 : Led_P1 = 0 : Led_P2 = 0 'Led0

    if Mem_d = 1 then Led_P0 = 0 : Led_P1 = 1 : Led_P2 = 1 'Led1

    if Mem_d = 2 then Led_P0 = 0 : Led_P1 = 0 : Led_P2 = 1 'Led2

    if Mem_d = 3 then Led_P0 = 1 : Led_P1 = 1 : Led_P2 = 0 'Led3

    return

   

LEDS_OFF:

    Led_P0 = 0 : Led_P1 = 0 : Led_P2 = 0 'All leds OFF

    return 

 

GAME_SEQUENCE:

    PAUSE 300 'give a little time before to continue

    gosub RDM_VALUE

    gosub LEDS_SEQUENCE

    return

 

RDM_VALUE:

    random value

    Rand = (value//4)

    if MEM_L > 2 then read mem_l - 3, Rand3 'Do not allow more than 3 same # in a row

    if Rand3 = Rand then RDM_VALUE          'if same value as 3 before, randomize again

    write mem_l, Rand

    return

 

FAIL:

    for Ctr_A = 1 to lifes

        Led_P0 = 0 : Led_P1 = 1 : Led_P2 = 0 'Led1 + Led3

        PAUSE 100

        GOSUB LEDS_OFF

        PAUSE 150

    next

    return

 

SCORE:

    if Mem_l = 0 then 'If score is 0, "Ready to start" light-show

        for Ctr_A = 0 to 3

            Led_P0 = 1 : Led_P1 = 0 : Led_P2 = 0 'Led0 'gosub led_0

            PAUSE 50

            Led_P0 = 0 : Led_P1 = 1 : Led_P2 = 1 'Led1 'gosub led_1

            PAUSE 50

            Led_P0 = 0 : Led_P1 = 0 : Led_P2 = 1 'Led2 'gosub led_2

            PAUSE 50

            Led_P0 = 1 : Led_P1 = 1 : Led_P2 = 0 'Led3 'gosub led_3

            pause 50

            GOSUB LEDS_OFF

        next

    else

        if mem_l > 9 then

            Scre = Mem_l DIg 1  'Read Tens (dizaines 10-90)

            For Ctr_A = 1 to Scre

                Led_P0 = 0 : Led_P1 = 0 : Led_P2 = 1''gosub led_2

                PAUSE 80

                GOSUB LEDS_OFF

                PAUSE 180

            next

            PAUSE 500  'PAUSE between digits to display

        endif

        Scre = Mem_l DIg 0  'Read Units (unités 1-9)

        if Scre <> 0 then

            For Ctr_A = 1 to Scre

                Led_P0 = 1 : Led_P1 = 1 : Led_P2 = 0''gosub led_3

                PAUSE 120

                GOSUB LEDS_OFF

                PAUSE 280

            next

        endif

    endif

    return

 

READ_BTNS:

    Dirs01 = 0   'Make the port an Output

    Btns01 = 1   'Set it High

    Dirs01 = 1   'Make the port an Input

    if Btns01 = 0 then pbtn = 0 : return

    Dirs01 = 0   'Make the port an Output

    Btns01 = 0   'Set it Low

    Dirs01 = 1   'Make the port an Input

    if Btns01 = 1 then pbtn = 1 : return

    Dirs23 = 0   'Make the port an Output

    Btns23 = 1   'Set it High

    Dirs23 = 1   'Make the port an Input

    if Btns23 = 0 then pbtn = 2 : return

    Dirs23 = 0   'Make the port an Output

    Btns23 = 0   'Set it Low

    Dirs23 = 1   'Make the port an Input

    if Btns23 = 1 then pbtn = 3 : return

    pbtn = 9

    return

 

INIT:

    Ledon = 320 '@ 4MHz, 1000 = 1 second

    LedoF = 180

    Mem_L = 0

    Scre  = 0

    Lifes = 3    'you've got 3 Lifes

    ctr_a = 0

    Ctr_L = 0

    Speed = 0

    return

 

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

' Program

START:   

    gosub READ_BTNS   'Read the buttons

    if Pbtn < 4 then  'Start game

        PAUSE 400

        gosub INIT    'Reset after an ended play

        gosub SCORE   'Nice - one more 'light-show' before 1st row - not essential

        gosub GAME_SEQUENCE

        goto main

    endif

    if value >= 20000 then   'acts like a general "elapsed time" counter as well as "seed"

        value = 0

        gosub SCORE ' "Ready to start" LED blinking if score is 0

    endif

    value = value + 1 'To change the "seed" for random #

    goto START

 

MAIN:

    gosub READ_BTNS

    if pbtn < 4 then

        if Ctr_L <= mem_l then

            read Ctr_L, mem_d        'read Rand# in DATA memory location

            if pbtn = Mem_d then     'if OK, light-up LED and continue

                gosub LEDS_DECODE

                while Pbtn < 4       'leave Led ON while btn pressed (nice)

                    gosub READ_BTNS

                wend

                pause 100            'don't allow too fast consecutive button press

                GOSUB LEDS_OFF

                Ctr_L = Ctr_L + 1

                if Ctr_L > mem_l then   'repeated sequence is finished OKAY!

                    Ctr_L = 0           'reset counter

                    mem_l = mem_l + 1   'add one step to game

                    gosub GAME_SEQUENCE 'continue game

                endif

            else                    'you miss...

                Mem_d = pbtn        'light-up the led you are selecting currently

                gosub LEDS_DECODE

                while Pbtn < 4      'leave Led ON while btn pressed (nice)

                    gosub READ_BTNS

                wend

                pause 100           'don't allow too fast consecutive button press

                GOSUB LEDS_OFF

                Lifes = Lifes - 1   '"fail"

                if lifes = 0 then

                    lifes = 3       'end of the game: make it blink 3 times!

                    PAUSE 200       'before showing fail indication

                    gosub FAIL

                    value = 17000   'display score timer (the closer to max value of Value, the quicker)

                    goto START

                endif   

                PAUSE 200           'before showing fail indication

                Gosub FAIL

                PAUSE 200           'before replay led sequence

                gosub LEDS_SEQUENCE

                Ctr_L = 0

            endif

        endif    

    endif

    value = value + 1           'To change the "seed" for random #

    Goto MAIN

end

       

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

' Test

'DISPLAY:

'    serout2 PORTC.3, 52465,["Mem_L=", dec mem_l, "  Speed=", dec Speed ,13] '300bps

'    serout2 PORTC.3, 52465,["LedOn=", dec Ledon, "  LedOf=", dec ledof, 10 ,13] '300bps

'    return