Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

comparing multiple button presses

Status
Not open for further replies.
I guess I asked the wrong question (nothing new)
I want to startthe game using only 2 buttons then 3 buttons all the way to a total of 8 but only have a total of actual 5 buttons.
can I eliminate #OPTION and then use INDEX as byte and increment INDEX as the player gets a match.
Player gets a no match then INDEX = INDEX-1
never delt with #OPTION
 
I want to start the game using only 2 buttons then 3 buttons all the way to a total of 8 but only have a total of actual 5 buttons.

I don't know what you mean by total of 8 but only total of 5 buttons.

Do you want to increase the number of challenges, one at a time, up to 8 but only use buttons 1-5?
If so, then set
Code:
// this option limits the max numbers of PORTB keys used, from 1-8
// if the ICSP programmer is connected, limit this to 6 (no RB6 or RB7)
#option MAX_NUM_KEYS = 5

// this option controls the max length of the challenge sequence, 
// from 1-23 chars (button presses)
#option MAX_SEQ_LENGTH = 8

If not, you'll have to describe what you mean by "total of actual 5 buttons".
 
the board has only 5 buttons
play starts with only 2 led/buttons for the first challenge then with a match the challenge is 3 buttons in the challenge. Incrementing the number of buttons in the challenge. With a no match then the number of buttons decrementing.
play progresses where the challenge has 8 buttons/leds
the #option has me scratching my head. I looked in the help file but?
 
'#option' is a compile-time directive that's used to change things around without having to rewrite the entire code.
It's similar to a '#define' in C (which is also supported).

You've been using '#option' statements for years.
If you want to get an explanation then look in the pdf manual, not the help file.
It'll be gobbledygook I'm sure.

Here's a version that uses 5 buttons, starts with 2 challenges and increases them up to 8.
It doesn't decrement them if you don't match, it starts a new game.
I'll leave that change up to you... I've done enough.
 

Attachments

  • simon.bas
    9.8 KB · Views: 189
AFTER PONDERING THE Simon code (post#44)
I found where Tumbleweed inserted code to increase the sequence amount.
Now to decrimanate with a wrong match
Code:
seq = 1
While (seq < START_SEQ)          //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   n = GetRND()                // get a new random number from 1 to MAX_KEY
   AddToString(challenge, n)   // add it to the challenge string
   seq = seq + 1
End While
 
I found where Tumbleweed inserted code to increase the sequence amount.
Now to decrimanate with a wrong match
That code you pointed out has nothing to do with increasing the sequence amount.
That's handled by the "for seq = START_SEQ to MAX_SEQ" loop.

You said you wanted to start off with two challenge sequences for some reason.
That code fills in up to START_SEQ entries before the challenge loop starts.
If you want to start off with two, then change
Code:
const START_SEQ = 1
to
Code:
const START_SEQ = 2

Looking at it again, that code you pointed out should really be after the "do forever" while true statement
so it gets executed at the beginning of every new game
 
Last edited:
Making lots of progress and adding little changes to smooth the game progress out.
Am contemplating sending a game to 90 year old sister in law that is in assisted living. Maybe "personalize" with her name.
learning bits and pieces of what and why Tumbleweed built code the way he did. Any suggestions or comments welome.
Code:
//progran notes

//add a routine to increase / decrease speed of challenge
//added a s_core routine to track players progress
//s-core equals 0 after each game maaybe?





Program simon

Device = 18F43K22
Clock = 16

// int osc and IO pin libraries
Include "intosc.bas"
#option DIGITALIO_INIT = true       // automatically call setalldigital
Include "setdigitalio.bas"

// lcd
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
Include "LCD.bas"
Include "convert.bas"

// this option enables playing a tone when an led is turned on
// set it false to exclude using tone.bas
#option USE_TONE_LIB = true
#if (USE_TONE_LIB)
  Include "TONE2.bas"
#endif

// hardware
Dim SWT0 As PORTB.0
Dim SWT1 As PORTB.1
Dim SWT2 As PORTB.2
Dim SWT3 As PORTB.3
Dim SWT4 As PORTB.4
Dim SWT5 As PORTB.5
Dim SWT6 As PORTB.6
Dim SWT7 As PORTB.7
Dim SW_PORT As PORTB

Dim LED0 As PORTC.0
Dim LED1 As PORTC.1
Dim LED2 As PORTC.2
Dim LED3 As PORTC.3
Dim LED4 As PORTC.4
Dim LED5 As PORTC.5
Dim LED6 As PORTC.6
Dim LED7 As PORTC.7
Dim LED_PORT As PORTC
Dim INDEX As Byte
Dim note As Word
Dim NOTE_PAUSE As Word
Dim grats As Word
Dim wrong As Word
dim S_core as byte
// this option limits the max numbers of PORTB keys used, from 1-8
// if the ICSP programmer is connected, limit this to 6 (no RB6 or RB7)
#option MAX_NUM_KEYS = 5
#if Not (MAX_NUM_KEYS in (1 to 8))
  #error MAX_NUM_KEYS, "MAX_NUM_KEYS must be 1-8"
#endif
Const MAX_KEY = MAX_NUM_KEYS
Const KEY_MASKS(9) As Byte = ($00, $01, $03, $07, $0F, $1F, $3F, $7F, $FF)

// this option controls the max length of the challenge sequence,
// from 1-23 chars (button presses)
#option MAX_SEQ_LENGTH = 4
#if Not (MAX_SEQ_LENGTH in (1 to 23))
  #error MAX_SEQ_LENGTH, "MAX_SEQ_LENGTH must be 1 to 23"
#endif
Const MAX_SEQ = MAX_SEQ_LENGTH

// set initial number of sequences in the challenge
// normally, this would be set to 1, but if you want to start with
// a different number of challenges change this (up to MAX_SEQ)
Const START_SEQ = 1

//-------------------------------------
// subroutines and functions
//-------------------------------------

// given an ledno 1-8, turn it off (0) or on (>0)
// if ledno = 0 then set them all on or off
// optional: play a note when an led is turned on (#option USE_TONE_LIB=true)
Sub SetLED(ledno As Byte, onoff As Byte)   
  #if (USE_TONE_LIB)
    Dim note As Word

    Select (ledno)
        Case 0
            If (onoff > 0) Then
                onoff = $FF
            EndIf               
            LED_PORT = onoff
           // note = NOTE_PAUSE
        Case 1
            LED0 = onoff
            note = NOTE_A4
        Case 2
            LED1 = onoff
            note = NOTE_D4
        Case 3
            LED2 = onoff
            note = NOTE_C5
        Case 4
            LED3 = onoff
            note = NOTE_F4
        Case 5
            LED4 = onoff
            note = NOTE_A6
        Case 6
            LED5 = onoff
            note = NOTE_B4
        Case 7
            LED6 = onoff
            note = NOTE_A4
        Case 8
            LED7 = onoff
            note = NOTE_D4
    End Select           

    // if led is turned on then play the note for 500ms
    If (onoff > 0) Then
        tone2.play(note, 500)
        tone2.wait()
    EndIf
  #else   // don't use tone library
    Select (ledno)
        Case 0
            If (onoff > 0) Then
                onoff = $FF
            EndIf               
            LED_PORT = onoff
        Case 1
            LED0 = onoff
        Case 2
            LED1 = onoff
        Case 3
            LED2 = onoff
        Case 4
            LED3 = onoff
        Case 5
            LED4 = onoff
        Case 6
            LED5 = onoff
        Case 7
            LED6 = onoff
        Case 8
            LED7 = onoff
    End Select           
  #endif  // (USE_TONE_LIB)
End Sub

// flash an LED on-off with delay
Sub FlashLED(ledno As Byte)
    Const FLASH_DELAY = 500
    
    SetLED(ledno, 1)            // turn on the corresponding LED
    DelayMS(FLASH_DELAY)        // wait a bit...
    SetLED(ledno, 0)            // and turn led off
    DelayMS(FLASH_DELAY)
End Sub

// wait for a keypress and return key number, 1-8
// turns on LED while the key is pressed
Function GetKey() As Byte
    Const KEY_BOUNCE_DELAY = 50     // msec delay for key bounce
    
    // wait for a key press
    Repeat
        If (SWT0 = 0) Then
            result = 1
        ElseIf (SWT1 = 0) Then
            result = 2
        ElseIf (SWT2 = 0) Then
            result = 3
        ElseIf (SWT3 = 0) Then
            result = 4
        ElseIf (SWT4 = 0) Then
            result = 5
        ElseIf (SWT5 = 0) Then
            result = 6
        ElseIf (SWT6 = 0) Then
            result = 7
        ElseIf (SWT7 = 0) Then
            result = 8
        Else    // no valid key press
            result = 0
        EndIf
        // limit response to the max number of supported keys
        If (result > MAX_KEY) Then
            result = 0
        EndIf
    Until (result <> 0)
    
    // turn on the corresponding LED
    SetLED(result, 1)
    
    // now wait for all keys to be released
    While ((SW_PORT And KEY_MASKS(MAX_KEY)) <> KEY_MASKS(MAX_KEY))
        DelayMS(KEY_BOUNCE_DELAY)
    End While
    
    // wait a bit for any release bounce
    DelayMS(KEY_BOUNCE_DELAY)

    // turn off the LED
    SetLED(result, 0)
End Function

// given a number n=1-8, convert it to a char and append it to the string s
Sub AddToString(ByRef s As String, n As Byte)
    Dim ch As Char
    
    ch = n + Byte("0")
    s = s + ch
End Sub

// given a string s and an index n=1-8, get the char value
Function GetFromString(ByRef s As String, n As Byte) As Byte
    Dim ch As Char
    
    // convert n to 0-based index
    If (n > 0) Then
        n = n - 1
    EndIf       
    // get nth char from string
    ch = s(n)
    // convert numeric char to value 0-9
    result = Byte(ch) - Byte("0")
End Function

// random number generator
// based on https://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.PseudoRandomNumberGenerator
Dim LCG,GLFSR As Byte
Sub initRND(reseed As Byte=0)
    If (reseed = 0) Then
        GLFSR = 1
        LCG = 84
    EndIf
    LCG = reseed
    GLFSR = LCG Xor $55     // just making the start values very different - not really important
    If (GLFSR = 0) Then     // except that GLFSR must not be zero
        GLFSR=1
    EndIf
End Sub

Sub C_grats()   //use a counter to select congrat
    Select (grats)
           Case 0 WriteAt(1,1,"GOOD JOB")
           Case 1 WriteAt(1,1,"GREAT JOB")
           Case 2 WriteAt(1,1,"DOING GREAT!")
           Case 3 WriteAt(1,1,"KEEP IT UP")
           Case 4 WriteAt(1,1,"COLLEGE BOUND? ")
           Case 5 WriteAt(1,1,"COLLEGE GRAD!")
           Case 6 WriteAt(1,1,"  ANOTHER ")
                  WriteAt(2,1,"  EINSTEIN?")
          
     End Select
     DelayMS(2000)       //time to read
     grats = grats +1
     If grats = 7 Then
     grats = 0
    // MAX_NUM_KEYS = MAX_NUM_KEYS +1
     End If
 End Sub
 
 Sub IN_sults()
     cls
     Select(wrong)
           Case 0 WriteAt(1,1,"DID YOU EVEN")
                  WriteAt(2,1,"GO TO SCHOOL?")
                  delayms(2000)
                  
           Case 1 WriteAt(1,1,"ARE YOU BLIND?")
                  delayms(2000)
           Case 2 WriteAt(1,1,"THIS GAME IS")
                  WriteAt(2,1,"TWO HARD 4 U!")
                  delayms(2000)
                  
           Case 3 WriteAt(1,1,"KEEP IT UP")
                  WriteAt(2,1,"YOU COULD BE")
                  DelayMS(1000)
                  WriteAt(1,1,"PRESINDENT")
                  delayms(2000)
                    
           Case 4 WriteAt(1,1," A DOG  ")
                  WriteAt(2,1,"COULD DO BETTER!")
                  delayms(2000)
                  
           Case 5 WriteAt(1,1,"2ND GRADE GRAD!")
                  WriteAt(2,1,"DON'T THINK SO")
                  delayms(2000)
                  
           Case 6 WriteAt(1,1,"  ANOTHER ")
                  WriteAt(2,1,"  EINSTEIN?")
                  delayms(2000)
                  CLS
                  WriteAt(1,1,"YOU WISH! ")
     End Select
     DelayMS(2000)        //time to read
    // wrong = wrong +1
     //If wrong = 7 Then
     //wrong = 0
     'End If
  End Sub     

Function GetRND() As Byte
    // init rand (just in case)
    If (LCG = 0) Or (GLFSR = 0) Then
        initRND()
    EndIf
    
    // LCG
    LCG=(7*LCG+17)

    // Galios LFSR
    If (GLFSR And 1) = 1 Then
        GLFSR = GLFSR Xor 135 '135 is the tap
        GLFSR = (GLFSR >> 1) Or $80
    Else
        GLFSR = (GLFSR >> 1)
    EndIf
    result = GLFSR Xor LCG

    // for our application we want a number from 1 to MAX_KEY
    result = (result Mod MAX_KEY) + 1
End Function


//-------------------------------------
// main program variables
//-------------------------------------
Dim challenge As String     // challenge pattern
Dim user As String          // user input
Dim i As Byte
Dim n As Byte
Dim seq As Byte

//-------------------------------------
// start of main program
//-------------------------------------
main:
// init hdw
TRISC = 0               // LED port - all outputs
TRISB = $FF             // SW port - all inputs
WPUB = $FF              // PORTB pullup mask - all PORTB pullups
INTCON2.bits(7) = 0     // RBPU bit - turn on pullups

// init tone module (if enabled)
#if (USE_TONE_LIB)
  tone2.init()
#endif

//turn off all LEDs
SetLED(0, 0)

// wait for user to press a key
// use the response time to seed the random number generator
LCG = 0
LCD.WriteAt(1,1,"press key 1-", MAX_KEY+Byte("0"), "...")
While ((SW_PORT And KEY_MASKS(MAX_KEY)) = KEY_MASKS(MAX_KEY))
    LCG = LCG + 1
End While
initRND(LCG)

// check to see if there are initial seqs required
// if so then add random numbers to the challenge string
seq = 1
While (seq < START_SEQ)          //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   n = GetRND()                // get a new random number from 1 to MAX_KEY
   AddToString(challenge, n)   // add it to the challenge string
   seq = seq + 1
   //add a decremewnting routine with wrong answera
End While
initRND(LCG)
tone2.init()
NOTE_PAUSE = 0
grats = 0
wrong = 0
S_core = 8
// do forever
While true
    // start off with both strings empty
    challenge = ""
    user = ""
    
    //turn off all LEDs
    SetLED(0, 0)
    
    For seq = START_SEQ To MAX_SEQ
        // get a random number and add it to the challenge string
        n = GetRND()                // get a new random number from 1 to MAX_KEY
        AddToString(challenge, n)   // add it to the challenge string

        // display the challenge seq so far
        LCD.Cls
        LCD.WriteAt(1,1,"challenge ", DecToStr(seq), "...")
        DelayMS(1000)
        LCD.WriteAt(1,1,"  COPY BUTTON   ")
        LCD.WriteAt(2,1,"    SEQUENCE    ")
        DELAYMS(2000)
        For i = 1 To seq
            n = GetFromString(challenge, i)
            FlashLED(n)                 // show rand number using LEDs
        Next
            
        // get user response
        LCD.Cls
        LCD.WriteAt(1,1,"enter ", DecToStr(seq), " keys...")
        DELAYMS(500)
        user = ""
        For i = 1 To seq
            n = GetKey()                // get user keypress (shown on LEDs)
            AddToString(user, n)        // add it to the user response
            // compare the current char as we go
            // if no match then end this game and start a new one
            If (GetFromString(challenge, i) <> n) Then   //checks for match
                SetLED(0, 1)                // turn on all leds
                delayms(1000)
                setled(0,0)                  //turn off all leds
                //S_core = S_core - 1          //when score hits 3 then game ends
                Break                   //leave this routine
            EndIf
            
        Next
      
  //add a S_core here so after 3 attempts the play ends       
        
        
          
        // compare the two strings to show match
        LCD.Cls
        If (challenge = user) Then
        C_grats()
        s_core = s_core+1      //ADD FOR CORRECT PRESS
        cls
            LCD.WriteAt(1,1," VERY GOOD LETS  ")
            LCD.WriteAt(2,1,"  ADD SOME KEYS  ")
            cls
            LCD.WriteAt(1,1,"score : ",dectostr( S_core))
            delayms(3000)
            //increment number of keys
        Else
            LCD.WriteAt(1,1,"WRONG MATCH")
            wrong = wrong + 1
            IN_sults()
            DelayMS(2000)
            S_core = s_core - 1   //decrimate SCORE FOR WRONG PRESS
            cls
            'LCD.WriteAt(1,1,"score : ",dectostr( S_core))
            delayms(3000)
            
        EndIf
        'DelayMS(2000)
    Next
    
    // this game is over
    // show the strings (up to 10 chars on a 16x LCD)
    LCD.Cls
    'LCD.WriteAt(1,1,"gen : ", challenge)
    'LCD.WriteAt(2,1,"user: ", user)
    'DelayMS(2000)
    LCD.WriteAt(1,1,"score : ",dectostr( S_core))
    delayms(3000)
End While

End Program
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top